<?php

namespace App\Components\Client;

use App\Models\Client\Client;
use App\Models\Contract;
use App\Models\ContractRequest;
use App\Services\ApplicationService;
use App\Services\EsignService;
use App\Services\HistoryService;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Livewire\Component;

class Contracts extends Component {
    use AuthorizesRequests;
    public $contracts;
    public array $selectedContractIds = [];
    public array $previewsToRender = [];

    public Client $client;

    public function mount(): void {
        $this->contracts = Contract::all();
    }

    /**
     * Pre-esign checklist. Returns a list of human-readable blockers.
     * An empty array means the application is ready to send.
     */
    public function getEsignBlockersProperty(): array {
        $blockers = [];
        $claim    = $this->client->claim;

        if (!$claim) {
            $blockers[] = 'No claim has been initialised for this client.';
            return $blockers;
        }

        if (!in_array($claim->redress_type, ['FIXED', 'INDIVIDUAL'], true)) {
            $blockers[] = 'Redress type must be set to Fixed or Individual.';
        }

        // Beneficiary is optional — only enforce contact requirements if one has been added.
//        if ($beneficiary = $claim->beneficiary) {
//            $contactCount = collect([
//                $beneficiary->email,
//                $beneficiary->telephone,
//            ])->filter(fn ($v) => filled((string) $v))->count();
//
//            if ($contactCount < 2) {
//                $blockers[] = 'Beneficiary must have at least 2 contact types (email and telephone).';
//            }
//        }

        return $blockers;
    }

    public function processSignature(EsignService $esignService, ApplicationService $appService): void {
        $this->authorize('claims.request.send');

        if (empty($this->selectedContractIds)) {
            $this->dispatch('toast', type: 'error', message: 'Please select at least one contract.');
            return;
        }

        if ($this->esignBlockers) {
            $this->dispatch('toast',
                type: 'error',
                message: 'Application is not ready: ' . implode(' ', $this->esignBlockers),
            );
            return;
        }

        $needsPreview = false;
        $this->previewsToRender = [];

        foreach ($this->contracts as $contract) {
            if (in_array($contract['id'], $this->selectedContractIds) && $contract['requires_preview']) {
                $needsPreview = true;

                $this->previewsToRender[] = [
                    'id' => $contract['id'],
                    'name' => $contract['name'],
                    'pdf_data' => $this->generateContractPdf($contract['id'], $appService)
                ];
            }
        }

        if ($needsPreview) {
            $this->dispatch('show-preview-modal', previews: $this->previewsToRender);
        } else {
            $this->sendToEsign($esignService);
        }
    }

    public function generateContractPdf($id, ApplicationService $service): string {
        $contract = Contract::find($id);
        if($contract) {
            return $service->build($this->client, [$contract->name])[$contract->name]['base64'];
        }

        return '';
    }

    protected function sendToEsign(EsignService $esignService) {
        $request = ContractRequest::create([
            'client_id' => $this->client->id,
            'user_id' => auth()->id(),
            'contract_ids' => $this->selectedContractIds,
            'status' => 'sent',
        ]);

        $contractNames = Contract::whereIn('id', $this->selectedContractIds)->pluck('name')->all();

        $response = $esignService->send($request);

        $history = app(HistoryService::class);

        if ($response) {
            $signatureLink = $response['link'];
            $fullResponseData = ['api_status' => 'success', 'envelope_id' => uniqid(), 'timestamp' => now()->toIso8601String()];

            $request->update([
                'link' => $signatureLink,
                'full_data' => $fullResponseData,
            ]);

            $history->add($this->client, 'E-signature request sent for "' . implode('", "', $contractNames) . '"', [
                'contract_request_id' => $request->id,
                'contracts'           => $contractNames,
            ]);

            $this->dispatch('toast',
                type: 'success',
                message: 'Successfully sent ' . count($this->selectedContractIds) . ' contract(s) for e-signature!',
            );

            $this->selectedContractIds = [];
        } else {
            $history->add($this->client, 'E-signature request failed for "' . implode('", "', $contractNames) . '"', [
                'contract_request_id' => $request->id,
                'contracts'           => $contractNames,
            ]);

            $this->dispatch('toast', type: 'error', message: 'Failed to send contracts to the e-sign service.');
        }
    }

    public function confirmAndSend(EsignService $esignService) {
        $this->authorize('claims.request.send');

        if ($this->esignBlockers) {
            $this->dispatch('toast',
                type: 'error',
                message: 'Application is not ready: ' . implode(' ', $this->esignBlockers),
            );
            $this->dispatch('close-preview-modal');
            return;
        }

        $this->sendToEsign($esignService);

        $this->dispatch('close-preview-modal');
    }

    public function render() {
        return view('components.client.contracts');
    }
}
