<?php

namespace App\Components\Claim;

use App\Models\Client\Client;
use App\Models\Dsar\Dsar;
use App\Models\Institution\Institution;
use App\Services\DsarService;
use App\Services\HistoryService;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Pagination\LengthAwarePaginator;
use Livewire\Component;
use Livewire\WithPagination;

class Dsars extends Component {
    use AuthorizesRequests;
    use WithPagination;

    public Client $client;
    public bool $showAdd = false;
    public $search = '';
    public array $selectedIds  = [];
    public array $postIds      = [];

    public function showAddDsar() {
        $this->showAdd = true;
    }

    public function createDsars(DsarService $dsar, HistoryService $history) {
        $this->authorize('dsars.create');

        $tranche = $this->client->claim->dsarTranches()->create([
            'status' => 'draft'
        ]);

        $pivotDates = $this->client->claim->institutions
            ->keyBy('id')
            ->map(fn($i) => $i->pivot->dates);

        $institutionsAdded = [];
        $createdDsars = [];

        foreach ($this->selectedIds as $id) {
            $institution = Institution::find($id);

            if (!$institution) {
                throw new \Exception('Institution not found');
            }

            $createdDsar = $tranche->dsars()->create([
                'solicitor_id' => $this->client->solicitor_id,
                'claim_id' => $this->client->claim->id,
                'user_id' => auth()->id(),
                'institution_id' => $id,
                'status' => 'draft',
                'content' => $dsar->buildContent($institution->dsarType, $this->client),
                'email_content' => $dsar->buildEmailContent($institution->dsarType, $this->client),
            ]);

            $createdDsars[] = $createdDsar;
            $institutionsAdded[] = $institution->display_name;
        }

        $trancheContext = [
            'claim_id' => $this->client->claim->id,
            'tranche_id' => $tranche->id,
            'institutions' => $institutionsAdded,
        ];

        // Log to the client timeline
        $history->add(
            $this->client,
            'DSAR tranche created with ' . count($institutionsAdded) . ' institution(s): ' . implode(', ', $institutionsAdded),
            $trancheContext
        );

        // Log to each individual DSAR
        foreach ($createdDsars as $createdDsar) {
            $history->add($createdDsar, 'DSAR created for "' . ($createdDsar->institution?->display_name ?? 'Unknown') . '"', [
                'claim_id' => $this->client->claim->id,
                'tranche_id' => $tranche->id,
                'institution' => $createdDsar->institution?->display_name,
            ]);
        }

        $this->hideAddDsar();

        return redirect()->route('dsars.tranches.view', $tranche);
    }

    public function hideAddDsar() {
        $this->showAdd = false;
        $this->reset(['search', 'selectedIds']);
    }

    public function selectAllPostable() {
        $this->postIds = $this->client->claim->dsars()
            ->where('status', 'needs posting')
            ->pluck('id')
            ->map(fn($id) => (string) $id)
            ->all();
    }

    public function markAsPosted(HistoryService $history) {
        $this->authorize('dsars.mark-posted');

        if (empty($this->postIds)) {
            return;
        }

        Dsar::whereIn('id', $this->postIds)
            ->where('status', 'needs posting')
            ->each(function (Dsar $dsar) use ($history) {
                $dsar->update([
                    'status'    => 'sent',
                    'posted_at' => now(),
                ]);
                $context = [
                    'dsar_id'     => $dsar->id,
                    'claim_id'    => $dsar->claim_id,
                    'institution' => $dsar->institution?->display_name,
                    'posted_at'   => now()->toDateTimeString(),
                ];
                $history->add($dsar, 'DSAR to "' . ($dsar->institution?->display_name ?? 'Unknown') . '" marked as posted', $context);
                $history->add($this->client, 'DSAR to "' . ($dsar->institution?->display_name ?? 'Unknown') . '" marked as posted', $context);
            });

        $this->reset('postIds');
        $this->dispatch('toast', message: 'DSARs marked as posted.', type: 'success');
    }

    public function render() {
        $dsarsQuery = $this->client->claim->dsars();

        $allInstitutions = $this->client->claim->careSettings
            ->pluck('institution')
            ->filter()
            ->flatMap(function ($institution)
            {
                return collect([$institution])->concat($institution->relatedInstitutions);
            })
            ->concat($this->client->claim->institutions)
            ->unique('id');

        // Global institutions (is_prioritised) not already in the claim list
        $claimInstitutionIds = $allInstitutions->pluck('id')->all();
        $globalInstitutions = Institution::where('is_prioritised', true)
            ->when($claimInstitutionIds, fn($q) => $q->whereNotIn('id', $claimInstitutionIds))
            ->orderBy('display_name')
            ->get();

        if (!empty($this->search)) {
            $term = strtolower($this->search);
            $allInstitutions = $allInstitutions->filter(
                fn($item) => str_contains(strtolower($item->display_name), $term)
            );
            $globalInstitutions = $globalInstitutions->filter(
                fn($item) => str_contains(strtolower($item->display_name), $term)
            );
        }

        $allInstitutions = $allInstitutions->values();

        $perPage = 10;
        $currentPage = LengthAwarePaginator::resolveCurrentPage('availPage');
        $currentItems = $allInstitutions->slice(($currentPage - 1) * $perPage, $perPage)->all();

        $paginatedInstitutions = new LengthAwarePaginator(
            $currentItems,
            $allInstitutions->count(),
            $perPage,
            $currentPage,
            [
                'path' => \request()->url(),
                'query' => request()->query(),
                'pageName' => 'availPage'
            ]
        );

        $draftTranches = $this->client->claim->dsarTranches()
            ->where('status', 'draft')
            ->with('dsars')
            ->get();

        return view('components.claim.dsars', [
            'dsars'                 => $dsarsQuery->paginate(10, ['*'], 'dsarsPage'),
            'availableInstitutions' => $paginatedInstitutions,
            'globalInstitutions'    => $globalInstitutions,
            'draftTranches'         => $draftTranches,
        ]);
    }
}