<?php

namespace App\Http\Controllers\HRM;

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

class AttendanceController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index(Request $request)
    {
        $companyId = $request->session()->get('company_id');

        // Default to today if no date is provided
        $date = $request->date ? Carbon::parse($request->date) : Carbon::today();

        $query = Attendance::with('employee')
            ->where('company_id', $companyId)
            ->whereDate('date', $date);

        // Apply filters if provided
        if ($request->has('employee_id') && $request->employee_id != '') {
            $query->where('employee_id', $request->employee_id);
        }

        if ($request->has('status') && $request->status != '') {
            $query->where('status', $request->status);
        }

        $attendances = $query->get();

        // Get all employees for the company for the dropdown
        $employees = Employee::where('company_id', $companyId)
            ->where('status', 'active')
            ->get();

        // Check which employees don't have attendance records for today
        $employeesWithoutAttendance = Employee::where('company_id', $companyId)
            ->where('status', 'active')
            ->whereDoesntHave('attendances', function ($query) use ($date) {
                $query->whereDate('date', $date);
            })
            ->get();

        return view('hrm.attendance.index', compact('attendances', 'employees', 'employeesWithoutAttendance', 'date'));
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create(Request $request)
    {
        $companyId = $request->session()->get('company_id');
        $employees = Employee::where('company_id', $companyId)
            ->where('status', 'active')
            ->get();

        return view('hrm.attendance.create', compact('employees'));
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'employee_id' => 'required|exists:employees,id',
            'date' => 'required|date',
            'check_in' => 'nullable|date_format:H:i',
            'check_out' => 'nullable|date_format:H:i',
            'status' => 'required|in:present,absent,late,half_day,on_leave',
            'notes' => 'nullable|string',
        ]);

        if ($validator->fails()) {
            return redirect()->back()
                ->withErrors($validator)
                ->withInput();
        }

        $companyId = $request->session()->get('company_id');

        // Check if employee belongs to the company
        $employee = Employee::findOrFail($request->employee_id);
        if ($employee->company_id != $companyId) {
            abort(403, 'Unauthorized action.');
        }

        // Check if attendance record already exists for this employee and date
        $existingAttendance = Attendance::where('employee_id', $request->employee_id)
            ->where('date', $request->date)
            ->first();

        if ($existingAttendance) {
            return redirect()->back()
                ->with('error', 'Attendance record already exists for this employee on this date.')
                ->withInput();
        }

        // Calculate total hours if both check-in and check-out are provided
        $totalHours = 0;
        $lateMinutes = 0;
        $overtimeMinutes = 0;

        if ($request->check_in && $request->check_out) {
            $checkIn = Carbon::parse($request->date . ' ' . $request->check_in);
            $checkOut = Carbon::parse($request->date . ' ' . $request->check_out);

            // If check-out is before check-in, assume it's the next day
            if ($checkOut < $checkIn) {
                $checkOut->addDay();
            }

            $totalHours = $checkOut->diffInMinutes($checkIn) / 60;

            // Calculate late minutes (assuming work starts at 9:00 AM)
            $workStart = Carbon::parse($request->date . ' 09:00:00');
            if ($checkIn > $workStart) {
                $lateMinutes = $checkIn->diffInMinutes($workStart);
            }

            // Calculate overtime minutes (assuming work ends at 5:00 PM)
            $workEnd = Carbon::parse($request->date . ' 17:00:00');
            if ($checkOut > $workEnd) {
                $overtimeMinutes = $checkOut->diffInMinutes($workEnd);
            }
        }

        $attendance = new Attendance();
        $attendance->company_id = $companyId;
        $attendance->employee_id = $request->employee_id;
        $attendance->date = $request->date;
        $attendance->status = $request->status;
        $attendance->notes = $request->notes;

        if ($request->check_in) {
            $attendance->check_in = Carbon::parse($request->date . ' ' . $request->check_in);
        }

        if ($request->check_out) {
            $attendance->check_out = Carbon::parse($request->date . ' ' . $request->check_out);
        }

        $attendance->total_hours = $totalHours;
        $attendance->late_minutes = $lateMinutes;
        $attendance->overtime_minutes = $overtimeMinutes;
        $attendance->created_by = Auth::id();
        $attendance->save();

        return redirect()->route('hrm.attendance.index', ['date' => $request->date])
            ->with('success', 'Attendance record created successfully.');
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        $attendance = Attendance::with('employee')->findOrFail($id);

        // Check if attendance belongs to the current company
        $companyId = session('company_id');
        if ($attendance->company_id != $companyId) {
            abort(403, 'Unauthorized action.');
        }

        return view('hrm.attendance.show', compact('attendance'));
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit(Request $request, $id)
    {
        $companyId = $request->session()->get('company_id');
        $attendance = Attendance::findOrFail($id);

        // Check if attendance belongs to the current company
        if ($attendance->company_id != $companyId) {
            abort(403, 'Unauthorized action.');
        }

        $employees = Employee::where('company_id', $companyId)
            ->where('status', 'active')
            ->get();

        return view('hrm.attendance.edit', compact('attendance', 'employees'));
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $id)
    {
        $attendance = Attendance::findOrFail($id);

        // Check if attendance belongs to the current company
        $companyId = $request->session()->get('company_id');
        if ($attendance->company_id != $companyId) {
            abort(403, 'Unauthorized action.');
        }

        $validator = Validator::make($request->all(), [
            'date' => 'required|date',
            'check_in' => 'nullable|date_format:H:i',
            'check_out' => 'nullable|date_format:H:i',
            'status' => 'required|in:present,absent,late,half_day,on_leave',
            'notes' => 'nullable|string',
        ]);

        if ($validator->fails()) {
            return redirect()->back()
                ->withErrors($validator)
                ->withInput();
        }

        // Calculate total hours if both check-in and check-out are provided
        $totalHours = 0;
        $lateMinutes = 0;
        $overtimeMinutes = 0;

        if ($request->check_in && $request->check_out) {
            $checkIn = Carbon::parse($request->date . ' ' . $request->check_in);
            $checkOut = Carbon::parse($request->date . ' ' . $request->check_out);

            // If check-out is before check-in, assume it's the next day
            if ($checkOut < $checkIn) {
                $checkOut->addDay();
            }

            $totalHours = $checkOut->diffInMinutes($checkIn) / 60;

            // Calculate late minutes (assuming work starts at 9:00 AM)
            $workStart = Carbon::parse($request->date . ' 09:00:00');
            if ($checkIn > $workStart) {
                $lateMinutes = $checkIn->diffInMinutes($workStart);
            }

            // Calculate overtime minutes (assuming work ends at 5:00 PM)
            $workEnd = Carbon::parse($request->date . ' 17:00:00');
            if ($checkOut > $workEnd) {
                $overtimeMinutes = $checkOut->diffInMinutes($workEnd);
            }
        }

        $attendance->date = $request->date;
        $attendance->status = $request->status;
        $attendance->notes = $request->notes;

        if ($request->check_in) {
            $attendance->check_in = Carbon::parse($request->date . ' ' . $request->check_in);
        } else {
            $attendance->check_in = null;
        }

        if ($request->check_out) {
            $attendance->check_out = Carbon::parse($request->date . ' ' . $request->check_out);
        } else {
            $attendance->check_out = null;
        }

        $attendance->total_hours = $totalHours;
        $attendance->late_minutes = $lateMinutes;
        $attendance->overtime_minutes = $overtimeMinutes;
        $attendance->updated_by = Auth::id();
        $attendance->save();

        return redirect()->route('hrm.attendance.index', ['date' => $request->date])
            ->with('success', 'Attendance record updated successfully.');
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy(Request $request, $id)
    {
        $attendance = Attendance::findOrFail($id);

        // Check if attendance belongs to the current company
        $companyId = $request->session()->get('company_id');
        if ($attendance->company_id != $companyId) {
            abort(403, 'Unauthorized action.');
        }

        $date = $attendance->date;
        $attendance->delete();

        return redirect()->route('hrm.attendance.index', ['date' => $date])
            ->with('success', 'Attendance record deleted successfully.');
    }

    /**
     * Bulk check-in for multiple employees.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function bulkCheckIn(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'employee_ids' => 'required|array',
            'employee_ids.*' => 'exists:employees,id',
            'date' => 'required|date',
            'check_in' => 'required|date_format:H:i',
            'status' => 'required|in:present,late',
        ]);

        if ($validator->fails()) {
            return redirect()->back()
                ->withErrors($validator)
                ->withInput();
        }

        $companyId = $request->session()->get('company_id');
        $date = $request->date;
        $checkIn = Carbon::parse($date . ' ' . $request->check_in);
        $status = $request->status;

        // Calculate late minutes (assuming work starts at 9:00 AM)
        $lateMinutes = 0;
        $workStart = Carbon::parse($date . ' 09:00:00');
        if ($checkIn > $workStart) {
            $lateMinutes = $checkIn->diffInMinutes($workStart);
        }

        foreach ($request->employee_ids as $employeeId) {
            // Check if employee belongs to the company
            $employee = Employee::findOrFail($employeeId);
            if ($employee->company_id != $companyId) {
                continue; // Skip this employee
            }

            // Check if attendance record already exists for this employee and date
            $existingAttendance = Attendance::where('employee_id', $employeeId)
                ->where('date', $date)
                ->first();

            if ($existingAttendance) {
                continue; // Skip this employee
            }

            $attendance = new Attendance();
            $attendance->company_id = $companyId;
            $attendance->employee_id = $employeeId;
            $attendance->date = $date;
            $attendance->check_in = $checkIn;
            $attendance->status = $status;
            $attendance->late_minutes = $lateMinutes;
            $attendance->created_by = Auth::id();
            $attendance->save();
        }

        return redirect()->route('hrm.attendance.index', ['date' => $date])
            ->with('success', 'Bulk check-in completed successfully.');
    }

    /**
     * Bulk check-out for multiple employees.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function bulkCheckOut(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'attendance_ids' => 'required|array',
            'attendance_ids.*' => 'exists:attendances,id',
            'check_out' => 'required|date_format:H:i',
        ]);

        if ($validator->fails()) {
            return redirect()->back()
                ->withErrors($validator)
                ->withInput();
        }

        $checkOut = Carbon::parse($request->check_out);

        foreach ($request->attendance_ids as $attendanceId) {
            $attendance = Attendance::findOrFail($attendanceId);

            // Check if attendance belongs to the current company
            $companyId = $request->session()->get('company_id');
            if ($attendance->company_id != $companyId) {
                continue; // Skip this attendance
            }

            // Skip if already checked out
            if ($attendance->check_out) {
                continue;
            }

            $date = $attendance->date;
            $checkOutDateTime = Carbon::parse($date . ' ' . $request->check_out);

            // If check-in exists, calculate total hours and overtime
            if ($attendance->check_in) {
                $checkIn = $attendance->check_in;

                // If check-out is before check-in, assume it's the next day
                if ($checkOutDateTime < $checkIn) {
                    $checkOutDateTime->addDay();
                }

                $totalHours = $checkOutDateTime->diffInMinutes($checkIn) / 60;

                // Calculate overtime minutes (assuming work ends at 5:00 PM)
                $overtimeMinutes = 0;
                $workEnd = Carbon::parse($date . ' 17:00:00');
                if ($checkOutDateTime > $workEnd) {
                    $overtimeMinutes = $checkOutDateTime->diffInMinutes($workEnd);
                }

                $attendance->total_hours = $totalHours;
                $attendance->overtime_minutes = $overtimeMinutes;
            }

            $attendance->check_out = $checkOutDateTime;
            $attendance->updated_by = Auth::id();
            $attendance->save();
        }

        return redirect()->route('hrm.attendance.index', ['date' => $date ?? Carbon::today()->format('Y-m-d')])
            ->with('success', 'Bulk check-out completed successfully.');
    }

    /**
     * Display monthly attendance report.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function monthlyReport(Request $request)
    {
        $companyId = $request->session()->get('company_id');

        // Default to current month if not provided
        $month = $request->month ? Carbon::parse($request->month . '-01') : Carbon::today()->startOfMonth();
        $startDate = $month->copy()->startOfMonth();
        $endDate = $month->copy()->endOfMonth();

        // Get all employees for the company
        $employeeQuery = Employee::where('company_id', $companyId);

        // Apply department filter if provided
        if ($request->has('department_id') && $request->department_id != '') {
            $employeeQuery->where('department_id', $request->department_id);
        }

        $employees = $employeeQuery->get();

        // Get all attendance records for the month
        $attendances = Attendance::where('company_id', $companyId)
            ->whereBetween('date', [$startDate, $endDate])
            ->get()
            ->groupBy('employee_id');

        // Get all departments for filter dropdown
        $departments = Department::where('company_id', $companyId)->get();

        // Generate calendar days for the month
        $calendarDays = [];
        $currentDay = $startDate->copy();
        while ($currentDay <= $endDate) {
            $calendarDays[] = $currentDay->copy();
            $currentDay->addDay();
        }

        return view('hrm.attendance.monthly_report', compact('employees', 'attendances', 'departments', 'month', 'calendarDays'));
    }
}
