<?php

namespace App\Components\Dsar;

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 Livewire\WithPagination;
use Symfony\Component\HttpFoundation\StreamedResponse;

class Outstanding extends Component {
    use AuthorizesRequests, WithPagination;

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

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

    public function updatingSearch()            { $this->resetPage(); }
    public function updatingStatusFilter()      { $this->resetPage(); }
    public function updatingInstitutionFilter() { $this->resetPage(); }
    public function updatingFlaggedOnly()       { $this->resetPage(); }
    public function updatingOverdueOnly()       { $this->resetPage(); }
    public function updatingDateFrom()          { $this->resetPage(); }
    public function updatingDateTo()            { $this->resetPage(); }

    public function render() {
        $dsars = $this->buildFilteredQuery()
            ->with(['institution', 'claim.client', 'latestResponse'])
            ->orderByDesc('is_flagged')->orderBy('created_at')
            ->paginate(20);

        $institutions = Institution::orderBy('display_name')
            ->whereHas('claims.dsars', fn($q) => $q->whereNotIn('status', DsarStatus::excludedFromOpen()))
            ->get(['id', 'display_name']);

        return view('components.dsar.outstanding', compact('dsars', 'institutions'));
    }

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

        $filename = 'outstanding_dsars_' . now()->format('Y-m-d') . '.csv';

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

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

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

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

    protected function buildFilteredQuery() {
        $query = Dsar::whereNotIn('status', DsarStatus::excludedFromOpen());

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

        if ($this->institutionFilter) {
            $query->where('institution_id', $this->institutionFilter);
        }

        if ($this->flaggedOnly) {
            $query->where('is_flagged', true);
        }

        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('institution', fn($i) => $i->where('display_name', 'like', "%{$search}%"))
                  ->orWhereHas('claim.client', fn($c) =>
                      $c->where('name_first', 'like', "%{$search}%")
                        ->orWhere('name_last', 'like', "%{$search}%")
                  );
            });
        }

        return $query;
    }
}
