<?php

namespace App\Components\Esign\Admin;

use App\Models\Contract;
use App\Models\Solicitor\Solicitor;
use Livewire\Component;

/**
 * Per-solicitor contracts + Fintrixor eSign configuration. Manages the firm's own
 * set of contracts (name, whether to preview, Fintrixor template id) plus the API
 * key and optional base-url override. Scoped to the current workspace solicitor.
 */
class EsignSettings extends Component
{
    public ?int $solicitorId = null;

    public string $baseUrl = '';
    public string $apiKey = '';            // a new key to set; blank keeps the existing one
    public bool $apiKeyConfigured = false;

    /** @var array<int, array{id: ?int, name: string, requires_preview: bool, fintrixor_template_id: string, redress_role: string}> */
    public array $rows = [];
    /** @var array<int, int> contract ids removed in the UI, deleted on save */
    public array $deletedIds = [];

    public ?string $success = null;
    public ?string $error = null;

    public function mount(): void
    {
        $this->authorize('esign.settings.manage');

        $solicitor = app(Solicitor::class);
        if (!$solicitor) {
            $this->error = 'Select a workspace before managing contracts.';
            return;
        }

        $this->solicitorId      = $solicitor->id;
        $this->baseUrl          = $solicitor->esign_base_url ?? '';
        $this->apiKeyConfigured = filled($solicitor->esign_api_key);
        $this->loadRows();
    }

    private function loadRows(): void
    {
        // Scoped to the current solicitor by BelongsToSolicitor.
        $this->rows = Contract::orderBy('name')->get()
            ->map(fn (Contract $c) => [
                'id'                    => $c->id,
                'name'                  => $c->name,
                'requires_preview'      => (bool) $c->requires_preview,
                'fintrixor_template_id' => (string) ($c->fintrixor_template_id ?? ''),
                'redress_role'          => (string) ($c->redress_role?->value ?? ''),
            ])
            ->values()
            ->all();
    }

    public function addRow(): void
    {
        $this->rows[] = ['id' => null, 'name' => '', 'requires_preview' => false, 'fintrixor_template_id' => '', 'redress_role' => ''];
    }

    public function removeRow(int $index): void
    {
        if (!isset($this->rows[$index])) {
            return;
        }

        if ($this->rows[$index]['id']) {
            $this->deletedIds[] = (int) $this->rows[$index]['id'];
        }

        unset($this->rows[$index]);
        $this->rows = array_values($this->rows);
    }

    public function save(): void
    {
        $this->authorize('esign.settings.manage');

        if (!$this->solicitorId) {
            $this->error = 'No workspace in context.';
            return;
        }

        // Drop fully-empty new rows before validating.
        $this->rows = array_values(array_filter(
            $this->rows,
            fn ($r) => $r['id'] || filled($r['name']) || filled($r['fintrixor_template_id'])
        ));

        // Normalise the "none" option ('') to null so `nullable` applies.
        foreach ($this->rows as $i => $row) {
            $this->rows[$i]['redress_role'] = filled($row['redress_role'] ?? null) ? $row['redress_role'] : null;
        }

        $this->validate([
            'baseUrl'                      => 'nullable|url|max:255',
            'apiKey'                       => 'nullable|string|max:255',
            'rows.*.name'                  => 'required|string|max:255',
            'rows.*.fintrixor_template_id' => 'nullable|string|max:191',
            'rows.*.redress_role'          => 'nullable|in:part1_annex,part2_annex',
        ], [], ['rows.*.name' => 'contract name']);

        $solicitor = Solicitor::findOrFail($this->solicitorId);

        $attributes = ['esign_base_url' => $this->baseUrl ?: null];
        if (filled($this->apiKey)) {
            $attributes['esign_api_key'] = trim($this->apiKey);
        }
        $solicitor->update($attributes);

        // Delete removed contracts (scoped — only this solicitor's).
        if ($this->deletedIds) {
            Contract::whereIn('id', $this->deletedIds)->delete();
            $this->deletedIds = [];
        }

        // Upsert the firm's contracts.
        foreach ($this->rows as $i => $row) {
            $data = [
                'name'                  => trim($row['name']),
                'requires_preview'      => (bool) ($row['requires_preview'] ?? false),
                'fintrixor_template_id' => filled($row['fintrixor_template_id']) ? trim($row['fintrixor_template_id']) : null,
                'redress_role'          => $row['redress_role'] ?? null,
            ];

            if ($row['id']) {
                Contract::where('id', $row['id'])->update($data);
            } else {
                $contract = Contract::create($data + ['solicitor_id' => $solicitor->id]);
                $this->rows[$i]['id'] = $contract->id;
            }
        }

        $this->apiKey           = '';
        $this->apiKeyConfigured = filled($solicitor->fresh()->esign_api_key);
        $this->loadRows();
        $this->success = 'Contracts & e-signature settings saved.';
        $this->error   = null;
    }

    public function render()
    {
        return view('components.esign.admin.esign-settings', [
            'defaultBaseUrl' => config('services.esign.base_url'),
        ]);
    }
}
