<?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 Livewire\Component;

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

    public Client $client;

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

    public function processSignature(EsignService $esignService, ApplicationService $appService): void {
        if (empty($this->selectedContractIds)) {
            $this->dispatch('toast', type: 'error', message: 'Please select at least one contract.');
            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->sendToEsign($esignService);

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

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