<?php

namespace App\Http\Controllers;

use App\Models\Branch;
use App\Services\BranchAccessService;
use App\Services\CreditScore\CreditScorePortfolioReportService;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use Illuminate\View\View;
use Symfony\Component\HttpFoundation\StreamedResponse;

class CreditScorePortfolioReportController extends Controller
{
    public function __construct(private readonly BranchAccessService $branchAccess)
    {
    }

    public function index(Request $request, CreditScorePortfolioReportService $service): View
    {
        $scope = $this->scope($request);

        return view('credit-score-reports.portfolio', [
            ...$scope,
            'data' => $service->generate($scope['selectedBranchIds']->all()),
        ]);
    }

    public function export(Request $request, CreditScorePortfolioReportService $service): StreamedResponse
    {
        $scope = $this->scope($request);
        $data = $service->generate($scope['selectedBranchIds']->all());
        $branchNames = $scope['selectedBranches']->pluck('name')->join(', ');

        return response()->streamDownload(function () use ($data, $branchNames): void {
            $out = fopen('php://output', 'w');
            fwrite($out, "\xEF\xBB\xBF");
            fputcsv($out, ['Credit Score Portfolio']);
            fputcsv($out, ['Generated', $data['generated_at']->format('Y-m-d H:i:s')]);
            fputcsv($out, ['Score version', $data['score_version']]);
            fputcsv($out, ['Branches', $branchNames]);
            fputcsv($out, []);
            fputcsv($out, ['Metric', 'Value']);
            foreach ($data['summary'] as $label => $value) {
                fputcsv($out, [str($label)->replace('_', ' ')->headline()->toString(), $value ?? '']);
            }

            fputcsv($out, []);
            fputcsv($out, ['Score band', 'Customers', 'Average score', 'Average confidence', 'Manual review', 'Thin file', 'Active loans', 'Outstanding', 'Overdue', 'Arrears rate %']);
            foreach ($data['bands'] as $row) {
                fputcsv($out, [
                    $row['label'], $row['customers'], $row['average_score'] ?? '', $row['average_confidence'] ?? '',
                    $row['manual_review'], $row['thin_file'], $row['active_loans'], $row['outstanding'], $row['overdue'], $row['arrears_rate'],
                ]);
            }

            fputcsv($out, []);
            fputcsv($out, ['Branch', 'Customers', 'Scored', 'Average score', 'Manual review', 'Active loans', 'Outstanding', 'Overdue', 'Arrears rate %']);
            foreach ($data['branches'] as $row) {
                fputcsv($out, [
                    $row['branch_name'], $row['customers'], $row['scored_customers'], $row['average_score'] ?? '',
                    $row['manual_review'], $row['active_loans'], $row['outstanding'], $row['overdue'], $row['arrears_rate'],
                ]);
            }
            fclose($out);
        }, 'credit-score-portfolio-'.now()->format('Y-m-d').'.csv', ['Content-Type' => 'text/csv; charset=UTF-8']);
    }

    private function scope(Request $request): array
    {
        $user = $request->user();
        $allowedBranchIds = collect($this->branchAccess->accessibleBranchIds($user))
            ->map(fn ($id) => (int) $id)
            ->unique()
            ->values();

        abort_if($allowedBranchIds->isEmpty(), 403, 'No branch access is assigned to this user.');

        $validated = validator($request->all(), [
            'branch_ids' => ['sometimes', 'array'],
            'branch_ids.*' => ['integer', 'exists:branches,id'],
        ])->validate();

        $requested = collect($validated['branch_ids'] ?? [])
            ->map(fn ($id) => (int) $id)
            ->unique()
            ->values();

        $this->branchAccess->assertBranchesAccessible($user, $requested->all());
        $selectedBranchIds = $requested->isEmpty() ? $allowedBranchIds : $requested;
        $branches = Branch::query()->whereIn('id', $allowedBranchIds)->orderBy('name')->get();

        return [
            'branches' => $branches,
            'selectedBranchIds' => $selectedBranchIds,
            'selectedBranches' => $this->selectedBranches($branches, $selectedBranchIds),
        ];
    }

    private function selectedBranches(Collection $branches, Collection $selectedBranchIds): Collection
    {
        return $branches->whereIn('id', $selectedBranchIds)->values();
    }
}
