<?php

namespace App\Http\Controllers;

use App\Models\Branch;
use App\Models\Collateral;
use App\Models\Loan;
use App\Services\AuditService;
use App\Services\BranchAccessService;
use App\Services\LoanApprovalService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;
use Illuminate\Validation\Rule;
use Illuminate\Validation\ValidationException;
use Illuminate\View\View;

class LoanApprovalController extends Controller
{
    public function index(Request $request): View
    {
        $statuses = ['under_review','correction_requested','waiting_for_documents','additional_collateral_requested','rejected','ready_for_disbursement'];
        $query = Loan::with(['customer','branch','product','creator','approver'])
            ->whereIn('branch_id',$this->allowedBranchIds($request))
            ->latest('id');

        if ($request->filled('search')) {
            $search = trim((string)$request->string('search'));
            $query->where(function ($q) use ($search): void {
                $q->where('loan_number','like',"%{$search}%")
                    ->orWhereHas('customer',fn($customer)=>$customer->where('customer_number','like',"%{$search}%")
                        ->orWhere('first_name','like',"%{$search}%")
                        ->orWhere('middle_name','like',"%{$search}%")
                        ->orWhere('last_name','like',"%{$search}%")
                        ->orWhere('phone','like',"%{$search}%"));
            });
        }

        if ($request->filled('status')) {
            abort_unless(in_array((string)$request->string('status'),$statuses,true),422);
            $query->where('status',$request->string('status'));
        } else {
            $query->where('status','under_review');
        }

        if ($request->filled('branch')) {
            $branchId=$request->integer('branch');
            abort_unless($request->user()->canAccessBranch($branchId),403);
            $query->where('branch_id',$branchId);
        }

        return view('loans.approvals.index',[
            'loans'=>$query->paginate(20)->withQueryString(),
            'statuses'=>$statuses,
            'branches'=>Branch::whereIn('id',$this->allowedBranchIds($request))->orderBy('name')->get(),
        ]);
    }

    public function decide(Request $request, Loan $loan, LoanApprovalService $service): RedirectResponse
    {
        Gate::authorize('approve',$loan);
        $data=$request->validate([
            'decision'=>['required',Rule::in(['approve','reject','request_correction','request_documents','request_additional_collateral'])],
            'comments'=>['nullable','string','max:4000'],
        ]);

        $before=$loan->status;
        $updated=$service->decide($loan,$request->user(),$data['decision'],$data['comments'] ?? null);
        AuditService::record('loan_approval.'.$data['decision'],$loan,['status'=>$before],['status'=>$updated->status,'comments'=>$data['comments'] ?? null],$loan->branch_id);

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

    public function addCollateral(Request $request, Loan $loan): RedirectResponse
    {
        Gate::authorize('addCollateral',$loan);
        if ($loan->status !== 'additional_collateral_requested') {
            throw ValidationException::withMessages(['collateral_ids'=>'Additional collateral can only be added while it has been requested by a reviewer.']);
        }

        $data=$request->validate([
            'collateral_ids'=>['required','array','min:1'],
            'collateral_ids.*'=>['integer','exists:collaterals,id'],
        ]);
        $ids=array_values(array_unique(array_map('intval',$data['collateral_ids'])));
        $valid=Collateral::whereIn('id',$ids)
            ->where('branch_id',$loan->branch_id)
            ->where('customer_id',$loan->customer_id)
            ->whereNotIn('status',['released','sold','returned'])
            ->count();
        if ($valid !== count($ids)) {
            throw ValidationException::withMessages(['collateral_ids'=>'All collateral must belong to this customer and branch and remain available.']);
        }

        $before=$loan->collaterals()->pluck('collaterals.id')->all();
        $loan->collaterals()->syncWithoutDetaching($ids);
        AuditService::record('loan_application.additional_collateral_added',$loan,['collateral_ids'=>$before],['collateral_ids'=>$loan->collaterals()->pluck('collaterals.id')->all()],$loan->branch_id);
        return back()->with('success','Additional collateral linked to the loan application.');
    }

    private function allowedBranchIds(Request $request)
    {
        return collect(app(BranchAccessService::class)->accessibleBranchIds($request->user()));
    }
}
