<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\BonusGeneration;
use App\Models\Loan;
use App\Models\Payroll;
use App\Models\SalaryIncrement;
use App\Services\BonusEligibilityService;
use App\Services\PayrollGenerationService;
use App\Services\SalaryIncrementService;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Inertia\Response;

class PayrollApprovalController extends Controller
{
    public function __construct(
        protected PayrollGenerationService $payrollService,
        protected BonusEligibilityService $bonusService,
        protected SalaryIncrementService $incrementService,
    ) {}

    public function index(): Response
    {
        return Inertia::render('Admin/Payroll/Approval/Index', [
            'payrolls' => Payroll::with(['generatedBy', 'approvedBy'])
                ->where('status', '!=', 'draft')
                ->orderByDesc('created_at')
                ->get(),
            'bonusGenerations' => BonusGeneration::with(['bonus', 'generatedBy', 'approvedBy'])
                ->withCount('items')
                ->withSum('items', 'bonus_amount')
                ->where('status', '!=', 'draft')
                ->orderByDesc('created_at')
                ->get(),
            'increments' => SalaryIncrement::with(['employee', 'approvedBy'])
                ->orderByDesc('created_at')
                ->get(),
            'loanRequests' => Loan::with(['employee', 'approver'])
                ->where('status', '!=', 'draft')
                ->orderByDesc('created_at')
                ->get(),
        ]);
    }

    public function approvePayroll(Request $request, Payroll $payroll)
    {
        try {
            $this->payrollService->approve($payroll, $request->user());

            return back()->with('success', 'Payroll approved successfully.');
        } catch (\Exception $e) {
            return back()->with('error', $e->getMessage());
        }
    }

    public function rejectPayroll(Request $request, Payroll $payroll)
    {
        if ($payroll->status !== 'pending') {
            return back()->with('error', 'Only pending payrolls can be rejected.');
        }

        $payroll->update([
            'status' => 'rejected',
            'approved_by' => $request->user()->id,
            'approved_at' => now(),
        ]);

        return back()->with('success', 'Payroll rejected.');
    }

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

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

    public function rejectBonus(Request $request, BonusGeneration $bonusGeneration)
    {
        if ($bonusGeneration->status !== 'pending') {
            return back()->with('error', 'Only pending bonus generations can be rejected.');
        }

        $bonusGeneration->update([
            'status' => 'rejected',
            'approved_by' => $request->user()->id,
            'approved_at' => now(),
        ]);

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

    public function approveIncrement(Request $request, SalaryIncrement $salaryIncrement)
    {
        try {
            $this->incrementService->approveIncrement($salaryIncrement, $request->user());

            return back()->with('success', 'Salary increment approved and applied.');
        } catch (\Exception $e) {
            return back()->with('error', $e->getMessage());
        }
    }

    public function rejectIncrement(Request $request, SalaryIncrement $salaryIncrement)
    {
        try {
            $this->incrementService->rejectIncrement($salaryIncrement, $request->user());

            return back()->with('success', 'Salary increment rejected.');
        } catch (\Exception $e) {
            return back()->with('error', $e->getMessage());
        }
    }

    public function bulkApprovePayrolls(Request $request)
    {
        $request->validate(['ids' => 'required|array', 'ids.*' => 'integer']);
        $payrolls = Payroll::whereIn('id', $request->ids)->where('status', 'pending')->get();
        $count = 0;
        foreach ($payrolls as $payroll) {
            $this->payrollService->approve($payroll, $request->user());
            $count++;
        }

        return back()->with('success', "$count payroll(s) approved.");
    }

    public function bulkRejectPayrolls(Request $request)
    {
        $request->validate(['ids' => 'required|array', 'ids.*' => 'integer']);
        $payrolls = Payroll::whereIn('id', $request->ids)->where('status', 'pending')->get();
        $count = 0;
        foreach ($payrolls as $payroll) {
            $payroll->update([
                'status' => 'rejected',
                'approved_by' => $request->user()->id,
                'approved_at' => now(),
            ]);
            $count++;
        }

        return back()->with('success', "$count payroll(s) rejected.");
    }

    public function bulkApproveBonuses(Request $request)
    {
        $request->validate(['ids' => 'required|array', 'ids.*' => 'integer']);
        $bonuses = BonusGeneration::whereIn('id', $request->ids)->where('status', 'pending')->get();
        $count = 0;
        foreach ($bonuses as $generation) {
            $this->bonusService->approve($generation, $request->user());
            $count++;
        }

        return back()->with('success', "$count bonus generation(s) approved.");
    }

    public function bulkRejectBonuses(Request $request)
    {
        $request->validate(['ids' => 'required|array', 'ids.*' => 'integer']);
        $bonuses = BonusGeneration::whereIn('id', $request->ids)->where('status', 'pending')->get();
        $count = 0;
        foreach ($bonuses as $generation) {
            $generation->update([
                'status' => 'rejected',
                'approved_by' => $request->user()->id,
                'approved_at' => now(),
            ]);
            $count++;
        }

        return back()->with('success', "$count bonus generation(s) rejected.");
    }

    public function bulkApproveIncrements(Request $request)
    {
        $request->validate(['ids' => 'required|array', 'ids.*' => 'integer']);
        $increments = SalaryIncrement::whereIn('id', $request->ids)->where('status', 'pending')->get();
        $count = 0;
        foreach ($increments as $increment) {
            try {
                $this->incrementService->approveIncrement($increment, $request->user());
                $count++;
            } catch (\Exception $e) {
                // skip failed
            }
        }

        return back()->with('success', "$count salary increment(s) approved.");
    }

    public function bulkRejectIncrements(Request $request)
    {
        $request->validate(['ids' => 'required|array', 'ids.*' => 'integer']);
        $increments = SalaryIncrement::whereIn('id', $request->ids)->where('status', 'pending')->get();
        $count = 0;
        foreach ($increments as $increment) {
            try {
                $this->incrementService->rejectIncrement($increment, $request->user());
                $count++;
            } catch (\Exception $e) {
                // skip failed
            }
        }

        return back()->with('success', "$count salary increment(s) rejected.");
    }

    public function approveLoan(Request $request, Loan $loan)
    {
        if ($loan->status !== 'pending') {
            return back()->with('error', 'Only pending loans can be approved.');
        }

        $loan->update([
            'status' => 'approved',
            'approved_by' => $request->user()->id,
            'approved_at' => now(),
        ]);

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

    public function rejectLoan(Request $request, Loan $loan)
    {
        if ($loan->status !== 'pending') {
            return back()->with('error', 'Only pending loans can be rejected.');
        }

        $loan->update([
            'status' => 'rejected',
            'approved_by' => $request->user()->id,
            'approved_at' => now(),
        ]);

        return back()->with('success', 'Loan rejected.');
    }

    public function bulkApproveLoans(Request $request)
    {
        $request->validate(['ids' => 'required|array', 'ids.*' => 'integer']);
        $loans = Loan::whereIn('id', $request->ids)->where('status', 'pending')->get();
        $count = 0;
        foreach ($loans as $loan) {
            $loan->update([
                'status' => 'approved',
                'approved_by' => $request->user()->id,
                'approved_at' => now(),
            ]);
            $count++;
        }

        return back()->with('success', "$count loan(s) approved.");
    }

    public function bulkRejectLoans(Request $request)
    {
        $request->validate(['ids' => 'required|array', 'ids.*' => 'integer']);
        $loans = Loan::whereIn('id', $request->ids)->where('status', 'pending')->get();
        $count = 0;
        foreach ($loans as $loan) {
            $loan->update([
                'status' => 'rejected',
                'approved_by' => $request->user()->id,
                'approved_at' => now(),
            ]);
            $count++;
        }

        return back()->with('success', "$count loan(s) rejected.");
    }
}
