<?php

namespace App\Http\Controllers\SuperAdmin;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\EmployeeAttendance;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use Illuminate\Support\Facades\Log;
use PhpOffice\PhpSpreadsheet\Shared\Date as ExcelDate;
use Carbon\Carbon;
use App\Models\EmployeeDetails;
use App\Models\EmployeeLeave;

class SuperAdminEmployeeAttendanceController extends Controller
{
    /**
     * Display a listing of the resource.
     */
    public function index(Request $request)
    {
        $employees = EmployeeDetails::all();
        $query = EmployeeAttendance::orderByDesc('date');

        if ($request->has('date') && $request->date != '') {
            $query->whereDate('date', $request->date);
        } else {
             $query->whereDate('date', now()->format('Y-m-d'));
        }

        $attendances = $query->get();
        // View expects 'attendances' and 'employees' (for modal)
        // Original index passed 'data' -> need to align view. 
        // View I edited uses $attendances.
        return view('superadmin.employee.employeeattendance', compact('employees', 'attendances'));
    }

    public function attendanceMatrix(Request $request)
    {
        // ... (Keep existing matrix logic)
        // Defaults to current month if not set
        $month = $request->input('month', date('Y-m'));
        $startDate = \Carbon\Carbon::parse($month . '-01');
        $endDate = $startDate->copy()->endOfMonth();
        $employees = EmployeeDetails::orderBy('employee_id')->get();
    
        // Get all dates in the month
        $dates = [];
        for ($d = $startDate->copy(); $d->lte($endDate); $d->addDay()) {
            $dates[] = $d->toDateString();
        }
    
        // Prepare data: $matrix[employee_id][date] = status
        $matrix = [];
        foreach ($employees as $emp) {
            $attendance = EmployeeAttendance::where('employee_id', $emp->employee_id)
                ->whereBetween('date', [$startDate->toDateString(), $endDate->toDateString()])
                ->get()
                ->keyBy('date');
            $leaves = EmployeeLeave::where('employee_id', $emp->id)
                ->where('status', 'Approved')
                ->where(function ($q) use ($startDate, $endDate) {
                    $q->whereBetween('leave_from', [$startDate, $endDate])
                      ->orWhereBetween('leave_to', [$startDate, $endDate]);
                })->get();
    
            foreach ($dates as $date) {
                $status = 'Absent';
                if (isset($attendance[$date])) {
                    $status = 'Present';
                }
                foreach ($leaves as $leave) {
                    if ($date >= $leave->leave_from && $date <= $leave->leave_to) {
                        $status = strtoupper($leave->leave_type) === 'LOP' ? 'LOP' : $leave->leave_type;
                        break;
                    }
                }
                $matrix[$emp->employee_id][$date] = $status;
            }
        }
    
        return view('superadmin.employee.attendance_matrix', compact('employees', 'dates', 'matrix', 'month'));
    }

    public function import(Request $request)
    {
        // ... (Keep existing import logic) ...
        \Log::info('Attendance import started.');
        $file = $request->file('import_file');
    
        if (!$file) {
            \Log::error('No file uploaded.');
            return back()->with('error', 'No file uploaded.');
        }
    
        try {
            $spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($file);
            $sheetData = $spreadsheet->getActiveSheet()->toArray(null, true, true, true);
        } catch (\Exception $e) {
            \Log::error('Spreadsheet load error: '.$e->getMessage());
            return back()->with('error', 'Failed to read file.');
        }
    
        // Helper to validate time (HH:MM, HH:MM:SS, or with AM/PM)
        // (Function nesting issue in replace? Define closure or keep as is if valid PHP 7+)
        // Better to inline or method, but preserving existing structure if it works.
        // It was defined inside method in original file.
        $parseTime = function($time) {
            $time = trim($time ?? '');
            if (!$time) return null;
            try {
                return \Carbon\Carbon::parse($time);
            } catch (\Exception $e) {
                \Log::error('Time parse error: '.$e->getMessage()." [Time: $time]");
                return null;
            }
        };
    
        $imported = 0;
        $skipped = 0;
    
        foreach (array_slice($sheetData, 1) as $rowNum => $row) {
        // Skip header or empty rows
        if (empty($row['B']) || strtoupper(trim($row['B'])) === 'DATE') {
            Log::info("Row $rowNum skipped: Empty or header row.");
            $skipped++;
            continue;
        }
    
        $dateValue = $row['B'];
        $date = null;
    
        // Try to convert Excel serial date
        if (is_numeric($dateValue)) {
            try {
                $dateObj = ExcelDate::excelToDateTimeObject($dateValue);
                $date = $dateObj->format('Y-m-d');
            } catch (\Exception $e) {
                Log::error("Row $rowNum skipped: Date serial parse failed (Value: '{$dateValue}')");
                $skipped++;
                continue;
            }
        } else {
            // Try to parse as a string
            try {
                $date = \Carbon\Carbon::parse($dateValue)->format('Y-m-d');
            } catch (\Exception $e) {
                Log::error("Row $rowNum skipped: Date string parse failed (Value: '{$dateValue}')");
                $skipped++;
                continue;
            }
        }
    
    
            // Parse times safely
            $checkIn   = $parseTime($row['F'] ?? null);
            $breakOut  = $parseTime($row['H'] ?? null);
            $breakIn   = $parseTime($row['J'] ?? null);
            $checkOut  = $parseTime($row['L'] ?? null);
    
            $totalWorkingMinutes = 0;
            if ($checkIn && $checkOut) {
                if ($breakOut && $breakIn) {
                    $beforeBreak = $breakOut->diffInMinutes($checkIn);
                    $afterBreak = $checkOut->diffInMinutes($breakIn);
                    $totalWorkingMinutes = $beforeBreak + $afterBreak;
                } else {
                    $totalWorkingMinutes = $checkOut->diffInMinutes($checkIn);
                }
            }
            $totalWorkingHours = round($totalWorkingMinutes / 60, 2);
            $requiredHours = 9;
            $otHours = $totalWorkingHours > $requiredHours ? round($totalWorkingHours - $requiredHours, 2) : 0;
            $shortageHours = $totalWorkingHours < $requiredHours ? round($requiredHours - $totalWorkingHours, 2) : 0;
    
            // Prepare data to save
            $insertData = [
                'date'           => $date,
                'employee_id'    => $row['C'] ?? null,
                'employee_name'  => $row['D'] ?? null,
                'check_in'       => $row['F'] ?? null,
                'break_out'      => $row['H'] ?? null,
                'break_in'       => $row['J'] ?? null,
                'check_out'      => $row['L'] ?? null,
                'working_hours'  => $totalWorkingHours,
                'ot_hours'       => $otHours,
                'shortage_hours' => $shortageHours,
            ];
    
            \Log::info("Inserting row $rowNum:", $insertData);
    
            try {
                \App\Models\EmployeeAttendance::create($insertData);
                $imported++;
            } catch (\Exception $e) {
                \Log::error("DB Insert error at row $rowNum: ".$e->getMessage(), $insertData);
                $skipped++;
                continue;
            }
        }
    
        \Log::info("Attendance import finished: Imported $imported, Skipped $skipped");
    
        return back()->with('success', "$imported attendance records imported, $skipped skipped.");
    }

    public function store(Request $request)
    {
        $request->validate([
            'employee_id' => 'required',
            'date' => 'required|date',
            'check_in' => 'nullable', 
            'check_out' => 'nullable',
        ]);

        $employee = EmployeeDetails::where('employee_id', $request->employee_id)->first();
        if (!$employee) {
             // Fallback if ID is ID not employee_id
             $employee = EmployeeDetails::find($request->employee_id);
        }

        // Calculate Hours
        $checkIn = $request->check_in ? \Carbon\Carbon::parse($request->check_in) : null;
        $checkOut = $request->check_out ? \Carbon\Carbon::parse($request->check_out) : null;
        $breakOut = $request->break_out ? \Carbon\Carbon::parse($request->break_out) : null;
        $breakIn = $request->break_in ? \Carbon\Carbon::parse($request->break_in) : null;

        $otHours = 0;
        $shortageHours = 0;
        $workingHours = 0;

        if ($checkIn && $checkOut) {
            $totalMinutes = $checkOut->diffInMinutes($checkIn);
            $breakMinutes = ($breakOut && $breakIn) ? $breakIn->diffInMinutes($breakOut) : 0;
            
            $netMinutes = max(0, $totalMinutes - $breakMinutes);
            $workingHours = round($netMinutes / 60, 2);

            $standardHours = 9; 
            if ($workingHours > $standardHours) {
                $otHours = round($workingHours - $standardHours, 2);
            } elseif ($workingHours < $standardHours) {
                $shortageHours = round($standardHours - $workingHours, 2);
            }
        }

        EmployeeAttendance::create([
            'employee_id' => $request->employee_id,
            'employee_name' => $employee ? $employee->name : 'Unknown',
            'date' => $request->date,
            'check_in' => $request->check_in,
            'break_out' => $request->break_out,
            'break_in' => $request->break_in,
            'check_out' => $request->check_out,
            'ot_hours' => $otHours,
            'shortage_hours' => $shortageHours,
            'working_hours' => $workingHours
        ]);

        return back()->with('success', 'Attendance added successfully.');
    }

    public function edit($id)
    {
        // Not used by Modal approach usually, but route exists
        return response()->json(EmployeeAttendance::find($id));
    }

    public function update(Request $request, $id)
    {
        $attendance = EmployeeAttendance::findOrFail($id);
        
        $request->validate([
            'date' => 'required|date',
        ]);

        $checkIn = $request->check_in ? \Carbon\Carbon::parse($request->check_in) : null;
        $checkOut = $request->check_out ? \Carbon\Carbon::parse($request->check_out) : null;
        $breakOut = $request->break_out ? \Carbon\Carbon::parse($request->break_out) : null;
        $breakIn = $request->break_in ? \Carbon\Carbon::parse($request->break_in) : null;

        $otHours = 0;
        $shortageHours = 0;
        $workingHours = 0;

        if ($checkIn && $checkOut) {
            $totalMinutes = $checkOut->diffInMinutes($checkIn);
            $breakMinutes = ($breakOut && $breakIn) ? $breakIn->diffInMinutes($breakOut) : 0;

            $netMinutes = max(0, $totalMinutes - $breakMinutes);
            $workingHours = round($netMinutes / 60, 2);

            $standardHours = 9; 
            if ($workingHours > $standardHours) {
                $otHours = round($workingHours - $standardHours, 2);
            } elseif ($workingHours < $standardHours) {
                $shortageHours = round($standardHours - $workingHours, 2);
            }
        }

        $attendance->update([
            'employee_id' => $request->employee_id ?? $attendance->employee_id,
            'date' => $request->date,
            'check_in' => $request->check_in,
            'break_out' => $request->break_out,
            'break_in' => $request->break_in,
            'check_out' => $request->check_out,
            'ot_hours' => $otHours,
            'shortage_hours' => $shortageHours,
            'working_hours' => $workingHours
        ]);

        return back()->with('success', 'Attendance updated successfully.');
    }

    public function destroy($id)
    {
        EmployeeAttendance::find($id)->delete();
        return back()->with('success', 'Attendance deleted.');
    }
}
