<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\Bonus;
use App\Models\BonusGeneration;
use App\Models\EmployeeSalaryAssignment;
use App\Services\BonusEligibilityService;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Inertia\Response;

class BonusGenerationController extends Controller
{
    public function __construct(protected BonusEligibilityService $bonusService) {}

    public function index(): Response
    {
        return Inertia::render('Admin/Payroll/Bonuses/Generations', [
            'generations' => BonusGeneration::with(['bonus', 'generatedBy', 'approvedBy'])
                ->withCount('items')
                ->withSum('items', 'bonus_amount')
                ->orderByDesc('created_at')
                ->get(),
        ]);
    }

    /**
     * Show the initial bonus generate form (no parameters required).
     */
    public function create(): Response
    {
        return Inertia::render('Admin/Payroll/Bonuses/Generate', [
            'bonuses' => Bonus::all(),
        ]);
    }

    public function preview(Request $request): Response
    {
        $request->validate([
            'generation_id' => ['nullable', 'exists:bonus_generations,id'],
            'bonus_id' => ['required_without:generation_id', 'exists:bonuses,id'],
            'month' => ['required_without:generation_id', 'date_format:Y-m'],
        ]);

        $existingGeneration = null;
        $bonus = null;
        $monthStr = $request->month;

        if ($request->generation_id) {
            $existingGeneration = BonusGeneration::with('items:id,bonus_generation_id,employee_id')
                ->findOrFail($request->generation_id);

            $bonus = Bonus::findOrFail($existingGeneration->bonus_id);
            $monthStr = $existingGeneration->month->format('Y-m');
        } else {
            $bonus = Bonus::findOrFail($request->bonus_id);
            $monthDate = Carbon::createFromFormat('Y-m', $request->month)->startOfMonth()->toDateString();

            // We NO LONGER auto-fetch existing draft by month/type here since they want to allow multiple.
            // If they are creating new, we just pass null. They must explicitly pass generation_id to edit.
        }

        $employees = $this->bonusService->getEligibleEmployees($bonus);

        $rows = $employees->map(function ($e) use ($bonus) {
            $assignment = EmployeeSalaryAssignment::where('employee_id', $e->id)
                ->orderByDesc('effective_from')
                ->first();

            $grossSalary = (float) ($assignment?->gross_salary ?? 0);

            $calculated = $bonus->amount_type === 'percentage'
                ? round($grossSalary * ((float) $bonus->amount / 100), 2)
                : (float) $bonus->amount;

            return [
                'id' => $e->id,
                'name' => $e->name,
                'job_title' => $e->employeeProfile?->job_title ?? null,
                'department' => $e->employeeProfile?->departmentRel?->name ?? null,
                'gross_salary' => $grossSalary,
                'calculated_bonus' => $calculated,
            ];
        });

        return Inertia::render('Admin/Payroll/Bonuses/Generate', [
            'bonuses' => Bonus::all(),
            'bonus' => $bonus,
            'month' => $monthStr,
            'eligibleEmployees' => $rows,
            'existingGeneration' => $existingGeneration,
        ]);
    }

    public function generate(Request $request)
    {
        $request->validate([
            'generation_id' => ['nullable', 'exists:bonus_generations,id'],
            'bonus_id' => ['required_without:generation_id', 'exists:bonuses,id'],
            'month' => ['required_without:generation_id', 'date_format:Y-m'],
            'employee_ids' => ['required', 'array', 'min:1'],
            'employee_ids.*' => ['integer'],
        ]);

        try {
            if ($request->generation_id) {
                $existingGeneration = BonusGeneration::findOrFail($request->generation_id);

                if ($existingGeneration->status !== 'draft') {
                    return back()->with('error', 'Only draft bonus generations can be edited. This bonus generation is already '.$existingGeneration->status.'.');
                }

                $bonus = Bonus::findOrFail($existingGeneration->bonus_id);
                $monthDate = $existingGeneration->month->toDateString();
            } else {
                $bonus = Bonus::findOrFail($request->bonus_id);
                $monthDate = Carbon::createFromFormat('Y-m', $request->month)->startOfMonth()->toDateString();
            }
            // We run generation. We need to pass the actual existing ID down to the service if it exists!
            $generation = $this->bonusService->generateBonus(
                $bonus,
                $monthDate,
                $request->user(),
                $request->employee_ids,
                $request->generation_id
            );

            return redirect()->route('admin.bonuses.generations.index')
                ->with('success', 'Bonus generated for '.$generation->items()->count().' employees — saved as draft.');
        } catch (\Exception $e) {
            return back()->with('error', $e->getMessage());
        }
    }

    public function sendForApproval(BonusGeneration $bonusGeneration)
    {
        if ($bonusGeneration->status !== 'draft') {
            return back()->with('error', 'Only draft bonus generations can be sent for approval.');
        }

        $bonusGeneration->update(['status' => 'pending']);

        return back()->with('success', 'Bonus generation sent for approval.');
    }

    public function approve(Request $request, BonusGeneration $bonusGeneration)
    {
        $this->bonusService->approve($bonusGeneration, $request->user());

        return back()->with('success', 'Bonus generation approved.');
    }
}
