<?php

namespace App\Http\Controllers;

use App\Models\CollectionFollowUp;
use App\Models\Loan;
use App\Services\AuditService;
use App\Services\BranchAccessService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;
use Illuminate\View\View;

class ArrearsController extends Controller
{
    public function index(Request $request): View
    {
        $query = $this->scopedQuery($request)
            ->with(['customer','branch','creator','collaterals'])
            ->where('status', 'active')
            ->where('days_overdue', '>', 0);

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

        $summary = $this->scopedQuery($request)
            ->where('status', 'active')
            ->where('days_overdue', '>', 0)
            ->selectRaw('arrears_bucket, COUNT(*) as loans_count, SUM(total_overdue) as total_overdue')
            ->groupBy('arrears_bucket')
            ->get()
            ->keyBy('arrears_bucket');

        return view('arrears.index', [
            'loans' => $query->orderByDesc('days_overdue')->orderBy('loan_number')->paginate(25)->withQueryString(),
            'summary' => $summary,
            'bucket' => (string) $request->string('bucket'),
            'search' => (string) $request->string('search'),
        ]);
    }

    public function show(Request $request, Loan $loan): View
    {
        $this->authorizeLoan($request, $loan);
        abort_if($loan->days_overdue < 1, 404);
        $loan->load([
            'customer','branch.business','creator','collaterals.category','installments','penaltyCharges.installment',
            'collectionFollowUps.employee','guarantor',
        ]);

        return view('arrears.show', ['loan' => $loan]);
    }

    public function storeFollowUp(Request $request, Loan $loan): RedirectResponse
    {
        $this->authorizeLoan($request, $loan);
        abort_if($loan->days_overdue < 1 || $loan->status !== 'active', 404);

        $data = $request->validate([
            'action_type' => ['required', Rule::in(CollectionFollowUp::ACTION_TYPES)],
            'notes' => ['nullable', 'string', 'max:5000'],
            'promise_date' => [Rule::requiredIf($request->input('action_type') === 'promise_to_pay'), 'nullable', 'date', 'after_or_equal:today'],
        ]);

        $followUp = DB::transaction(function () use ($request, $loan, $data): CollectionFollowUp {
            return CollectionFollowUp::create([
                'loan_id' => $loan->id,
                'customer_id' => $loan->customer_id,
                'branch_id' => $loan->branch_id,
                'action_type' => $data['action_type'],
                'action_at' => now(),
                'notes' => $data['notes'] ?? null,
                'promise_date' => $data['promise_date'] ?? null,
                'employee_id' => $request->user()->id,
            ]);
        });

        AuditService::record('collections.follow_up_created', $followUp, [], $followUp->toArray());
        return back()->with('success', 'Collection follow-up recorded.');
    }

    private function scopedQuery(Request $request)
    {
        return Loan::query()->whereIn(
            'branch_id',
            app(BranchAccessService::class)->accessibleBranchIds($request->user())
        );
    }

    private function authorizeLoan(Request $request, Loan $loan): void
    {
        abort_unless($request->user()->canAccessBranch($loan->branch_id), 403);
    }
}
