<?php

namespace App\Components\Dsar;

use App\Models\Client\Client;
use App\Models\Dsar\DsarType;
use App\Models\Institution\Institution;
use App\Models\Solicitor\Solicitor;
use App\Services\Communications\Placeholders\DsarPlaceholders;
use App\Services\Communications\Placeholders\PlaceholderRegistry;
use App\Services\Communications\Placeholders\TemplateRenderer;
use App\ValueObjects\Communications\PlaceholderContext;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Livewire\Attributes\Url;
use Livewire\Component;

class TypeEditor extends Component {
    use AuthorizesRequests;
    public $dsarId;
    public $display_name;
    public $description;
    public $content;
    public $email_content;

    /* Preview state */
    #[Url]
    public ?int $previewClientId = null;

    public ?int $previewInstitutionId = null;

    public ?string $previewContent = null;

    public ?string $previewEmailContent = null;

    public array $previewUnknown = [];

    /** @var array<int, string> */
    public array $unknownAtSave = [];

    protected $rules = [
        'display_name' => 'required|string|max:255',
        'description' => 'nullable|string|max:500',
        'content' => 'required|string',
        'email_content' => 'nullable|string',
    ];

    public function mount($dsarId = null) {
        $this->authorize($dsarId ? 'dsars.types.edit' : 'dsars.types.create');
        if ($dsarId) {
            $type = DsarType::findOrFail($dsarId);
            $this->dsarId = $type->id;
            $this->display_name = $type->display_name;
            $this->description = $type->description;
            $this->content = $type->content;
            $this->email_content = $type->email_content;
        }

        $this->refreshPreview();
    }

    public function updated($property): void {
        if (in_array($property, ['content', 'email_content', 'previewClientId', 'previewInstitutionId'], true)) {
            $this->refreshPreview();
        }
    }

    public function save() {
        $this->authorize($this->dsarId ? 'dsars.types.edit' : 'dsars.types.create');
        $this->validate();

        DsarType::updateOrCreate(
            ['id' => $this->dsarId],
            [
                'display_name' => $this->display_name,
                'description' => $this->description,
                'content' => $this->content,
                'email_content' => $this->email_content ?: null,
            ]
        );

        $this->unknownAtSave = app(TemplateRenderer::class)->unknownTokensIn(
            [$this->content, $this->email_content],
            'percent',
        );

        $this->dispatch('toast', message: 'Configuration saved successfully.', type: 'success');
    }

    public function cancel() {
        $this->dispatch('dsar-cancelled');
    }

    /* ---------- Preview ---------- */

    public function refreshPreview(): void {
        $renderer = app(TemplateRenderer::class);

        $ctx = PlaceholderContext::fromMessageable(
            messageable: $this->resolveSampleClient(),
            related: $this->resolveSampleInstitution(),
            solicitor: app(Solicitor::class),
            user: auth()->user(),
            extra: ['dsar_reference' => 'DSAR-PREVIEW-000000'],
        );

        [$this->previewContent, , $unknownContent] = $renderer->renderRaw($this->content, $ctx, false, 'percent');
        [$this->previewEmailContent, , $unknownEmail] = $this->email_content
            ? $renderer->renderRaw($this->email_content, $ctx, false, 'percent')
            : [null, [], []];

        $this->previewUnknown = array_values(array_unique(array_merge($unknownContent, $unknownEmail)));
    }

    private function resolveSampleClient(): ?Client {
        if ($this->previewClientId) {
            return Client::with('claim.status')->find($this->previewClientId);
        }

        return Client::with('claim.status')->orderBy('id')->first();
    }

    private function resolveSampleInstitution(): ?Institution {
        if ($this->previewInstitutionId) {
            return Institution::find($this->previewInstitutionId);
        }

        return Institution::orderBy('display_name')->first();
    }

    public function render() {
        $registry = app(PlaceholderRegistry::class);

        $placeholdersByCategory = collect(DsarPlaceholders::grouped())
            ->map(fn (array $tokens) => collect($tokens)
                ->map(fn (string $token) => $registry->get($token))
                ->filter()
                ->values());

        return view('components.dsar.type-editor', [
            'placeholdersByCategory' => $placeholdersByCategory,
            'previewClients' => Client::query()->orderBy('name_first')->limit(30)->get(['id', 'name_first', 'name_last']),
            'previewInstitutions' => Institution::query()->orderBy('display_name')->limit(50)->get(['id', 'display_name']),
        ]);
    }
}
