<?php

namespace App\Http\Controllers\Modules\Employee;

use App\Http\Controllers\Controller;
use App\Http\Traits\HasRoleViews;
use App\Models\EmployeeAttendance;
use App\Models\EmployeeDetails;
use App\Services\Employee\AttendanceService;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;
use PhpOffice\PhpSpreadsheet\IOFactory;

/**
 * Unified Attendance Controller
 *
 * Handles employee attendance management for all roles.
 * Views are automatically resolved based on the logged-in user's role.
 */
class AttendanceController extends Controller
{
    use HasRoleViews;

    protected AttendanceService $attendanceService;

    public function __construct(AttendanceService $attendanceService)
    {
        $this->attendanceService = $attendanceService;
    }

    /**
     * Display the attendance management page
     */
    public function index()
    {
        $employees = EmployeeDetails::where('status', EmployeeDetails::STATUS_ACTIVE)->get();
        $attendances = $this->attendanceService->getAll();
        return $this->roleView('employee.employeeattendance', compact('employees', 'attendances'));
    }

    /**
     * Get attendance data for DataTable
     */
    public function list(): JsonResponse
    {
        $data = $this->attendanceService->getAll();
        return response()->json(['data' => $data]);
    }

    /**
     * Store a newly created attendance record
     */
    public function store(Request $request)
    {
        $validated = $request->validate($this->getDailyAttendanceRules());

        try {
            // Get employee name from employee_id
            $employee = EmployeeDetails::where('employee_id', $validated['employee_id'])->first();
            if ($employee) {
                $validated['employee_name'] = $employee->name;
            }

            $this->attendanceService->create($validated);
            return back()->with('success', 'Attendance record added successfully.');
        } catch (\Exception $e) {
            Log::error('Failed to create attendance: ' . $e->getMessage());
            return back()->with('error', 'Failed to create attendance record.');
        }
    }

    /**
     * Get a single attendance record for editing
     */
    public function edit(int $id): JsonResponse
    {
        try {
            $attendance = $this->attendanceService->findByIdOrFail($id);
            return response()->json($attendance);
        } catch (\Exception $e) {
            return response()->json(['error' => 'Record not found'], 404);
        }
    }

    /**
     * Update the specified attendance record
     */
    public function update(Request $request, int $id)
    {
        $validated = $request->validate($this->getDailyAttendanceRules());

        try {
            // Get employee name from employee_id
            $employee = EmployeeDetails::where('employee_id', $validated['employee_id'])->first();
            if ($employee) {
                $validated['employee_name'] = $employee->name;
            }

            $this->attendanceService->update($id, $validated);

            if ($request->ajax() || $request->expectsJson()) {
                return response()->json([
                    'success' => true,
                    'message' => 'Attendance updated successfully',
                ]);
            }

            return back()->with('success', 'Attendance updated successfully.');
        } catch (\Exception $e) {
            Log::error('Failed to update attendance: ' . $e->getMessage());

            if ($request->ajax() || $request->expectsJson()) {
                return response()->json([
                    'success' => false,
                    'message' => 'Failed to update attendance record',
                ], 500);
            }

            return back()->with('error', 'Failed to update attendance record.');
        }
    }

    /**
     * Remove the specified attendance record
     */
    public function destroy(Request $request, int $id)
    {
        if (!$this->isSuperAdmin() && !$this->isManager()) {
            if ($request->ajax() || $request->expectsJson()) {
                return response()->json(['success' => false, 'message' => 'Unauthorized.'], 403);
            }
            abort(403, 'Unauthorized.');
        }

        try {
            $this->attendanceService->delete($id);

            if ($request->ajax() || $request->expectsJson()) {
                return response()->json([
                    'success' => true,
                    'message' => 'Attendance deleted successfully',
                ]);
            }

            return back()->with('success', 'Attendance deleted successfully.');
        } catch (\Exception $e) {
            Log::error('Failed to delete attendance: ' . $e->getMessage());

            if ($request->ajax() || $request->expectsJson()) {
                return response()->json([
                    'success' => false,
                    'message' => 'Failed to delete attendance record',
                ], 500);
            }

            return back()->with('error', 'Failed to delete attendance record.');
        }
    }

    /**
     * Import attendance from Excel
     */
    public function import(Request $request)
    {
        $request->validate([
            'import_file' => 'required|file|mimes:xlsx,xls',
        ]);

        $file = $request->file('import_file');

        try {
            $spreadsheet = IOFactory::load($file->getRealPath());
            $sheetData = $spreadsheet->getActiveSheet()->toArray(null, true, true, true);

            $successCount = 0;
            $errorCount = 0;

            foreach (array_slice($sheetData, 1) as $row) {
                try {
                    EmployeeAttendance::create([
                        'employee_name' => $row['A'],
                        'employee_id' => $row['B'],
                        'gender' => $row['C'],
                        'date_of_birth' => $row['D'],
                        'date_of_joining' => $row['E'],
                        'department' => $row['F'],
                        'designation' => $row['G'],
                        'days_worked' => $row['H'],
                        'sundays_eligible' => $row['I'],
                        'holidays' => $row['J'],
                        'leave_enjoyed' => $row['K'],
                        'total_paid_days' => $row['L'],
                        'absent' => $row['M'],
                        'first_shifts' => $row['N'],
                        'night_shifts' => $row['O'],
                        'ot_hours' => $row['P'],
                        'shortage_hours' => $row['Q'],
                    ]);
                    $successCount++;
                } catch (\Exception $e) {
                    $errorCount++;
                    Log::warning('Attendance import row failed: ' . $e->getMessage());
                }
            }

            $message = "{$successCount} attendance records imported.";
            if ($errorCount > 0) {
                $message .= " {$errorCount} records failed.";
            }

            return back()->with('success', $message);
        } catch (\Exception $e) {
            Log::error('Attendance import failed: ' . $e->getMessage());
            return back()->with('error', 'Failed to import: ' . $e->getMessage());
        }
    }

    /**
     * Get attendance by month
     */
    public function getByMonth(Request $request): JsonResponse
    {
        $monthYear = $request->input('month_year');
        $attendances = $this->attendanceService->getByMonth($monthYear);

        return response()->json(['data' => $attendances]);
    }

    /**
     * Get validation rules for bulk/monthly import
     */
    protected function getValidationRules(): array
    {
        return [
            'employee_name' => 'required|string|max:255',
            'employee_id' => 'required|string|max:100',
            'gender' => 'required|in:Male,Female,Other',
            'date_of_birth' => 'required|date',
            'date_of_joining' => 'required|date',
            'department' => 'required|string|max:255',
            'designation' => 'required|string|max:255',
            'days_worked' => 'required|integer|min:0',
            'sundays_eligible' => 'required|integer|min:0',
            'holidays' => 'required|integer|min:0',
            'leave_enjoyed' => 'required|integer|min:0',
            'total_paid_days' => 'required|integer|min:0',
            'absent' => 'required|integer|min:0',
            'first_shifts' => 'required|integer|min:0',
            'night_shifts' => 'required|integer|min:0',
            'ot_hours' => 'required|integer|min:0',
            'shortage_hours' => 'required|integer|min:0',
        ];
    }

    /**
     * Get validation rules for daily attendance (punch in/out)
     */
    protected function getDailyAttendanceRules(): array
    {
        return [
            'employee_id' => 'required|string|max:100',
            'date' => 'required|date',
            'check_in' => 'nullable|date_format:H:i',
            'check_out' => 'nullable|date_format:H:i',
            'break_out' => 'nullable|date_format:H:i',
            'break_in' => 'nullable|date_format:H:i',
        ];
    }
}
