<?php

namespace App\Components\Report;

use App\Enum\Dsar\DsarStatus;
use App\Models\Dsar\Dsar;
use App\Models\Institution\Institution;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Livewire\Component;
use Symfony\Component\HttpFoundation\StreamedResponse;

class DsarInstitutionReport extends Component {
    use AuthorizesRequests;

    public Institution $institution;

    public string $search       = '';
    public string $statusFilter = '';
    public bool   $overdueOnly  = false;
    public string $dateFrom     = '';
    public string $dateTo       = '';

    public function mount(): void {
        $this->authorize('dsars.report');
    }

    public function render() {
        $allOutstanding = Dsar::where('institution_id', $this->institution->id)
            ->whereNotIn('status', DsarStatus::excludedFromOpen())
            ->get(['id', 'created_at']);

        $totalOutstanding = $allOutstanding->count();
        // Carbon 3's diffInDays is signed and the oldest DSAR is in the past, so
        // abs() keeps the age positive.
        $oldestDays       = $allOutstanding->isNotEmpty()
            ? (int) abs(now()->diffInDays($allOutstanding->min('created_at')))
            : null;

        $grouped = $this->buildFilteredQuery()
            ->with(['claim.client', 'latestResponse'])
            ->orderBy('created_at')
            ->get()
            ->groupBy('claim_id');

        return view('components.report.dsar-institution', compact(
            'totalOutstanding', 'oldestDays', 'grouped'
        ));
    }

    public function export(): StreamedResponse {
        $dsars = $this->buildFilteredQuery()
            ->with(['claim.client', 'latestResponse'])
            ->orderBy('created_at')
            ->get();

        $filename = 'dsars_' . str($this->institution->display_name)->slug() . '_' . now()->format('Y-m-d') . '.csv';

        return new StreamedResponse(function () use ($dsars) {
            $handle = fopen('php://output', 'w');

            fputcsv($handle, ['Client', 'Claim Ref', 'Status', 'Sent Date', 'Days Outstanding', 'Latest Response']);

            foreach ($dsars as $dsar) {
                fputcsv($handle, [
                    $dsar->claim?->client?->fullName ?? '',
                    $dsar->claim?->slug ?? '',
                    $dsar->status,
                    $dsar->created_at->format('d/m/Y'),
                    (int) $dsar->created_at->diffInDays(),
                    $dsar->latestResponse?->typeLabel ?? '',
                ]);
            }

            fclose($handle);
        }, 200, [
            'Content-Type'        => 'text/csv',
            'Content-Disposition' => "attachment; filename=\"{$filename}\"",
        ]);
    }

    protected function buildFilteredQuery() {
        $query = Dsar::where('institution_id', $this->institution->id)
            ->whereNotIn('status', DsarStatus::excludedFromOpen());

        if ($this->statusFilter) {
            $query->where('status', $this->statusFilter);
        }

        if ($this->overdueOnly) {
            $query->where('created_at', '<=', now()->subDays(30));
        }

        if ($this->dateFrom) {
            $query->whereDate('created_at', '>=', $this->dateFrom);
        }

        if ($this->dateTo) {
            $query->whereDate('created_at', '<=', $this->dateTo);
        }

        if ($this->search) {
            $search = $this->search;
            $query->where(function ($q) use ($search) {
                $q->whereHas('claim.client', fn ($c) =>
                    $c->where('name_first', 'like', "%{$search}%")
                      ->orWhere('name_last', 'like', "%{$search}%")
                )->orWhereHas('claim', fn ($c) =>
                    $c->where('slug', 'like', "%{$search}%")
                );
            });
        }

        return $query;
    }
}
