<?php

namespace App\Http\Controllers\Admin\HR;

use App\Http\Controllers\Controller;
use App\Models\Attendance;
use App\Models\Employee;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class AttendanceController extends Controller
{
    public function index(Request $request)
    {
        // Get selected month or default to current month
        $selectedMonth = $request->get('month', now()->format('Y-m'));

        // Generate list of last 6 months
        $months = [];
        for ($i = 0; $i < 6; $i++) {
            $date = now()->subMonths($i);
            $months[$date->format('Y-m')] = $date->format('F Y');
        }

        // Parse the selected month
        $monthStart = \Carbon\Carbon::parse($selectedMonth . '-01')->startOfMonth();
        $monthEnd = \Carbon\Carbon::parse($selectedMonth . '-01')->endOfMonth();

        // Get current user's employee record if they're an employee
        /** @var \App\Models\User $user */
        $user = Auth::user();
        $employee = Employee::where('user_id', $user->id)->first();

        // Build query
        $query = Attendance::with(['employee.department', 'employee.designation', 'approver'])
            ->whereBetween('date', [$monthStart, $monthEnd]);

        // If user is an employee (not admin), filter to show only their own attendance
        if ($employee && !$user->hasRole('admin')) {
            $query->where('employee_id', $employee->id);
        }

        $attendances = $query->orderBy('date', 'asc')->paginate(15);

        // Calculate summary statistics
        $allAttendances = $query->get(); // Get all for the month without pagination

        $daysWorked = $allAttendances->whereIn('status', ['present', 'late', 'half_day'])->count();
        $offDays = $allAttendances->whereIn('status', ['absent', 'on_leave'])->count();

        // Calculate total OT (total hours - 9 hours per day worked)
        $totalOT = 0;
        foreach ($allAttendances->whereNotNull('total_hours') as $attendance) {
            $totalOT += ($attendance->total_hours - 9);
        }

        $summary = [
            'days_worked' => $daysWorked,
            'off_days' => $offDays,
            'total_ot' => $totalOT,
        ];

        return view('admin.hr.attendance.index', compact('attendances', 'months', 'summary'));
    }

    public function markForm()
    {
        $user = Auth::user();
        $employee = Employee::where('user_id', $user->id)->first();

        if (!$employee) {
            return redirect()->route('admin.dashboard')
                ->with('error', 'You are not linked to an employee record.');
        }

        // Check if attendance already marked today
        $today = now()->toDateString();
        $todayAttendance = Attendance::where('employee_id', $employee->id)
            ->where('date', $today)
            ->first();

        return view('admin.hr.attendance.mark', compact('employee', 'todayAttendance'));
    }

    public function checkAttendance(Request $request)
    {
        $user = Auth::user();
        $employee = Employee::where('user_id', $user->id)->first();

        if (!$employee) {
            return response()->json(['exists' => false, 'is_today' => false]);
        }

        $date = $request->get('date');
        $today = now()->toDateString();

        $attendance = Attendance::where('employee_id', $employee->id)
            ->where('date', $date)
            ->first();

        return response()->json([
            'exists' => $attendance !== null,
            'is_today' => $date === $today
        ]);
    }

    public function store(Request $request)
    {
        $user = Auth::user();
        $employee = Employee::where('user_id', $user->id)->first();

        if (!$employee) {
            return redirect()->route('admin.dashboard')
                ->with('error', 'You are not linked to an employee record.');
        }

        $validated = $request->validate([
            'date' => 'required|date|before_or_equal:today',
            'check_in' => 'required|date_format:H:i',
            'check_out' => 'nullable|date_format:H:i',
            'break_start' => 'nullable|date_format:H:i',
            'break_end' => 'nullable|date_format:H:i',
            'status' => 'required|in:present,absent,late,half_day,on_leave',
            'notes' => 'nullable|string',
        ], [
            'date.before_or_equal' => 'You cannot mark attendance for future dates.',
        ]);

        // Additional validation: Check if attendance already exists for a past date (not today)
        $today = now()->toDateString();
        if ($validated['date'] !== $today) {
            $existingAttendance = Attendance::where('employee_id', $employee->id)
                ->where('date', $validated['date'])
                ->first();

            if ($existingAttendance) {
                return redirect()->back()
                    ->withInput()
                    ->withErrors(['date' => 'You have already marked attendance for this date. Please choose a different date.']);
            }
        }

        $validated['employee_id'] = $employee->id;

        // Handle late-night shifts: if check_out is before check_in (past midnight)
        // For example: check_in = 20:00, check_out = 02:00 means worked until 2 AM next day
        if ($request->filled('check_out')) {
            $checkInTime = \Carbon\Carbon::parse($validated['check_in']);
            $checkOutTime = \Carbon\Carbon::parse($validated['check_out']);

            // If check_out time is less than check_in time, it means next day (past midnight)
            // This handles cases like 08:00 check-in and 02:00 check-out (2 AM next day)
            if ($checkOutTime->lessThan($checkInTime)) {
                // Add 1 day to check_out for calculation purposes
                $checkOutTime->addDay();
            }

            // Calculate break duration if provided
            $breakMinutes = 0;
            if ($request->filled('break_start') && $request->filled('break_end')) {
                $breakStart = \Carbon\Carbon::parse($validated['break_start']);
                $breakEnd = \Carbon\Carbon::parse($validated['break_end']);

                if ($breakEnd->lessThan($breakStart)) {
                    $breakEnd->addDay();
                }

                $breakMinutes = $breakStart->diffInMinutes($breakEnd);
            }

            // Calculate total working hours (excluding break)
            $totalMinutes = $checkInTime->diffInMinutes($checkOutTime) - $breakMinutes;
            $validated['total_hours'] = round($totalMinutes / 60, 2);
        }

        Attendance::updateOrCreate(
            ['employee_id' => $employee->id, 'date' => $validated['date']],
            $validated
        );

        return redirect()->route('admin.hr.attendance.index')
            ->with('success', 'Attendance marked successfully.');
    }

    public function approvalList(Request $request)
    {
        $attendances = Attendance::with(['employee.department', 'employee.designation'])
            ->whereNull('approved_by')
            ->orderBy('date', 'asc')
            ->paginate(15);

        return view('admin.hr.attendance.approve', compact('attendances'));
    }

    public function approve(Request $request, Attendance $attendance)
    {
        $request->validate([
            'notes' => 'nullable|string',
        ]);

        $attendance->update([
            'approved_by' => Auth::id(),
            'approved_at' => now(),
            'notes' => $request->notes ?? $attendance->notes,
        ]);

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