<?php

namespace App\Support;

use App\Logging\SensitiveDataRedactor;
use App\Models\Client;
use App\Models\Invoice;
use App\Models\Order;
use App\Models\Ticket;

/**
 * PRC-618 — Ortak merge-field üretimi.
 *
 * Eskiden SendEmailJob içinde gömülü olan merge-field üretimi (entity-tipi
 * switch + ek alan mapping'i + per-tip getX metodları) buraya VERBATIM taşındı.
 * SendEmailJob::prepareMergeFields artık bu builder'a delege eder; SendClientSmsJob
 * (PRC-618 series C) da aynı alanları render etmek için bunu kullanır.
 *
 * Tek kaynak (DRY): merge-field mantığı SADECE burada yaşar. E-posta-özel mantık
 * (hook/unsubscribe/footer/recipient/preference) SendEmailJob'da KALIR.
 */
class ClientMergeFieldBuilder
{
    /**
     * Merge fields'ları hazırla.
     *
     * @param  string  $entityType  Entity tipi (client/ticket/order/invoice/domain/quote/cancellation_request)
     * @param  mixed   $entity      Yüklenmiş entity modeli
     * @param  array   $additionalMergeFields  Çağıran tarafın eklediği ek alanlar
     * @param  string  $language    Dil (a2_iso) — şu an merge-field üretiminde kullanılmıyor; SMS/ileride ihtiyaç olursa thread'lenir
     */
    public function build(string $entityType, $entity, array $additionalMergeFields = [], string $language = 'tr'): array
    {
        // SEC PRC-207: Merge fields cPanel password, reset token, verification
        // code gibi credential içeriyor. Tüm debug satırları redact edilir;
        // prod'da (APP_DEBUG=false) zaten yazılmaz.
        if (config('app.debug')) {
            \Log::debug('ClientMergeFieldBuilder::build - START', [
                'entity_type' => $entityType,
                'entity_class' => $entity ? get_class($entity) : 'null',
                'additionalMergeFields' => SensitiveDataRedactor::redact($additionalMergeFields ?? []),
            ]);
        }

        $mergeFields = [];

        // Type-specific merge fields
        switch ($entityType) {
            case 'client':
                $mergeFields = $this->getClientMergeFields($entity);
                break;
            case 'ticket':
                $mergeFields = $this->getTicketMergeFields($entity);
                break;
            case 'order':
                $mergeFields = $this->getOrderMergeFields($entity);
                break;
            case 'invoice':
                $mergeFields = $this->getInvoiceMergeFields($entity);
                break;
            case 'domain':
                $mergeFields = $this->getDomainMergeFields($entity);
                break;
            case 'cancellation_request':
                // Client greeting/footer alanları (FIRSTNAME/LASTNAME/CLIENT_EMAIL
                // vb.) entity->client'tan; cancellation'a özel alanlar
                // (CANCELLATIONID/REASON/...) CancellationListener'dan
                // additionalMergeFields ile gelir (PRC-491).
                $mergeFields = ($entity && $entity->client)
                    ? $this->getClientMergeFields($entity->client)
                    : [];
                break;
            case 'quote':
                // PRC-613: quote_delivery / quote_accepted FIRSTNAME/LASTNAME
                // (+ footer COMPANY_NAME vb.) için client greeting alanları
                // entity->client'tan; quote'a özel alanlar (QUOTE_NUMBER/TOTAL/
                // QUOTE_LINK/PROPOSAL_BLOCK ...) QuoteService'ten additionalMergeFields
                // ile gelir. Case eksikken default'a düşüp boş kalıyordu.
                $mergeFields = ($entity && $entity->client)
                    ? $this->getClientMergeFields($entity->client)
                    : [];
                break;
            case 'client_product':
                // PRC-625: client-facing servis maillerinin ('Product Provisioned',
                // 'Service Welcome Email', 'Service Suspension', 'Service Unsuspension',
                // SSL ...) hepsi SendEmailJob::dispatch('...', 'client_product', $cp->id)
                // ile gönderiliyor. loadEntity 'client'.'language' + 'product' eager
                // load eder ama build() switch'inde case yoktu → default'a düşüp
                // getClientMergeFields hiç çağrılmadığı için {CLIENT_NAME}/{FIRSTNAME}/
                // {LASTNAME} boş kalıyordu ("Hello {FIRSTNAME}" → "Hello ,"). Greeting/
                // footer client'tan; servise özel anlamlı alanlar entity kolonlarından.
                if ($entity && $entity->client) {
                    $mergeFields = $this->getClientMergeFields($entity->client);
                    $productName = $entity->product?->name ?? '';
                    $mergeFields['PRODUCT_NAME'] = $productName;
                    $mergeFields['SERVICE_NAME'] = $productName;
                    $mergeFields['SERVICE_DOMAIN'] = $entity->domain ?? '';
                    $mergeFields['NEXT_DUE_DATE'] = $entity->next_due_date
                        ? $entity->next_due_date->format('d.m.Y') : '';
                    // PRC-824 — renewal öncesi bilgilendirme için tutar + döngü.
                    $mergeFields['AMOUNT'] = $entity->recurring_amount !== null
                        ? number_format((float) $entity->recurring_amount, 2) : '';
                    $mergeFields['BILLING_CYCLE'] = $entity->billingcycle ?? '';
                }
                break;
            case 'client_domain':
                // PRC-625: domain lifecycle/admin client-facing mailleri (entity_type
                // 'client_domain', loadEntity 'client'.'language') aynı sınıf açık —
                // case eksikti, client greeting alanları üretilmiyordu. Greeting/footer
                // client'tan; domain'e özel anlamlı alanlar entity kolonlarından
                // (expire_date kolonu → EXPIRY_DATE).
                if ($entity && $entity->client) {
                    $mergeFields = $this->getClientMergeFields($entity->client);
                    $mergeFields['DOMAIN_NAME'] = $entity->domain ?? '';
                    $mergeFields['DOMAIN'] = $entity->domain ?? '';
                    $mergeFields['EXPIRY_DATE'] = $entity->expire_date
                        ? $entity->expire_date->format('d.m.Y') : '';
                }
                break;
            case 'affiliate':
                // PRC-625 final review (CRITICAL): affiliate maillerinin (Commission
                // Earned/Approved, Payout Paid/Rejected, Referral Bonus) hepsi
                // SendEmailJob::dispatch('...', 'affiliate', $affiliate->id, ...)
                // ile gönderiliyor. Case eksikken default'a düşüyordu →
                // getClientMergeFields hiç çağrılmadığı için FIRSTNAME/LASTNAME/
                // CLIENT_NAME/EMAIL boş kalıyor ("Merhaba ,"). Greeting/footer
                // alanları entity->client'tan; affiliate'e özel alanlar
                // (AMOUNT/PRODUCT/STATUS ...) caller'dan additionalMergeFields ile
                // gelir. quote/cancellation_request ile aynı stil.
                if ($entity && $entity->client) {
                    $mergeFields = $this->getClientMergeFields($entity->client);
                    // Affiliate'e özel anlamlı kolonlar (entity'de mevcutsa).
                    $mergeFields['AFFILIATE_CODE'] = $entity->referral_code ?? '';
                    $mergeFields['AFFILIATE_BALANCE'] = $entity->pending_balance ?? '';
                    $mergeFields['AFFILIATE_TOTAL_EARNED'] = $entity->total_earned ?? '';
                    $mergeFields['AFFILIATE_TOTAL_PAID'] = $entity->total_paid ?? '';
                }
                break;
            case 'reseller':
                // PRC-841 — reseller entity'li mailler (Admin Notification kanalı,
                // DNS/başvuru bildirimleri). Greeting/footer bağlı client'tan;
                // reseller'a özel alanlar (BRAND_NAME/ADMIN_NOTE) caller'dan gelir.
                if ($entity && $entity->client) {
                    $mergeFields = $this->getClientMergeFields($entity->client);
                    $mergeFields['BRAND_NAME'] = $entity->brand_name ?? '';
                }
                break;
            default:
                \Log::warning('ClientMergeFieldBuilder::build - Unknown entity type', [
                    'entity_type' => $entityType,
                ]);
        }

        if (config('app.debug')) {
            \Log::debug('ClientMergeFieldBuilder::build - Type-specific fields generated', [
                'entity_type' => $entityType,
                'merge_fields_count' => count($mergeFields),
                'merge_fields' => SensitiveDataRedactor::redact($mergeFields),
            ]);
        }

        // Ek merge fields'ları ekle ve mapping yap
        if (! empty($additionalMergeFields)) {
            // Template format'ına göre mapping yap
            $mappedAdditionalFields = $this->mapAdditionalFields($additionalMergeFields);
            $mergeFields = array_merge($mergeFields, $mappedAdditionalFields);
            if (config('app.debug')) {
                \Log::debug('ClientMergeFieldBuilder::build - Additional fields merged', [
                    'original_additional_fields' => SensitiveDataRedactor::redact($additionalMergeFields),
                    'mapped_additional_fields' => SensitiveDataRedactor::redact($mappedAdditionalFields),
                    'final_merge_fields' => SensitiveDataRedactor::redact($mergeFields),
                ]);
            }
        }

        // PRC-843 — mail whitelabel: alıcı brand müşterisiyse platform-kimlik
        // alanları (SITE_NAME/SITE_URL/LOGIN_URL/CLIENT_AREA_URL + logo) brand'in
        // değerleriyle EZİLİR. Bu alanlar EmailTemplateHelper::getSystemMergeFields
        // (config app.url) tarafından üretilir ama render'da passed-fields sistem
        // alanlarını override eder → burada set etmek yeterli. Queue-safe: brand
        // alıcı client'tan çözülür (BrandContext request-scoped, burada YOK).
        $brandIdentity = \App\Support\BrandMailIdentity::forClient(
            \App\Support\BrandMailIdentity::clientFromEntity($entity)
        );
        if ($brandIdentity !== null) {
            $mergeFields['SITE_NAME'] = $brandIdentity['name'];
            $mergeFields['BRAND_NAME'] = $brandIdentity['name'];
            if ($brandIdentity['logo']) {
                $mergeFields['COMPANY_LOGO'] = $brandIdentity['logo'];
                $mergeFields['BRAND_LOGO'] = $brandIdentity['logo'];
            }
            if ($brandIdentity['base_url']) {
                $base = $brandIdentity['base_url'];
                $mergeFields['SITE_URL'] = $base;
                $mergeFields['LOGIN_URL'] = $base . '/clientarea/login';
                $mergeFields['CLIENT_AREA_URL'] = $base . '/clientarea';
            }
        }

        // PRC-625: dual-emit — her kavram için HEM kanonik (INVOICE_NUMBER) HEM
        // legacy (INVOICENUM) ad doldurulur; custom içerik + seeder içeriği ikisi
        // de değer basar. Geriye-uyumlu; var olan anahtarı ezmez.
        $mergeFields = MergeFieldDictionary::expand($mergeFields);

        if (config('app.debug')) {
            \Log::debug('ClientMergeFieldBuilder::build - FINAL RESULT', [
                'total_fields_count' => count($mergeFields),
                'final_merge_fields' => SensitiveDataRedactor::redact($mergeFields),
            ]);
        }

        return $mergeFields;
    }

    /**
     * Client merge fields
     */
    private function getClientMergeFields(Client $client): array
    {
        // SEC PRC-207: client_email + isim → masked; debug-only.
        if (config('app.debug')) {
            \Log::debug('ClientMergeFieldBuilder::getClientMergeFields - START', [
                'client_id' => $client->id,
                'client_email' => SensitiveDataRedactor::maskEmail($client->email),
                'client_first_name' => SensitiveDataRedactor::maskName($client->first_name),
                'client_last_name' => SensitiveDataRedactor::maskName($client->last_name),
            ]);
        }

        // Verification code - check cache first (new system), then database (legacy)
        $verificationCode = '';
        $expiresAt = '';
        $cacheKey = "email_verification:{$client->id}";
        $verification = \Cache::get($cacheKey);

        if ($verification && isset($verification['code'])) {
            // Cache-based verification (new system)
            $verificationCode = $verification['code'];
            if (isset($verification['expires_at'])) {
                $expiresAt = $verification['expires_at']->format('d.m.Y H:i');
            }
            if (config('app.debug')) {
                \Log::debug('ClientMergeFieldBuilder::getClientMergeFields - Found cache verification', [
                    'client_id' => $client->id,
                    // SEC: verification_code asla raw değil; varlık + uzunluk yeterli.
                    'verification_code_present' => $verificationCode !== '',
                    'expires_at' => $expiresAt,
                ]);
            }
        } else {
            // Database-based verification (legacy)
            $verificationCode = $client->email_verification_code ?? '';
            $expiresAt = $client->email_verification_expires_at ?
                $client->email_verification_expires_at->format('d.m.Y H:i') : '';
            if (config('app.debug')) {
                \Log::debug('ClientMergeFieldBuilder::getClientMergeFields - Using database verification', [
                    'client_id' => $client->id,
                    'verification_code_present' => $verificationCode !== '',
                    'expires_at' => $expiresAt,
                ]);
            }
        }

        // PRC-625 final review (CRITICAL): seeder + custom içerikte {CLIENT_NAME}
        // 302+ kez kullanılıyor ama burada üretilmiyordu → caller explicit
        // geçirmedikçe HEPSİ boş kalıyordu (geniş latent açık). CLIENT_NAME
        // zaten kanonik ad (MergeFieldDictionary::CANONICAL); ad+soyad birleşimi,
        // boşsa company_name'e düş. FIRSTNAME/LASTNAME ayrı üretim KORUNUR.
        $clientName = trim(($client->first_name ?? '') . ' ' . ($client->last_name ?? ''));
        if ($clientName === '') {
            $clientName = $client->company_name ?? '';
        }

        $fields = [
            // Standard format (underscore-less) - primary format
            'CLIENTID' => $client->id,
            'CLIENT_NAME' => $clientName,
            'FIRSTNAME' => $client->first_name,
            'LASTNAME' => $client->last_name,
            'EMAIL' => $client->email,
            'CLIENTEMAIL' => $client->email,
            'COMPANY' => $client->company_name ?? '',
            'PHONE' => $client->phone ?? '',
            'USERNAME' => $client->email, // Use email as username
            'VERIFICATIONCODE' => $verificationCode,
            'VERIFICATIONURL' => route('store.auth.verify-email'),
            'LOGINURL' => route('store.auth.login'),
            'EXPIRESMINUTES' => '30',
            'EXPIRESAT' => $expiresAt,

            // Legacy format (with underscores) - only for compatibility with widely-used fields
            'CLIENT_EMAIL' => $client->email, // Widely used in footers
            'COMPANY_NAME' => $client->company_name ?? '', // Widely used
        ];

        // SEC PRC-207: VERIFICATIONCODE log'a yazılmaz; varlığı + kaynağı yeter.
        if (config('app.debug')) {
            \Log::debug('ClientMergeFieldBuilder::getClientMergeFields - RESULT', [
                'client_id' => $client->id,
                'verification_code_present' => !empty($fields['VERIFICATIONCODE']),
                'verification_source' => $verification ? 'cache' : 'database',
                'generated_fields_count' => count($fields),
            ]);
        }

        return $fields;
    }

    /**
     * Ticket merge fields
     */
    private function getTicketMergeFields(Ticket $ticket): array
    {
        // Load relationships if not loaded
        if (!$ticket->relationLoaded('clientProduct')) {
            $ticket->load(['clientProduct.product', 'clientDomain']);
        }

        // İlgili ürün/domain bilgisi
        $relatedItem = '-';
        if ($ticket->clientProduct) {
            $relatedItem = $ticket->clientProduct->product?->name ?? 'Ürün/Hizmet';
            if ($ticket->clientProduct->domain) {
                $relatedItem .= ' (' . $ticket->clientProduct->domain . ')';
            }
        } elseif ($ticket->clientDomain) {
            $relatedItem = $ticket->clientDomain->domain ?? '-';
        }

        $fields = [
            // Standard format (underscore-less) - primary format
            'TICKETID' => $ticket->id,
            'TICKETNUMBER' => $ticket->uuid ?? '',
            // PRC-596: kısa public referans (subject marker [#kod] otomatik eklenir;
            // bu değişken template'lerde de kullanılabilir)
            'TICKETREFERENCE' => $ticket->reference ?? '',
            'TICKETSUBJECT' => $ticket->title ?? '',
            'TICKETSTATUS' => $ticket->status?->name ?? '',
            'TICKETPRIORITY' => $ticket->priority ?? '',
            'TICKETDEPARTMENT' => $ticket->department?->name ?? '',
            'TICKETURL' => route('store.auth.tickets.details', $ticket->id), // Müşteri paneli linki
            'TICKETRELATEDITEM' => $relatedItem, // İlgili ürün/domain
        ];

        // Client bilgilerini de ekle
        if ($ticket->client) {
            $fields = array_merge($fields, $this->getClientMergeFields($ticket->client));
        } else {
            // PRC-604: anonim/kayıtsız ticket (client_id null) — getClientMergeFields
            // çalışmadığı için FIRSTNAME boş kalıyordu ("Merhaba ,"). Gönderenin
            // saklı görünen adına, yoksa e-posta adresine düş. Tek karar noktası;
            // anonim ticket kaynağından bağımsız.
            $fallbackName = $ticket->contact_name ?: $ticket->mail;
            $fields['FIRSTNAME'] = $fallbackName;
            $fields['LASTNAME'] = '';
            $fields['EMAIL'] = $ticket->mail ?? '';
            $fields['CLIENTEMAIL'] = $ticket->mail ?? '';
        }

        return $fields;
    }

    /**
     * Order merge fields
     */
    private function getOrderMergeFields(Order $order): array
    {
        // Load invoice relationship if not loaded
        if (! $order->relationLoaded('invoice')) {
            $order->load('invoice');
        }

        // Use customer-facing invoice URL instead of admin URL
        $orderUrl = '#';
        if ($order->invoice) {
            $orderUrl = route('store.payment.show', $order->invoice->id);
        }

        $fields = [
            // Standard format (underscore-less) - primary format
            'ORDERID' => $order->id,
            'ORDERNUMBER' => $order->order_number ?? '',
            'ORDERDATE' => $order->created_at?->format('d.m.Y') ?? '',
            'ORDERTOTAL' => $order->total ?? '',
            'ORDERSTATUS' => $order->status ?? '',
            'ORDERURL' => $orderUrl,
        ];

        // Order items'lardan product ve domain bilgilerini ekle
        $order->load(['items.product', 'items.tld']);

        $productNames = [];
        $productDescriptions = [];
        $domainNames = [];
        $domainTlds = [];

        foreach ($order->items as $item) {
            // Product items için
            if ($item->type === 'product' && $item->product) {
                $productNames[] = $item->product->name ?? '';
                $productDescriptions[] = $item->product->description ?? '';
            }

            // Domain items için
            if ($item->type === 'domain') {
                if ($item->domain_name) {
                    $domainNames[] = $item->domain_name;
                }
                if ($item->tld) {
                    $domainTlds[] = $item->tld->extension ?? '';
                }
            }

            // Item description (genel)
            if ($item->description) {
                $productDescriptions[] = $item->description;
            }
        }

        // Product ve domain bilgilerini ekle (standard format)
        $fields['PRODUCTNAME'] = ! empty($productNames) ? $productNames[0] : '';
        $fields['PRODUCTDESCRIPTION'] = ! empty($productDescriptions) ? $productDescriptions[0] : '';
        $fields['DOMAINNAME'] = ! empty($domainNames) ? $domainNames[0] : '';
        $fields['DOMAINTLD'] = ! empty($domainTlds) ? $domainTlds[0] : '';
        $fields['ALLPRODUCTS'] = implode(', ', $productNames);
        $fields['ALLDOMAINS'] = implode(', ', $domainNames);

        // Client bilgilerini de ekle
        if ($order->client) {
            $fields = array_merge($fields, $this->getClientMergeFields($order->client));
        }

        return $fields;
    }

    /**
     * Invoice merge fields
     */
    private function getInvoiceMergeFields(Invoice $invoice): array
    {
        // Get payment transaction (last successful payment from client_balances)
        $lastPayment = $invoice->successfulPayments()
            ->orderBy('created_at', 'desc')
            ->first();

        $fields = [
            // Standard format (underscore-less) - primary format
            'INVOICEID' => $invoice->id,
            'INVOICENUM' => $invoice->invoice_number ?? '',
            'INVOICENUMBER' => $invoice->invoice_number ?? '',
            'INVOICEDATE' => $invoice->issued_at?->format('d.m.Y') ?? '',
            'DUEDATE' => $invoice->due_date?->format('d.m.Y') ?? '',
            'INVOICETOTAL' => number_format($invoice->total_amount ?? 0, 2).' '.($invoice->currency->code ?? 'TRY'),
            'INVOICESTATUS' => $invoice->status ?? '',
            'INVOICEURL' => route('store.payment.show', $invoice->id),
            'RECEIPTURL' => route('store.payment.show', $invoice->id),

            // Payment information
            'PAYMENTDATE' => $lastPayment ? $lastPayment->created_at->format('d.m.Y H:i') : '-',
            'PAYMENTMETHOD' => $lastPayment ? $this->getPaymentMethodName($lastPayment->payment_gateway) : '-',
            'PAYMENTAMOUNT' => $lastPayment ? number_format($lastPayment->amount ?? 0, 2).' '.($invoice->currency->code ?? 'TRY') : '-',

            // Invoice items table
            'INVOICEITEMS' => $this->getInvoiceItemsTable($invoice),
        ];

        // Invoice'ın order'ı varsa product ve domain bilgilerini ekle
        if ($invoice->order_id) {
            $order = Order::with(['items.product', 'items.tld'])->find($invoice->order_id);
            if ($order) {
                $productNames = [];
                $productDescriptions = [];
                $domainNames = [];
                $domainTlds = [];

                foreach ($order->items as $item) {
                    // Product items için
                    if ($item->type === 'product' && $item->product) {
                        $productNames[] = $item->product->name ?? '';
                        $productDescriptions[] = $item->product->description ?? '';
                    }

                    // Domain items için
                    if ($item->type === 'domain') {
                        if ($item->domain_name) {
                            $domainNames[] = $item->domain_name;
                        }
                        if ($item->tld) {
                            $domainTlds[] = $item->tld->extension ?? '';
                        }
                    }

                    // Item description (genel)
                    if ($item->description) {
                        $productDescriptions[] = $item->description;
                    }
                }

                // Product ve domain bilgilerini ekle (standard format)
                $fields['PRODUCTNAME'] = ! empty($productNames) ? $productNames[0] : '';
                $fields['PRODUCTDESCRIPTION'] = ! empty($productDescriptions) ? $productDescriptions[0] : '';
                $fields['DOMAINNAME'] = ! empty($domainNames) ? $domainNames[0] : '';
                $fields['DOMAINTLD'] = ! empty($domainTlds) ? $domainTlds[0] : '';
                $fields['ALLPRODUCTS'] = implode(', ', $productNames);
                $fields['ALLDOMAINS'] = implode(', ', $domainNames);
            }
        }

        // Client bilgilerini de ekle
        if ($invoice->client) {
            $fields = array_merge($fields, $this->getClientMergeFields($invoice->client));
        }

        return $fields;
    }

    /**
     * Domain merge fields
     */
    private function getDomainMergeFields($domain): array
    {
        $fields = [];

        // Domain modeli henüz tam implement edilmemiş olabilir
        // Temel fields'ları kontrol edelim
        if (method_exists($domain, 'toArray')) {
            $domainArray = $domain->toArray();

            // Standard format (underscore-less) - primary format
            $fields['DOMAINID'] = $domain->id ?? '';
            $fields['DOMAINNAME'] = $domain->name ?? $domain->domain_name ?? '';
            $fields['DOMAINTLD'] = $domain->tld ?? $domain->extension ?? '';
            $fields['DOMAINREGISTRATIONDATE'] = isset($domain->registered_at) ?
                $domain->registered_at->format('d.m.Y') : '';
            $fields['DOMAINEXPIRYDATE'] = isset($domain->expires_at) ?
                $domain->expires_at->format('d.m.Y') : '';
            $fields['DOMAINSTATUS'] = $domain->status ?? '';
        }

        // Client bilgilerini de ekle
        if (isset($domain->client)) {
            $fields = array_merge($fields, $this->getClientMergeFields($domain->client));
        }

        return $fields;
    }

    /**
     * Additional fields'ları template format'ına göre map et
     */
    private function mapAdditionalFields(array $additionalFields): array
    {
        $mapped = [];

        foreach ($additionalFields as $key => $value) {
            // Orijinal key'i ekle
            $mapped[$key] = $value;

            // Template format'ına göre mapping
            switch ($key) {
                case 'VERIFICATION_CODE':
                    $mapped['VERIFICATIONCODE'] = $value; // Standard format without underscore
                    break;
                case 'EXPIRES_MINUTES':
                    $mapped['EXPIRESMINUTES'] = $value;
                    break;
                case 'EXPIRES_AT':
                    $mapped['EXPIRESAT'] = $value;
                    break;
                case 'VERIFICATION_URL':
                    $mapped['VERIFICATIONURL'] = $value;
                    break;
                case 'REPLY_MESSAGE':
                    $mapped['TICKETMESSAGE'] = $value; // Template'te TICKETMESSAGE bekleniyor
                    break;
                case 'REPLY_ID':
                    $mapped['REPLYID'] = $value;
                    break;
                case 'REPLY_DATE':
                    $mapped['REPLYDATE'] = $value;
                    break;
                case 'REPLY_TIME':
                    $mapped['REPLYTIME'] = $value;
                    break;
                case 'ADMIN_NAME':
                    $mapped['ADMINNAME'] = $value;
                    break;
                case 'ADMIN_EMAIL':
                    $mapped['ADMINEMAIL'] = $value;
                    break;
                    // Common underscore to non-underscore mappings
                case 'ORDER_ID':
                    $mapped['ORDERID'] = $value;
                    break;
                case 'INVOICE_ID':
                    $mapped['INVOICEID'] = $value;
                    break;
                case 'TICKET_ID':
                    $mapped['TICKETID'] = $value;
                    break;
                case 'CLIENT_ID':
                    $mapped['CLIENTID'] = $value;
                    break;
                case 'FIRST_NAME':
                    $mapped['FIRSTNAME'] = $value;
                    break;
                case 'LAST_NAME':
                    $mapped['LASTNAME'] = $value;
                    break;
                case 'CLIENT_EMAIL':
                    $mapped['CLIENTEMAIL'] = $value;
                    break;
                case 'COMPANY_NAME':
                    $mapped['COMPANYNAME'] = $value;
                    break;
                case 'RESET_CODE':
                    $mapped['RESETCODE'] = $value;
                    break;
                case 'INVITE_LINK':
                    $mapped['INVITELINK'] = $value;
                    break;
                case 'BONUS_AMOUNT':
                    $mapped['BONUSAMOUNT'] = $value;
                    break;
                case 'MAINTENANCE_TIME':
                    $mapped['MAINTENANCETIME'] = $value;
                    break;
                case 'ALERT_MESSAGE':
                    $mapped['ALERTMESSAGE'] = $value;
                    break;
                case 'ALERT_TYPE':
                    $mapped['ALERTTYPE'] = $value;
                    break;
                    // Payment fields
                case 'PAYMENT_DATE':
                    $mapped['PAYMENTDATE'] = $value;
                    break;
                case 'PAYMENT_METHOD':
                    $mapped['PAYMENTMETHOD'] = $value;
                    break;
                case 'PAYMENT_AMOUNT':
                    $mapped['PAYMENTAMOUNT'] = $value;
                    break;
                case 'RECEIPT_URL':
                    $mapped['RECEIPTURL'] = $value;
                    break;
                case 'INVOICE_NUM':
                    $mapped['INVOICENUM'] = $value;
                    break;
                case 'INVOICE_DATE':
                    $mapped['INVOICEDATE'] = $value;
                    break;
                case 'DUE_DATE':
                    $mapped['DUEDATE'] = $value;
                    break;
                case 'INVOICE_TOTAL':
                    $mapped['INVOICETOTAL'] = $value;
                    break;
                case 'INVOICE_URL':
                    $mapped['INVOICEURL'] = $value;
                    break;
                case 'TICKET_SUBJECT':
                    $mapped['TICKETSUBJECT'] = $value;
                    break;
                case 'TICKET_PRIORITY':
                    $mapped['TICKETPRIORITY'] = $value;
                    break;
                case 'TICKET_DEPARTMENT':
                    $mapped['TICKETDEPARTMENT'] = $value;
                    break;
                case 'TICKET_URL':
                    $mapped['TICKETURL'] = $value;
                    break;
                case 'RESET_URL':
                case 'RESET_LINK':
                    $mapped['RESETURL'] = $value;
                    break;
                    // Domain fields
                case 'REGISTRATION_DATE':
                    $mapped['REGISTRATIONDATE'] = $value;
                    break;
                case 'EXPIRY_DATE':
                    $mapped['EXPIRYDATE'] = $value;
                    break;
                case 'RENEWAL_DATE':
                    $mapped['RENEWALDATE'] = $value;
                    break;
                case 'NEW_EXPIRY_DATE':
                    $mapped['NEWEXPIRYDATE'] = $value;
                    break;
                case 'RENEWAL_PERIOD':
                    $mapped['RENEWALPERIOD'] = $value;
                    break;
                    // SSL fields
                case 'SSL_START_DATE':
                    $mapped['SSLSTARTDATE'] = $value;
                    break;
                case 'SSL_END_DATE':
                    $mapped['SSLENDDATE'] = $value;
                    break;
                case 'SSL_TYPE':
                    $mapped['SSLTYPE'] = $value;
                    break;
                    // cPanel fields
                case 'CPANEL_USERNAME':
                    $mapped['CPANELUSERNAME'] = $value;
                    break;
                case 'CPANEL_PASSWORD':
                    $mapped['CPANELPASSWORD'] = $value;
                    break;
                case 'CPANEL_URL':
                    $mapped['CPANELURL'] = $value;
                    break;
                    // Other common mappings
                case 'CARD_EXPIRY':
                    $mapped['CARDEXPIRY'] = $value;
                    break;
                case 'BILLING_URL':
                    $mapped['BILLINGURL'] = $value;
                    break;
                case 'DOMAIN_URL':
                    $mapped['DOMAINURL'] = $value;
                    break;
                case 'SERVICE_NAME':
                    $mapped['SERVICENAME'] = $value;
                    break;
                case 'CANCELLATION_ID':
                    $mapped['CANCELLATIONID'] = $value;
                    break;
                case 'CANCELLATION_REASON':
                    $mapped['CANCELLATIONREASON'] = $value;
                    break;
                case 'REQUEST_DATE':
                    $mapped['REQUESTDATE'] = $value;
                    break;
                case 'ADMIN_ORDER_URL':
                    $mapped['ADMINORDERURL'] = $value;
                    break;
                case 'ADMIN_CANCELLATION_URL':
                    $mapped['ADMINCANCELLATIONURL'] = $value;
                    break;
            }
        }

        return $mapped;
    }

    /**
     * Get payment method display name
     */
    private function getPaymentMethodName(?string $paymentMethod): string
    {
        $paymentMethods = [
            'banktransfer' => 'Banka Transferi',
            'bank_transfer' => 'Banka Transferi',
            'credit_card' => 'Kredi Kartı',
            'paypal' => 'PayPal',
            'stripe' => 'Stripe',
            'payu' => 'PayU',
            'paytr' => 'PayTR',
            'balance' => 'Hesap Bakiyesi',
            'credit' => 'Kredi',
        ];

        return $paymentMethods[strtolower($paymentMethod ?? '')] ?? $paymentMethod ?? 'Diğer';
    }

    /**
     * Get invoice items table HTML
     */
    private function getInvoiceItemsTable(Invoice $invoice): string
    {
        $items = $invoice->items;

        if ($items->isEmpty()) {
            return '';
        }

        $html = '<table style="width: 100%; border-collapse: collapse; margin: 20px 0;">';
        $html .= '<thead>';
        $html .= '<tr style="background-color: #f8f9fa;">';
        $html .= '<th style="border: 1px solid #dee2e6; padding: 12px; text-align: left;">Açıklama</th>';
        $html .= '<th style="border: 1px solid #dee2e6; padding: 12px; text-align: center;">Miktar</th>';
        $html .= '<th style="border: 1px solid #dee2e6; padding: 12px; text-align: right;">Birim Fiyat</th>';
        $html .= '<th style="border: 1px solid #dee2e6; padding: 12px; text-align: right;">Toplam</th>';
        $html .= '</tr>';
        $html .= '</thead>';
        $html .= '<tbody>';

        foreach ($items as $item) {
            $html .= '<tr>';
            $html .= '<td style="border: 1px solid #dee2e6; padding: 10px;">'.htmlspecialchars($item->description ?? '-').'</td>';
            $html .= '<td style="border: 1px solid #dee2e6; padding: 10px; text-align: center;">'.($item->quantity ?? 1).'</td>';
            $html .= '<td style="border: 1px solid #dee2e6; padding: 10px; text-align: right;">'.number_format($item->unit_price ?? 0, 2).' '.($invoice->currency->code ?? 'TRY').'</td>';
            $html .= '<td style="border: 1px solid #dee2e6; padding: 10px; text-align: right;">'.number_format($item->line_total ?? 0, 2).' '.($invoice->currency->code ?? 'TRY').'</td>';
            $html .= '</tr>';
        }

        $html .= '</tbody>';
        $html .= '<tfoot style="background-color: #f8f9fa;">';

        // Subtotal
        if ($invoice->subtotal > 0) {
            $html .= '<tr>';
            $html .= '<td colspan="3" style="border: 1px solid #dee2e6; padding: 10px; text-align: right;"><strong>Ara Toplam:</strong></td>';
            $html .= '<td style="border: 1px solid #dee2e6; padding: 10px; text-align: right;"><strong>'.number_format($invoice->subtotal, 2).' '.($invoice->currency->code ?? 'TRY').'</strong></td>';
            $html .= '</tr>';
        }

        // Tax
        if ($invoice->tax_amount > 0) {
            $html .= '<tr>';
            $html .= '<td colspan="3" style="border: 1px solid #dee2e6; padding: 10px; text-align: right;">Vergi ('.($invoice->tax_rate ?? 0).'%):</td>';
            $html .= '<td style="border: 1px solid #dee2e6; padding: 10px; text-align: right;">'.number_format($invoice->tax_amount, 2).' '.($invoice->currency->code ?? 'TRY').'</td>';
            $html .= '</tr>';
        }

        // Discount
        if ($invoice->discount_amount > 0) {
            $html .= '<tr>';
            $html .= '<td colspan="3" style="border: 1px solid #dee2e6; padding: 10px; text-align: right; color: #28a745;">İndirim:</td>';
            $html .= '<td style="border: 1px solid #dee2e6; padding: 10px; text-align: right; color: #28a745;">-'.number_format($invoice->discount_amount, 2).' '.($invoice->currency->code ?? 'TRY').'</td>';
            $html .= '</tr>';
        }

        // Total
        $html .= '<tr style="background-color: #e9ecef;">';
        $html .= '<td colspan="3" style="border: 1px solid #dee2e6; padding: 12px; text-align: right;"><strong>TOPLAM:</strong></td>';
        $html .= '<td style="border: 1px solid #dee2e6; padding: 12px; text-align: right;"><strong style="font-size: 1.1em;">'.number_format($invoice->total_amount ?? 0, 2).' '.($invoice->currency->code ?? 'TRY').'</strong></td>';
        $html .= '</tr>';

        $html .= '</tfoot>';
        $html .= '</table>';

        return $html;
    }
}
