<?php

namespace App\Components\Claim;

use App\Models\Claim\Claim;
use App\Models\Claim\ClaimInstitution;
use App\Models\Dsar\DsarType;
use App\Models\Institution\Institution;
use App\Models\Institution\InstitutionRecordType;
use App\Models\Institution\InstitutionType;
use App\Services\HistoryService;
use Livewire\Component;

class InstitutionManager extends Component {

    public Claim $claim;

    public bool $showOffcanvas = false;
    public string $step = 'search';

    public string $searchTerm = '';

    public ?int $selectedInstitutionId = null;
    public string $selectedInstitutionName = '';

    public ?int $recordTypeId = null;
    public string $dates = '';

    public $newInstitutionName = '';
    public bool $showCreateForm = false;

    public function mount(Claim $claim) {
        $this->claim = $claim;
    }

    public function openOffcanvas() {
        $this->reset('searchTerm', 'step', 'selectedInstitutionId', 'selectedInstitutionName', 'recordTypeId', 'dates', 'showCreateForm', 'newInstitutionName');
        $this->step = 'search';
        $this->showOffcanvas = true;
    }

    public function closeOffcanvas() {
        $this->showOffcanvas = false;
    }

    public function updatedSearchTerm() {
        // search results are computed in render() — nothing to store here
    }

    public function selectInstitution(int $id, string $name) {
        $this->selectedInstitutionId   = $id;
        $this->selectedInstitutionName = $name;
        $this->step = 'details';
    }

    public function backToSearch() {
        $this->step = 'search';
        $this->selectedInstitutionId   = null;
        $this->selectedInstitutionName = '';
        $this->recordTypeId = null;
        $this->dates = '';
    }

    public function attach(HistoryService $history) {
        $this->validate([
            'selectedInstitutionId' => 'required|integer',
        ]);

        $this->claim->institutions()->attach($this->selectedInstitutionId, [
            'record_type_id' => $this->recordTypeId ?: null,
            'dates'          => $this->dates ?: null,
        ]);

        $history->add($this->claim->client, 'Institution "' . $this->selectedInstitutionName . '" linked to claim', [
            'claim_id'       => $this->claim->id,
            'institution_id' => $this->selectedInstitutionId,
            'institution'    => $this->selectedInstitutionName,
        ]);

        $this->reset('selectedInstitutionId', 'selectedInstitutionName', 'recordTypeId', 'dates', 'searchTerm');
        $this->step = 'search';

        $this->dispatch('toast', type: 'success', message: 'Institution linked.');
    }

    public function detach(HistoryService $history, int $pivotId) {
        $pivot = ClaimInstitution::with('institution')->findOrFail($pivotId);
        $institutionName = $pivot->institution?->display_name;
        $pivot->delete();

        $history->add($this->claim->client, 'Institution "' . $institutionName . '" removed from claim', [
            'claim_id'    => $this->claim->id,
            'institution' => $institutionName,
        ]);

        $this->dispatch('toast', type: 'success', message: 'Institution removed.');
    }

    public function toggleCreateForm() {
        $this->showCreateForm     = !$this->showCreateForm;
        $this->newInstitutionName = '';
        $this->resetValidation();
    }

    public function createAndAttach(HistoryService $history) {
        $this->validate([
            'newInstitutionName' => 'required|string|min:3|max:255',
        ]);

        $institution = Institution::create([
            'display_name'        => $this->newInstitutionName,
            'institution_type_id' => InstitutionType::first()->id,
            'dsar_type_id'        => DsarType::first()?->id,
        ]);

        $this->claim->institutions()->attach($institution->id, [
            'record_type_id' => $this->recordTypeId ?: null,
            'dates'          => $this->dates ?: null,
        ]);

        $history->add($this->claim->client, 'Institution "' . $institution->display_name . '" created and linked to claim', [
            'claim_id'       => $this->claim->id,
            'institution_id' => $institution->id,
            'institution'    => $institution->display_name,
        ]);

        $this->showCreateForm     = false;
        $this->newInstitutionName = '';
        $this->reset('recordTypeId', 'dates');

        $this->dispatch('toast', type: 'success', message: 'Institution created and linked.');
    }

    public function render() {
        $searchResults = [];
        $term = trim($this->searchTerm);

        if (strlen($term) >= 2) {
            $linkedInstitutionIds = $this->claim->institutions()->pluck('institutions.id')->toArray();

            $searchResults = Institution::where('display_name', 'like', '%' . $term . '%')
                ->orWhereHas('aliases', fn($q) => $q->where('alias', 'like', '%' . $term . '%'))
                ->with('aliases')
                ->limit(10)
                ->get()
                ->map(function ($institution) use ($term, $linkedInstitutionIds) {
                    $name = $institution->display_name;

                    if (stripos($name, $term) === false) {
                        $alias = $institution->aliases->first(fn($a) => stripos($a->alias, $term) !== false);
                        if ($alias) {
                            $name = "{$institution->display_name} ({$alias->alias})";
                        }
                    }

                    return [
                        'id'           => $institution->id,
                        'display_name' => $name,
                        'already_linked' => in_array($institution->id, $linkedInstitutionIds),
                    ];
                })
                ->values()
                ->all();
        }

        $institutions = ClaimInstitution::with(['institution.type', 'recordType'])
            ->where('claim_id', $this->claim->id)
            ->get()
            ->groupBy(fn($r) => $r->recordType?->display_name ?? 'Unclassified');

        $recordTypes = InstitutionRecordType::orderBy('display_name')->get();

        return view('components.claim.institution-manager', compact('institutions', 'searchResults', 'recordTypes'));
    }
}
