<?php

namespace App\Services\Esign;

use App\Models\Client\Client;
use App\Models\Contract;
use App\Services\ApplicationService;
use App\Services\PdfFormService;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;

/**
 * Produces a base64 PDF of a contract FILLED with the client's data but NOT
 * signed, for on-screen preview before sending to Fintrixor.
 *
 * The Fintrixor API has no "render filled draft" endpoint (its download is 404
 * until completed), so the preview is rendered locally: the static AcroForm
 * templates (storage/app/private/templates/<slug>.pdf) are filled with pdftk via
 * PdfFormService; Part-1/Part-3 are delegated to ApplicationService. Field names
 * match each PDF's AcroForm fields; signature fields are intentionally left blank.
 */
class ContractPreviewService
{
    /**
     * @return string|null base64-encoded PDF, or null if no preview is available.
     */
    public function base64(Contract $contract, Client $client): ?string
    {
        $slug = Str::slug($contract->name);

        // Part-1 / Part-3 are generated dynamically by ApplicationService.
        if (in_array($slug, ['part-1', 'part-3'], true)) {
            $key = $slug === 'part-1' ? 'Part 1' : 'Part 3';
            try {
                $built = app(ApplicationService::class)->build($client, [$key]);
                return $built[$key]['base64'] ?? null;
            } catch (\Throwable $e) {
                Log::warning('eSign preview (application) failed', ['contract' => $slug, 'error' => $e->getMessage()]);
                return null;
            }
        }

        // Static AcroForm contracts (cfa, loa, fee-clarity, …).
        $templateFile = $slug . '.pdf';
        if (!Storage::disk('local')->exists('templates/' . $templateFile)) {
            return null;
        }

        $outRel = 'esign-previews/' . $slug . '-' . $client->id . '-' . uniqid() . '.pdf';

        // pdftk won't create the output directory itself — ensure it exists first.
        Storage::disk('public')->makeDirectory('esign-previews');

        try {
            app(PdfFormService::class)->fill($templateFile, $this->fieldsFor($slug, $client), $outRel);
            return base64_encode(Storage::disk('public')->get($outRel));
        } catch (\Throwable $e) {
            Log::warning('eSign preview (form fill) failed', ['contract' => $slug, 'error' => $e->getMessage()]);
            return null;
        } finally {
            Storage::disk('public')->delete($outRel);   // temp render — never kept
        }
    }

    /**
     * AcroForm field map per contract slug. Field names come from the actual PDF
     * (pdftk dump_data_fields); firm details come from the client's solicitor so
     * the preview is tenant-correct. Signature fields are left blank (unsigned).
     *
     * @return array<string, string>
     */
    private function fieldsFor(string $slug, Client $client): array
    {
        $solicitor  = $client->solicitor;
        $user       = auth()->user();
        $clientName = collect([$client->name_first, $client->name_middle, $client->name_last])->filter()->implode(' ');
        $today      = date('d/m/Y');
        $reference  = str_pad((string) $client->id, 6, '0', STR_PAD_LEFT);

        $clientAddress = ($a = $client->currentAddress)
            ? collect([$a->line_1, $a->line_2, $a->line_3, $a->postcode])->filter()->implode("\n")
            : '';

        $solAddr = ($solicitor && method_exists($solicitor, 'addresses')) ? $solicitor->addresses()->first() : null;
        $firmAddress  = $solAddr ? collect([$solAddr->line_1, $solAddr->line_2, $solAddr->line_3])->filter()->implode(', ') : '';
        $firmPostcode = $solAddr->postcode ?? '';
        $witnessName  = $user ? trim($user->name_first . ' ' . $user->name_last) : '';

        return match ($slug) {
            'cfa' => [
                'reference'          => $reference,
                'client_full_name'   => $clientName,
                'client_full_name_2' => $clientName,
                'client_full_name_3' => $clientName,
                'date'               => $today,
                'date_2'             => $today,
                'date_3'             => $today,
                'reply_to'           => (string) ($solicitor->email_address ?? ''),
            ],
            'fee-clarity' => [
                'client_full_name_2' => $clientName,
                'client_full_nam'    => $clientName, // matches the PDF's (mis-named) field
                'reference'          => $reference,
                'date'               => $today,
                'date_2'             => $today,
            ],
            'loa' => [
                'client_full_name'   => $clientName,
                'client_full_name_2' => $clientName,
                'client_dob'         => $client->date_of_birth?->format('d/m/Y') ?? '',
                'client_address'     => $clientAddress,
                'prev_name'          => $client->previousNames()->first()?->fullName ?? '',
                'witness_name'       => $witnessName,
                'witness_signature'  => '', // unsigned preview
                'witness_occupation' => 'Case Handler',
                'witness_address'    => $firmAddress,
                'firm_name'          => (string) ($solicitor->name ?? ''),
                'firm_address'       => $firmAddress,
                'firm_postcode'      => $firmPostcode,
                'firm_email'         => (string) ($solicitor->email_address ?? ''),
                'firm_tel'           => (string) ($solicitor->phone_number ?? ''),
                'date'               => $today,
                'date_2'             => $today,
            ],
            default => [
                'client_full_name' => $clientName,
                'date'             => $today,
                'reference'        => $reference,
            ],
        };
    }
}
