<?php

namespace App\Mail;

use App\Models\PackagePurchase;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;

class PurchaseConfirmation extends Mailable
{
    use Queueable, SerializesModels;

    public function __construct(public PackagePurchase $purchase)
    {
        //
    }

    public function envelope(): Envelope
    {
        return new Envelope(
            subject: __('emails.purchase.subject', ['package' => $this->localizedPackageName()]),
        );
    }

    public function content(): Content
    {
        return new Content(
            view: 'emails.purchase',
            with: [
                'purchase' => $this->purchase,
                'user' => $this->purchase->tenant->user,
                'package' => $this->purchase->package,
                'packageName' => $this->localizedPackageName(),
                'priceFormatted' => $this->formattedTotal(),
                'purchaseDate' => $this->formattedPurchaseDate(),
                'providerLabel' => $this->providerLabel(),
                'orderId' => $this->purchase->provider_id,
                'packageTypeLabel' => $this->packageTypeLabel(),
                'limits' => $this->packageLimits(),
                'invoiceUrl' => $this->resolveInvoiceUrl(),
                'ctaUrl' => route('tenant.admin.dashboard'),
            ],
        );
    }

    public function attachments(): array
    {
        return [];
    }

    private function localizedPackageName(): string
    {
        $locale = $this->locale ?? app()->getLocale();

        return optional($this->purchase->package)->getNameForLocale($locale) ?? '';
    }

    private function formattedTotal(): string
    {
        $totals = $this->purchase->metadata['paddle_totals'] ?? [];
        $currency = $totals['currency']
            ?? $this->purchase->metadata['currency']
            ?? $this->purchase->package?->currency
            ?? 'EUR';
        $amount = array_key_exists('total', $totals) ? (float) $totals['total'] : (float) $this->purchase->price;

        $locale = $this->locale ?? app()->getLocale();
        $formatter = class_exists(\NumberFormatter::class)
            ? new \NumberFormatter($this->mapLocale($locale), \NumberFormatter::CURRENCY)
            : null;

        if ($formatter) {
            $formatted = $formatter->formatCurrency($amount, $currency);
            if ($formatted !== false) {
                return $formatted;
            }
        }

        $symbol = match ($currency) {
            'EUR' => '€',
            'USD' => '$',
            default => $currency,
        };

        return number_format($amount, 2, ',', '.').' '.$symbol;
    }

    private function formattedPurchaseDate(): string
    {
        $locale = $this->locale ?? app()->getLocale();
        $date = $this->purchase->purchased_at ?? now();

        if (str_starts_with($locale, 'en')) {
            return $date->translatedFormat('F j, Y');
        }

        return $date->translatedFormat('d. F Y');
    }

    private function mapLocale(string $locale): string
    {
        $normalized = strtolower(str_replace('_', '-', $locale));

        return match (true) {
            str_starts_with($normalized, 'de') => 'de_DE',
            str_starts_with($normalized, 'en') => 'en_US',
            default => 'de_DE',
        };
    }

    private function providerLabel(): string
    {
        $provider = $this->purchase->provider ?? 'paddle';
        $labelKey = 'emails.purchase.provider.'.$provider;
        $label = __($labelKey);

        if ($label === $labelKey) {
            return ucfirst((string) $provider);
        }

        return $label;
    }

    private function packageTypeLabel(): string
    {
        $type = $this->purchase->package?->type ?? 'endcustomer';
        $labelKey = 'emails.purchase.package_type.'.$type;
        $label = __($labelKey);

        if ($label === $labelKey) {
            return ucfirst((string) $type);
        }

        return $label;
    }

    /**
     * @return array<int, array{label: string, value: string}>
     */
    private function packageLimits(): array
    {
        $package = $this->purchase->package;
        if (! $package) {
            return [];
        }

        $limits = [
            'max_photos' => $package->max_photos,
            'max_guests' => $package->max_guests,
            'gallery_days' => $package->gallery_days,
            'max_tasks' => $package->max_tasks,
            'max_events_per_year' => $package->max_events_per_year,
        ];

        $result = [];

        foreach ($limits as $key => $value) {
            if (! is_numeric($value) || (int) $value <= 0) {
                continue;
            }

            $result[] = [
                'label' => __('emails.purchase.limits.'.$key),
                'value' => number_format((int) $value, 0, ',', '.'),
            ];
        }

        return $result;
    }

    private function resolveInvoiceUrl(): ?string
    {
        $payload = $this->purchase->metadata['payload'] ?? [];

        $invoiceUrl = $payload['invoice_url'] ?? null;
        if (is_string($invoiceUrl) && $invoiceUrl !== '') {
            return $invoiceUrl;
        }

        $receiptUrl = $payload['receipt_url'] ?? null;
        if (is_string($receiptUrl) && $receiptUrl !== '') {
            return $receiptUrl;
        }

        return null;
    }
}
