<?php

namespace App\Http\Controllers\Admin;

use App\Enums\UserRole;
use App\Http\Controllers\Controller;
use App\Models\AttendanceRecord;
use App\Models\Department;
use App\Models\Employee;
use App\Models\LeaveRequest;
use App\Models\PerformanceReview;
use App\Models\SalaryAdvance;
use App\Models\TrainingRecord;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;

class HRController extends Controller
{
    protected $accountingService;

    public function __construct(\App\Services\AccountingService $accountingService)
    {
        $this->accountingService = $accountingService;
    }
    public function index()
    {
        $stats = [
            'total_employees' => Employee::count(),
            'active' => Employee::where('status', 'ACTIVE')->count(),
            'departments' => Department::count(),
            'on_leave' => Employee::where('status', 'ON_LEAVE')->count(),
            'pending_reviews' => PerformanceReview::where('status', 'PENDING')->count(),
            'training_this_month' => TrainingRecord::whereMonth('created_at', now()->month)->count(),
        ];

        return view('admin.hr.index', compact('stats'));
    }

    public function employees(Request $request)
    {
        $employees = Employee::query()
            ->with(['user', 'department', 'position'])
            ->when($request->search, function ($q, $search) {
                $q->where(function ($inner) use ($search) {
                    $inner->where('employee_number', 'like', "%{$search}%")
                        ->orWhereHas('user', function ($uq) use ($search) {
                            $uq->where('name', 'like', "%{$search}%")
                                ->orWhere('email', 'like', "%{$search}%");
                        });
                });
            })
            ->when($request->department && $request->department !== 'all', fn ($q) => $q->where('department_id', $request->department))
            ->when($request->status && $request->status !== 'all', fn ($q) => $q->where('status', $request->status))
            ->latest()
            ->paginate(15);

        $departments = Department::orderBy('name')->pluck('name', 'id');

        return view('admin.hr.employees', compact('employees', 'departments'));
    }

    public function employeeStore(Request $request)
    {
        $validated = $request->validate([
            'first_name' => 'required|string|max:255',
            'last_name' => 'required|string|max:255',
            'email' => 'required|email|unique:users,email',
            'phone' => 'nullable|string|max:30',
            'department_id' => 'nullable|exists:departments,id',
            'position_id' => 'nullable|exists:positions,id',
            'hire_date' => 'required|date',
            'salary' => 'required|numeric|min:0',
        ]);

        $user = User::create([
            'name' => trim($validated['first_name'].' '.$validated['last_name']),
            'email' => $validated['email'],
            'phone' => $validated['phone'] ?? null,
            'password' => Hash::make(Str::random(24)),
            'role' => UserRole::Employee->value,
        ]);

        Employee::create([
            'employee_number' => 'EMP-'.now()->format('Ymd').'-'.strtoupper(Str::random(5)),
            'user_id' => $user->id,
            'department_id' => $validated['department_id'] ?? null,
            'position_id' => $validated['position_id'] ?? null,
            'hire_date' => $validated['hire_date'],
            'salary' => $validated['salary'],
            'status' => 'ACTIVE',
            'branch_id' => auth()->user()->branch_id,
        ]);

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

    public function employeeShow($id)
    {
        $employee = Employee::with([
            'user',
            'department',
            'position',
            'attendanceRecords',
            'performanceReviews',
            'trainingRecords',
        ])->findOrFail($id);

        return view('admin.hr.employee-show', compact('employee'));
    }

    public function attendance(Request $request)
    {
        $records = AttendanceRecord::with(['employee.user'])
            ->when($request->date, fn ($q, $d) => $q->whereDate('date', $d))
            ->when(! $request->date, fn ($q) => $q->whereDate('date', today()))
            ->when($request->search, function ($q, $search) {
                $q->whereHas('employee.user', function ($uq) use ($search) {
                    $uq->where('name', 'like', "%{$search}%");
                });
            })
            ->latest('date')
            ->paginate(20);

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

    public function attendanceStore(Request $request)
    {
        $validated = $request->validate([
            'employee_id' => 'required|exists:employees,id',
            'date' => 'required|date',
            'check_in' => 'nullable',
            'check_out' => 'nullable',
            'status' => 'required|in:PRESENT,ABSENT,LATE,HALF_DAY',
        ]);

        AttendanceRecord::updateOrCreate(
            ['employee_id' => $validated['employee_id'], 'date' => $validated['date']],
            $validated
        );

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

    public function performance(Request $request)
    {
        $reviews = PerformanceReview::with('employee.user')
            ->when($request->status && $request->status !== 'all', fn ($q) => $q->where('status', $request->status))
            ->latest('created_at')
            ->paginate(15);

        return view('admin.hr.performance', compact('reviews'));
    }

    public function performanceStore(Request $request)
    {
        $validated = $request->validate([
            'employee_id' => 'required|exists:employees,id',
            'period' => 'required|string|max:255',
            'overall_rating' => 'required|numeric|min:1|max:5',
            'goals' => 'nullable|string',
            'achievements' => 'nullable|string',
            'comments' => 'nullable|string',
        ]);

        $ratingMap = [
            1 => 'UNSATISFACTORY',
            2 => 'NEEDS_IMPROVEMENT',
            3 => 'SATISFACTORY',
            4 => 'GOOD',
            5 => 'EXCELLENT',
        ];

        PerformanceReview::create([
            'employee_id' => $validated['employee_id'],
            'reviewer_id' => auth()->id(),
            'period' => $validated['period'],
            'rating' => $ratingMap[(int) round($validated['overall_rating'])] ?? 'SATISFACTORY',
            'goals' => $validated['goals'] ? [$validated['goals']] : [],
            'achievements' => $validated['achievements'] ? [$validated['achievements']] : [],
            'areas_for_improvement' => [],
            'comments' => $validated['comments'] ?? null,
            'status' => 'DRAFT',
        ]);

        return back()->with('success', 'Performance review created.');
    }

    public function payroll(Request $request)
    {
        $employees = Employee::query()
            ->where('status', 'ACTIVE')
            ->when($request->department && $request->department !== 'all', fn ($q) => $q->where('department_id', $request->department))
            ->with(['user', 'department'])
            ->paginate(20);

        $departments = Department::orderBy('name')->pluck('name', 'id');
        $advances = SalaryAdvance::with('employee.user')->where('status', 'PENDING')->latest()->take(10)->get();

        return view('admin.hr.payroll', compact('employees', 'departments', 'advances'));
    }

    public function payrollStore(Request $request)
    {
        $validated = $request->validate([
            'employee_id' => 'required|exists:employees,id',
            'period' => 'required|string', // e.g. "2024-05"
            'basic_salary' => 'required|numeric',
            'allowances' => 'nullable|numeric',
            'deductions' => 'nullable|numeric',
            'paid_date' => 'required|date',
            'status' => 'required|in:PENDING,PAID',
        ]);

        $allowances = $validated['allowances'] ?? 0;
        $deductions = $validated['deductions'] ?? 0;
        $netSalary = $validated['basic_salary'] + $allowances - $deductions;

        $employee = Employee::find($validated['employee_id']);

        $record = \App\Models\PayrollRecord::create([
            'user_id' => $employee->user_id,
            'period' => $validated['period'],
            'basic_salary' => $validated['basic_salary'],
            'allowances' => $allowances,
            'deductions' => $deductions,
            'net_salary' => $netSalary,
            'status' => $validated['status'],
            'paid_date' => $validated['paid_date'],
        ]);

        // Post to Accounting
        $this->accountingService->postPayrollRecord($record);

        return back()->with('success', 'Payroll processed and posted to accounting.');
    }

    public function departments()
    {
        $departments = Department::withCount('employees')->paginate(15);

        return view('admin.hr.departments', compact('departments'));
    }

    public function departmentStore(Request $request)
    {
        $validated = $request->validate([
            'name' => 'required|string|max:255|unique:departments,name',
            'description' => 'nullable|string',
        ]);

        Department::create($validated);

        return back()->with('success', 'Department created.');
    }

    public function departmentDestroy($id)
    {
        $department = Department::withCount('employees')->findOrFail($id);

        if ($department->employees_count > 0) {
            return back()->with('error', 'Cannot delete a department that still has employees.');
        }

        $department->delete();

        return back()->with('success', 'Department deleted.');
    }

    public function leaves(Request $request)
    {
        $leaves = LeaveRequest::with(['employee.employee.position', 'approver'])
            ->when($request->status && $request->status !== 'all', fn ($q) => $q->where('status', $request->status))
            ->latest()
            ->paginate(15);

        return view('admin.hr.leaves', compact('leaves'));
    }

    public function leaveAction(Request $request, $id)
    {
        $validated = $request->validate([
            'action' => 'required|in:approve,reject',
            'notes' => 'nullable|string|max:1000',
        ]);

        $leave = LeaveRequest::findOrFail($id);
        $leave->update([
            'status' => $validated['action'] === 'approve' ? 'APPROVED' : 'REJECTED',
            'approved_by' => auth()->id(),
            'approved_at' => now(),
            'admin_notes' => $validated['notes'] ?? null,
        ]);

        return back()->with('success', 'Leave request '.($validated['action'] === 'approve' ? 'approved' : 'rejected').'.');
    }
}
