<?php

namespace App\Services\Task;

use App\Models\Agency\Agency;
use App\Models\Customer\Customer;
use App\Models\DayTour\DayTourDate;
use App\Models\InternationalTour\InternationalTourDate;
use App\Models\Product\DayTripTourDate;
use App\Models\Sale\Sale;
use App\Models\Task\Task;
use App\Models\Tour\TourDate;
use App\Services\Operation\OperationService;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Carbon;

/**
 * Otomatik görev şablonlarındaki {{token}} değişkenleri (ContractRenderService
 * kalıbıyla). Acente, kural başına başlık/açıklama şablonu tanımlarken bu
 * değişkenleri metne ekler; görev oluşturulurken ilişkili kayıtlardan dolar.
 */
class TaskTemplateVariables
{
    public const GROUPS = [
        'musteri' => 'Müşteri',
        'satis' => 'Satış',
        'tur' => 'Tur / Kalkış',
        'fatura' => 'Fatura',
        'gorev' => 'Görev',
        'tetik' => 'Tetikleyici',
        'acente' => 'Acente',
        'genel' => 'Genel',
    ];

    /** token => [etiket, grup] */
    public const TOKENS = [
        // Müşteri — kimlik & iletişim
        'musteri.ad_soyad' => ['Müşteri Adı Soyadı', 'musteri'],
        'musteri.telefon' => ['Müşteri Telefonu', 'musteri'],
        'musteri.telefon2' => ['Müşteri 2. Telefonu', 'musteri'],
        'musteri.email' => ['Müşteri E-postası', 'musteri'],
        'musteri.tip' => ['Müşteri Tipi (Şirket/Kişi)', 'musteri'],
        'musteri.dogum_tarihi' => ['Doğum Tarihi', 'musteri'],
        'musteri.tc_kimlik' => ['T.C. Kimlik No', 'musteri'],
        'musteri.pasaport_no' => ['Pasaport No', 'musteri'],
        'musteri.pasaport_bitis' => ['Pasaport Geçerlilik Tarihi', 'musteri'],
        'musteri.uyruk' => ['Uyruk', 'musteri'],
        'musteri.adres' => ['Adres', 'musteri'],
        'musteri.sehir' => ['Şehir', 'musteri'],
        'musteri.ulke' => ['Ülke', 'musteri'],
        // Müşteri — kurumsal
        'musteri.firma' => ['Firma Adı', 'musteri'],
        'musteri.vergi_no' => ['Firma Vergi No', 'musteri'],
        'musteri.vergi_dairesi' => ['Firma Vergi Dairesi', 'musteri'],
        // Müşteri — finans & geçmiş
        'musteri.bakiye' => ['Cari Bakiye', 'musteri'],
        'musteri.kredi_limiti' => ['Kredi Limiti', 'musteri'],
        'musteri.vade_gunu' => ['Ödeme Vadesi (gün)', 'musteri'],
        'musteri.toplam_rezervasyon' => ['Toplam Rezervasyon Sayısı', 'musteri'],
        'musteri.toplam_harcama' => ['Toplam Harcama', 'musteri'],
        'musteri.son_rezervasyon' => ['Son Rezervasyon Tarihi', 'musteri'],
        'musteri.segment' => ['Müşteri Segmenti', 'musteri'],
        'musteri.temsilci' => ['Atanmış Temsilci', 'musteri'],

        // Satış
        'satis.kod' => ['Satış Kodu', 'satis'],
        'satis.baslik' => ['Satış Başlığı', 'satis'],
        'satis.tutar' => ['Toplam Tutar', 'satis'],
        'satis.odenen' => ['Ödenen Tutar', 'satis'],
        'satis.kalan' => ['Kalan Bakiye', 'satis'],
        'satis.indirim' => ['İndirim Tutarı', 'satis'],
        'satis.vergi' => ['Vergi Tutarı', 'satis'],
        'satis.para_birimi' => ['Para Birimi', 'satis'],
        'satis.durum' => ['Satış Durumu', 'satis'],
        'satis.odeme_durumu' => ['Ödeme Durumu', 'satis'],
        'satis.tarih' => ['Satış Başlangıç Tarihi', 'satis'],
        'satis.bitis_tarihi' => ['Satış Bitiş Tarihi', 'satis'],
        'satis.pax' => ['Toplam Yolcu Sayısı', 'satis'],
        'satis.yetiskin' => ['Yetişkin Sayısı', 'satis'],
        'satis.cocuk' => ['Çocuk Sayısı', 'satis'],
        'satis.bebek' => ['Bebek Sayısı', 'satis'],
        'satis.kaynak' => ['Satış Kaynağı', 'satis'],
        'satis.olusturulma' => ['Satış Kayıt Tarihi', 'satis'],

        // Tur / Kalkış
        'tur.ad' => ['Tur Adı', 'tur'],
        'tur.kod' => ['Tur Kodu', 'tur'],
        'kalkis.tarih' => ['Kalkış Tarihi', 'tur'],
        'kalkis.bitis' => ['Dönüş Tarihi', 'tur'],
        'kalkis.kod' => ['Kalkış Kodu', 'tur'],
        'kalkis.sure' => ['Süre (gün/gece)', 'tur'],
        'kalkis.dolu' => ['Dolu Koltuk (satılan+rezerve)', 'tur'],
        'kalkis.satilan' => ['Satılan Koltuk', 'tur'],
        'kalkis.rezerve' => ['Rezerve Koltuk', 'tur'],
        'kalkis.kapasite' => ['Toplam Kapasite', 'tur'],
        'kalkis.kalan' => ['Kalan Kapasite', 'tur'],
        'kalkis.min_katilimci' => ['Minimum Katılımcı', 'tur'],
        'kalkis.kesinlesme_vadesi' => ['Kesinleşme Son Tarihi', 'tur'],
        'kalkis.kapora_vadesi' => ['Kapora Son Tarihi', 'tur'],
        'kalkis.bakiye_vadesi' => ['Bakiye Ödeme Son Tarihi', 'tur'],

        // Fatura
        'fatura.no' => ['Fatura Numarası', 'fatura'],
        'fatura.tarih' => ['Fatura Kesim Tarihi', 'fatura'],
        'fatura.tip' => ['Fatura Türü (Satış/İade)', 'fatura'],
        'fatura.durum' => ['Fatura Durumu', 'fatura'],
        'fatura.resmi_durum' => ['Resmi Fatura Durumu', 'fatura'],
        'fatura.muhatap' => ['Fatura Muhatabı', 'fatura'],
        'fatura.muhatap_tipi' => ['Muhatap Tipi (Şahıs/Şirket)', 'fatura'],
        'fatura.vergi_no' => ['Muhatap Vergi/TC No', 'fatura'],
        'fatura.tutar' => ['Fatura Genel Toplamı', 'fatura'],
        'fatura.kdv' => ['Fatura KDV Toplamı', 'fatura'],
        'fatura.indirim' => ['Fatura İndirim Toplamı', 'fatura'],
        'fatura.para_birimi' => ['Fatura Para Birimi', 'fatura'],
        'fatura.kalem_sayisi' => ['Fatura Kalem Sayısı', 'fatura'],

        // Görev (eskalasyonda: geciken görev)
        'gorev.baslik' => ['Geciken Görev Başlığı', 'gorev'],
        'gorev.son_tarih' => ['Geciken Görev Son Tarihi', 'gorev'],
        'gorev.durum' => ['Geciken Görev Durumu', 'gorev'],
        'gorev.oncelik' => ['Geciken Görev Önceliği', 'gorev'],
        'gorev.atananlar' => ['Geciken Görevin Atananları', 'gorev'],

        // Acente
        'acente.ad' => ['Acente Adı', 'acente'],
        'acente.telefon' => ['Acente Telefonu', 'acente'],
        'acente.email' => ['Acente E-postası', 'acente'],
        'acente.adres' => ['Acente Adresi', 'acente'],
        'acente.yetkili' => ['Acente Yetkilisi', 'acente'],
        'acente.vergi_no' => ['Acente Vergi No', 'acente'],
        'acente.web' => ['Acente Web Sitesi', 'acente'],

        // Genel
        'tarih.bugun' => ['Bugünün Tarihi', 'genel'],
        'tarih.saat' => ['Şu Anki Saat', 'genel'],
        'tarih.yil' => ['İçinde Bulunulan Yıl', 'genel'],
    ];

    /** Tetikleyiciye özgü context değişkenleri: trigger => token => [etiket, context anahtarı] */
    public const TRIGGER_TOKENS = [
        'departure_guaranteed' => ['tetik.mod' => ['Kesinleşme Şekli (otomatik/manuel)', 'mode_label']],
        'departure_prep_incomplete' => ['tetik.eksikler' => ['Eksik Operasyonel Onaylar', 'missing']],
        'offer_stale' => ['tetik.gun' => ['Yanıtsız Geçen Gün', 'days']],
        'payment_deadline_missed' => ['tetik.vade_turu' => ['Geçilen Vade Türü', 'deadline_label']],
        'payment_received' => [
            'tetik.tutar' => ['Alınan Ödeme Tutarı', 'amount'],
            'tetik.tamami' => ['"Tamamı tahsil edildi" notu', 'paid_suffix'],
        ],
        'task_overdue_escalation' => ['tetik.gun' => ['Gecikme (gün)', 'days']],
        'invoice_official_pending_stale' => ['tetik.gun' => ['Beklemede Geçen Gün', 'days']],
    ];

    /** Tetikleyici başına kullanılabilir değişken grupları */
    public const TRIGGER_GROUPS = [
        'deadline_missed_min_pax' => ['tur', 'acente', 'genel'],
        'departure_guaranteed' => ['tur', 'acente', 'genel'],
        'guarantee_deadline_near' => ['tur', 'acente', 'genel'],
        'departure_prep_incomplete' => ['tur', 'acente', 'genel'],
        'departure_completed' => ['tur', 'acente', 'genel'],
        'departure_cancelled' => ['tur', 'acente', 'genel'],
        'sale_created' => ['satis', 'musteri', 'tur', 'acente', 'genel'],
        'sale_confirmed' => ['satis', 'musteri', 'tur', 'acente', 'genel'],
        'sale_cancelled' => ['satis', 'musteri', 'tur', 'acente', 'genel'],
        'offer_stale' => ['satis', 'musteri', 'acente', 'genel'],
        'departure_soon_unpaid' => ['satis', 'musteri', 'acente', 'genel'],
        'payment_deadline_missed' => ['satis', 'musteri', 'tur', 'acente', 'genel'],
        'payment_received' => ['satis', 'musteri', 'acente', 'genel'],
        'task_overdue_escalation' => ['gorev', 'acente', 'genel'],
        'passport_expiring' => ['musteri', 'satis', 'acente', 'genel'],
        'invoice_created' => ['fatura', 'satis', 'musteri', 'acente', 'genel'],
        'invoice_official_issued' => ['fatura', 'satis', 'musteri', 'acente', 'genel'],
        'invoice_cancelled' => ['fatura', 'satis', 'musteri', 'acente', 'genel'],
        'invoice_official_pending_stale' => ['fatura', 'satis', 'musteri', 'acente', 'genel'],
    ];

    /**
     * Kurallar ekranındaki değişken kütüphanesi için: tetikleyiciye uygun
     * gruplu token listesi. [{group, token, label}, ...]
     */
    public static function catalogFor(string $trigger): array
    {
        $groups = self::TRIGGER_GROUPS[$trigger] ?? ['acente', 'genel'];
        $out = [];

        foreach (self::TOKENS as $token => [$label, $group]) {
            if (in_array($group, $groups, true)) {
                $out[] = ['group' => self::GROUPS[$group], 'token' => $token, 'label' => $label];
            }
        }

        foreach (self::TRIGGER_TOKENS[$trigger] ?? [] as $token => [$label]) {
            $out[] = ['group' => self::GROUPS['tetik'], 'token' => $token, 'label' => $label];
        }

        return $out;
    }

    /**
     * Görev oluşturulurken tüm token değerlerini ilişkili kayıtlardan üretir.
     *
     * @param Model   $source    Tetikleyen ana kayıt
     * @param Model[] $relations Ek ilişkili kayıtlar (müşteri, kalkış…)
     */
    public static function values(string $trigger, Model $source, array $relations, array $context, int $agencyId): array
    {
        $models = array_merge([$source], array_values($relations));

        $firstOf = function (string ...$classes) use ($models): ?Model {
            foreach ($models as $m) {
                foreach ($classes as $class) {
                    if ($m instanceof $class) {
                        return $m;
                    }
                }
            }

            return null;
        };

        /** @var ?Customer $customer */
        $customer = $firstOf(Customer::class);
        /** @var ?Sale $sale */
        $sale = $firstOf(Sale::class);
        $date = $firstOf(TourDate::class, InternationalTourDate::class, DayTourDate::class, DayTripTourDate::class);
        $task = $source instanceof Task ? $source : null;
        /** @var ?\App\Models\Sale\SaleInvoice $invoice */
        $invoice = $firstOf(\App\Models\Sale\SaleInvoice::class);

        if (! $sale && $invoice?->sale_id) {
            $sale = $invoice->sale;
        }
        if (! $customer && $invoice?->customer_id) {
            $customer = $invoice->customer;
        }
        if (! $customer && $sale) {
            $customer = $sale->customer;
        }

        $money = fn ($v) => $v !== null ? number_format((float) $v, 2, ',', '.') : '';
        $day = fn ($v) => $v ? Carbon::parse($v)->format('d.m.Y') : '';

        $vals = [];

        // Müşteri — kimlik & iletişim
        $vals['musteri.ad_soyad'] = $customer?->full_name ?? '';
        $vals['musteri.telefon'] = $customer?->phone ?? '';
        $vals['musteri.telefon2'] = $customer?->phone_alt ?? '';
        $vals['musteri.email'] = $customer?->email ?? '';
        $vals['musteri.tip'] = $customer ? ($customer->customer_type === 'corporate' ? 'Şirket' : 'Kişi') : '';
        $vals['musteri.dogum_tarihi'] = $day($customer?->birth_date);
        $vals['musteri.tc_kimlik'] = $customer?->national_id ?? '';
        $vals['musteri.pasaport_no'] = $customer?->passport_number ?? '';
        $vals['musteri.pasaport_bitis'] = $day($customer?->passport_expiry);
        $vals['musteri.uyruk'] = $customer?->nationality ?? '';
        $vals['musteri.adres'] = $customer?->address ?? '';
        $vals['musteri.sehir'] = $customer?->city ?? '';
        $vals['musteri.ulke'] = $customer?->country ?? '';
        // Müşteri — kurumsal
        $vals['musteri.firma'] = $customer?->company_name ?? '';
        $vals['musteri.vergi_no'] = $customer?->company_tax_number ?? '';
        $vals['musteri.vergi_dairesi'] = $customer?->company_tax_office ?? '';
        // Müşteri — finans & geçmiş
        $vals['musteri.bakiye'] = $money($customer?->current_balance);
        $vals['musteri.kredi_limiti'] = $money($customer?->credit_limit);
        $vals['musteri.vade_gunu'] = $customer?->payment_term_days !== null ? (string) $customer?->payment_term_days : '';
        $vals['musteri.toplam_rezervasyon'] = $customer?->total_bookings !== null ? (string) $customer?->total_bookings : '';
        $vals['musteri.toplam_harcama'] = $money($customer?->total_spent);
        $vals['musteri.son_rezervasyon'] = $day($customer?->last_booking_date);
        $vals['musteri.segment'] = $customer?->customer_segment ?? '';
        $vals['musteri.temsilci'] = $customer?->assigned_agent_id
            ? (\App\Models\User::find($customer->assigned_agent_id)?->full_name ?? '')
            : '';

        // Satış
        $paymentStatusLabels = ['unpaid' => 'Ödenmedi', 'partial' => 'Kısmi Ödendi', 'paid' => 'Ödendi', 'refunded' => 'İade Edildi'];
        $vals['satis.kod'] = $sale?->sale_code ?? '';
        $vals['satis.baslik'] = $sale?->title ?? '';
        $vals['satis.tutar'] = $money($sale?->total_amount);
        $vals['satis.odenen'] = $money($sale?->paid_amount);
        $vals['satis.kalan'] = $money($sale?->remaining_amount);
        $vals['satis.indirim'] = $money($sale?->discount_amount);
        $vals['satis.vergi'] = $money($sale?->tax_amount);
        $vals['satis.para_birimi'] = $sale?->currency ?? '';
        $vals['satis.durum'] = $sale ? Sale::getStatusLabel($sale->status) : '';
        $vals['satis.odeme_durumu'] = $sale ? ($paymentStatusLabels[$sale->payment_status] ?? (string) $sale->payment_status) : '';
        $vals['satis.tarih'] = $day($sale?->start_date);
        $vals['satis.bitis_tarihi'] = $day($sale?->end_date);
        $vals['satis.pax'] = $sale
            ? (string) ((int) $sale->adult_count + (int) $sale->child_count + (int) $sale->infant_count)
            : '';
        $vals['satis.yetiskin'] = $sale ? (string) (int) $sale->adult_count : '';
        $vals['satis.cocuk'] = $sale ? (string) (int) $sale->child_count : '';
        $vals['satis.bebek'] = $sale ? (string) (int) $sale->infant_count : '';
        $vals['satis.kaynak'] = $sale?->source ?? '';
        $vals['satis.olusturulma'] = $day($sale?->created_at);

        // Tur / Kalkış
        $tourName = '';
        $tourCode = '';
        if ($date) {
            $ops = app(OperationService::class);
            $cap = $ops->capacityOf($date);
            $tour = $ops->tourOf($date);
            $tourName = $tour?->name ?? '';
            $tourCode = (string) ($tour?->code ?? '');

            $days = (int) ($date->duration_days ?? 0);
            $nights = (int) ($date->duration_nights ?? 0);

            $vals['kalkis.tarih'] = $ops->startDateOf($date)?->format('d.m.Y') ?? '';
            $vals['kalkis.bitis'] = $ops->endDateOf($date)?->format('d.m.Y') ?? '';
            $vals['kalkis.kod'] = (string) ($date->code ?? '');
            $vals['kalkis.sure'] = $days > 0 ? ($days . ' gün' . ($nights > 0 ? ' / ' . $nights . ' gece' : '')) : '';
            $vals['kalkis.dolu'] = (string) $cap['used'];
            $vals['kalkis.satilan'] = (string) $cap['sold'];
            $vals['kalkis.rezerve'] = (string) $cap['reserved'];
            $vals['kalkis.kapasite'] = (string) $cap['total'];
            $vals['kalkis.kalan'] = (string) $cap['remaining'];
            $vals['kalkis.min_katilimci'] = (string) $ops->guaranteeConfigOf($date)['threshold'];
            $vals['kalkis.kesinlesme_vadesi'] = $day($date->guarantee_deadline ?? null);
            $vals['kalkis.kapora_vadesi'] = $day($date->deposit_deadline ?? null);
            $vals['kalkis.bakiye_vadesi'] = $day($date->full_payment_deadline ?? null);
        } else {
            foreach (['kalkis.tarih', 'kalkis.bitis', 'kalkis.kod', 'kalkis.sure', 'kalkis.dolu', 'kalkis.satilan',
                      'kalkis.rezerve', 'kalkis.kapasite', 'kalkis.kalan', 'kalkis.min_katilimci',
                      'kalkis.kesinlesme_vadesi', 'kalkis.kapora_vadesi', 'kalkis.bakiye_vadesi'] as $t) {
                $vals[$t] = '';
            }
        }
        // Tur adı: kalkış yoksa satış başlığından (ör. pasaport tetikleyicisi)
        $vals['tur.ad'] = $tourName !== '' ? $tourName : ($context['tour'] ?? ($sale?->title ?? ''));
        $vals['tur.kod'] = $tourCode;

        // Fatura
        $invoiceSnap = $invoice?->billing_snapshot ?? [];
        $vals['fatura.no'] = $invoice?->invoice_number ?? '';
        $vals['fatura.tarih'] = $day($invoice?->issue_date);
        $vals['fatura.tip'] = $invoice?->type_label ?? '';
        $vals['fatura.durum'] = $invoice?->status_label ?? '';
        $vals['fatura.resmi_durum'] = $invoice?->official_status_label ?? '';
        $vals['fatura.muhatap'] = $invoice?->billing_name ?? '';
        $vals['fatura.muhatap_tipi'] = $invoice?->billing_type_label ?? '';
        $vals['fatura.vergi_no'] = $invoiceSnap['tax_number'] ?? '';
        $vals['fatura.tutar'] = $money($invoice?->amount);
        $vals['fatura.kdv'] = $money($invoice?->tax_total);
        $vals['fatura.indirim'] = $money($invoice?->discount_total);
        $vals['fatura.para_birimi'] = $invoice?->currency ?? '';
        $vals['fatura.kalem_sayisi'] = $invoice ? (string) count((array) $invoice->items) : '';

        // Görev (eskalasyon)
        $vals['gorev.baslik'] = $task?->title ?? '';
        // Saat girilmemiş görevlerde yanıltıcı "00:00" yazılmaz
        $vals['gorev.son_tarih'] = $task?->due_date?->format($task->due_has_time ? 'd.m.Y H:i' : 'd.m.Y') ?? '';
        $vals['gorev.durum'] = $task ? $task->statusMeta()['label'] : '';
        $vals['gorev.oncelik'] = $task ? $task->priorityMeta()['label'] : '';
        $vals['gorev.atananlar'] = $task ? $task->assignees->map(fn ($u) => $u->full_name)->implode(', ') : '';

        // Acente
        $agency = Agency::find($agencyId);
        $vals['acente.ad'] = $agency?->name ?? '';
        $vals['acente.telefon'] = $agency?->contact_phone ?? '';
        $vals['acente.email'] = $agency?->contact_email ?? '';
        $vals['acente.adres'] = $agency?->contact_address ?? '';
        $vals['acente.yetkili'] = $agency?->contact_person ?? '';
        $vals['acente.vergi_no'] = $agency?->tax_number ?? '';
        $vals['acente.web'] = $agency?->website_url ?? '';

        // Genel
        $vals['tarih.bugun'] = now()->format('d.m.Y');
        $vals['tarih.saat'] = now()->format('H:i');
        $vals['tarih.yil'] = now()->format('Y');

        // Tetikleyici context değişkenleri
        foreach (self::TRIGGER_TOKENS[$trigger] ?? [] as $token => [, $contextKey]) {
            $vals[$token] = (string) ($context[$contextKey] ?? '');
        }

        return $vals;
    }
}
