<?php

namespace App\Services;

use App\Models\CompanySetting;
use App\Models\Customer;
use App\Models\EmailTemplate;
use App\Models\Invoice;
use App\Models\Payment;
use App\Models\Quotation;
use Illuminate\Support\Str;

/**
 * Resolves {placeholders} in email subjects and HTML bodies from live data.
 */
class EmailTemplateService
{
    public function sanitizeBody(string $html): string
    {
        $html = preg_replace('/<script\b[^>]*>.*?<\/script>/is', '', $html) ?? '';
        $html = preg_replace('/\s(on\w+|javascript:)\s*=\s*("[^"]*"|\'[^\']*\'|[^\s>]+)/i', '', $html) ?? '';

        return $html;
    }

    public function getTemplate(string $slug): ?EmailTemplate
    {
        return EmailTemplate::findActiveBySlug($slug);
    }

    /**
     * @param  array<string, string>  $extra
     * @return array<string, string>
     */
    public function mergePlaceholders(array $base, array $extra): array
    {
        return array_merge($base, $extra);
    }

    public function apply(string $content, array $placeholders): string
    {
        foreach ($placeholders as $key => $value) {
            $k = Str::of($key)->trim()->toString();
            $v = (string) $value;
            $content = str_replace('{'.$k.'}', $v, $content);
            $content = str_replace('{{'.$k.'}}', $v, $content);
        }

        return $content;
    }

    /**
     * @return array<string, string>
     */
    public function basePlaceholders(?Customer $customer = null): array
    {
        $c = CompanySetting::getSettings();

        return [
            'customer_name' => $customer?->name ?? '',
            'company_name' => $c->company_name ?? config('app.name', ''),
            'company_email' => $c->company_email ?? '',
            'company_phone' => $c->company_phone ?? '',
            'company_address' => $this->formatCompanyAddress($c),
            'today_date' => now()->format('M j, Y'),
        ];
    }

    /**
     * @return array<string, string>
     */
    public function invoicePlaceholders(Invoice $invoice): array
    {
        $invoice->loadMissing('customer');

        return array_merge($this->basePlaceholders($invoice->customer), [
            'invoice_number' => $invoice->invoice_number,
            'invoice_total' => (string) $invoice->total,
            'invoice_due_date' => $invoice->due_date?->format('M j, Y') ?? '',
            'invoice_status' => ucfirst((string) $invoice->status),
            'invoice_balance' => (string) $invoice->balance,
            'invoice_view_link' => $invoice->getPublicUrl(),
        ]);
    }

    /**
     * @return array<string, string>
     */
    public function quotationPlaceholders(Quotation $quotation): array
    {
        $quotation->loadMissing('customer');

        return array_merge($this->basePlaceholders($quotation->customer), [
            'quotation_number' => $quotation->quotation_number,
            'quotation_total' => (string) $quotation->total,
            'quotation_expiry_date' => $quotation->expiry_date?->format('M j, Y') ?? '',
            'quotation_view_link' => $quotation->getPublicUrl(),
        ]);
    }

    /**
     * @return array<string, string>
     */
    public function paymentPlaceholders(Payment $payment): array
    {
        $payment->loadMissing(['invoice', 'customer']);

        $base = $this->basePlaceholders($payment->customer);
        if ($payment->invoice) {
            $base = $this->mergePlaceholders($base, $this->invoicePlaceholders($payment->invoice));
        }

        return $this->mergePlaceholders($base, [
            'payment_amount' => (string) $payment->amount,
            'payment_date' => $payment->payment_date?->format('M j, Y') ?? '',
            'payment_reference' => $payment->payment_number.($payment->reference ? ' / '.$payment->reference : ''),
        ]);
    }

    private function formatCompanyAddress(CompanySetting $c): string
    {
        $parts = array_filter([
            $c->company_address ?? null,
            $c->company_city ?? null,
            $c->company_state ?? null,
            $c->company_zip ?? null,
            $c->company_country ?? null,
        ]);

        return implode(', ', $parts);
    }
}
