"""Seed the localization tables with platform defaults.

Idempotent — safe to re-run. Uses ``update_or_create`` so administrators can
adjust fields in admin and re-seeding will only refresh seeded rows.

Architecture note:
  - Calendar belongs to Country (IR→jalali, SA→hijri), NOT to Language.
  - Language carries the numeral system (fa→persian, ar→eastern_arabic).
  - Locale = Language + Country: stores all formatting overrides.
"""

from __future__ import annotations

from typing import Any

from django.core.management.base import BaseCommand
from django.db import transaction

from simorgh.apps.localization.models import (
    CalendarSystem,
    Country,
    Currency,
    Language,
    Locale,
    NumeralSystem,
    TextDirection,
    Timezone,
)

LANGUAGES: list[dict[str, Any]] = [
    {
        "code": "en",
        "name_native": "English",
        "name_english": "English",
        "direction": TextDirection.LTR,
        "numeral_system": NumeralSystem.LATIN,
        "is_default": True,
        "sort_order": 10,
    },
    {
        "code": "fa",
        "name_native": "فارسی",
        "name_english": "Persian",
        "direction": TextDirection.RTL,
        "numeral_system": NumeralSystem.PERSIAN,
        "is_default": False,
        "sort_order": 20,
    },
    {
        "code": "ar",
        "name_native": "العربية",
        "name_english": "Arabic",
        "direction": TextDirection.RTL,
        "numeral_system": NumeralSystem.EASTERN_ARABIC,
        "is_default": False,
        "sort_order": 30,
    },
    {
        "code": "de",
        "name_native": "Deutsch",
        "name_english": "German",
        "direction": TextDirection.LTR,
        "numeral_system": NumeralSystem.LATIN,
        "is_default": False,
        "sort_order": 40,
    },
    {
        "code": "tr",
        "name_native": "Türkçe",
        "name_english": "Turkish",
        "direction": TextDirection.LTR,
        "numeral_system": NumeralSystem.LATIN,
        "is_default": False,
        "sort_order": 50,
    },
]


# (code, language_code, country_iso2, calendar_override, direction_override, numeral_override, ...)
LOCALES: list[dict[str, Any]] = [
    {
        "code": "en-US",
        "language_code": "en",
        "country_iso2": "US",
        "calendar": "",              # inherit from US country: gregorian
        "direction": "",             # inherit from en language: ltr
        "numeral_system": "",        # inherit from en language: latin
        "date_format": "MM/DD/YYYY",
        "time_format": "hh:mm A",
        "datetime_format": "MM/DD/YYYY hh:mm A",
        "first_day_of_week": 6,      # Sunday
        "number_decimal_separator": ".",
        "number_thousand_separator": ",",
        "currency_code": "USD",
        "timezone": "America/New_York",
        "is_default": True,
    },
    {
        "code": "fa-IR",
        "language_code": "fa",
        "country_iso2": "IR",
        "calendar": CalendarSystem.JALALI,   # explicit: fa in IR → jalali
        "direction": TextDirection.RTL,
        "numeral_system": NumeralSystem.PERSIAN,
        "date_format": "YYYY/MM/DD",
        "time_format": "HH:mm",
        "datetime_format": "YYYY/MM/DD HH:mm",
        "first_day_of_week": 5,      # Saturday (Iran week starts Sat)
        "number_decimal_separator": "٫",
        "number_thousand_separator": "٬",
        "currency_code": "IRR",
        "timezone": "Asia/Tehran",
        "is_default": False,
    },
    {
        "code": "ar-SA",
        "language_code": "ar",
        "country_iso2": "SA",
        "calendar": CalendarSystem.HIJRI,    # explicit: ar in SA → hijri
        "direction": TextDirection.RTL,
        "numeral_system": NumeralSystem.EASTERN_ARABIC,
        "date_format": "DD/MM/YYYY",
        "time_format": "HH:mm",
        "datetime_format": "DD/MM/YYYY HH:mm",
        "first_day_of_week": 0,      # Monday
        "number_decimal_separator": "٫",
        "number_thousand_separator": "٬",
        "currency_code": "SAR",
        "timezone": "Asia/Riyadh",
        "is_default": False,
    },
    {
        "code": "ar-AE",
        "language_code": "ar",
        "country_iso2": "AE",
        "calendar": CalendarSystem.GREGORIAN,  # UAE uses Gregorian officially
        "direction": TextDirection.RTL,
        "numeral_system": NumeralSystem.EASTERN_ARABIC,
        "date_format": "DD/MM/YYYY",
        "time_format": "HH:mm",
        "datetime_format": "DD/MM/YYYY HH:mm",
        "first_day_of_week": 0,      # Monday
        "number_decimal_separator": ".",
        "number_thousand_separator": ",",
        "currency_code": "AED",
        "timezone": "Asia/Dubai",
        "is_default": False,
    },
    {
        "code": "en-GB",
        "language_code": "en",
        "country_iso2": "GB",
        "calendar": "",              # gregorian
        "direction": "",
        "numeral_system": "",
        "date_format": "DD/MM/YYYY",
        "time_format": "HH:mm",
        "datetime_format": "DD/MM/YYYY HH:mm",
        "first_day_of_week": 0,      # Monday
        "number_decimal_separator": ".",
        "number_thousand_separator": ",",
        "currency_code": "GBP",
        "timezone": "Europe/London",
        "is_default": False,
    },
    {
        "code": "de-DE",
        "language_code": "de",
        "country_iso2": "DE",
        "calendar": "",
        "direction": "",
        "numeral_system": "",
        "date_format": "DD.MM.YYYY",
        "time_format": "HH:mm",
        "datetime_format": "DD.MM.YYYY HH:mm",
        "first_day_of_week": 0,      # Monday
        "number_decimal_separator": ",",
        "number_thousand_separator": ".",
        "currency_code": "EUR",
        "timezone": "Europe/Berlin",
        "is_default": False,
    },
    {
        "code": "tr-TR",
        "language_code": "tr",
        "country_iso2": "TR",
        "calendar": "",
        "direction": "",
        "numeral_system": "",
        "date_format": "DD.MM.YYYY",
        "time_format": "HH:mm",
        "datetime_format": "DD.MM.YYYY HH:mm",
        "first_day_of_week": 0,      # Monday
        "number_decimal_separator": ",",
        "number_thousand_separator": ".",
        "currency_code": "TRY",
        "timezone": "Europe/Istanbul",
        "is_default": False,
    },
]


TIMEZONES: list[dict[str, Any]] = [
    {"name": "UTC", "display_name": "UTC", "utc_offset": "+00:00", "sort_order": 10},
    {"name": "Asia/Tehran", "display_name": "Tehran", "utc_offset": "+03:30", "sort_order": 20},
    {"name": "Asia/Dubai", "display_name": "Dubai", "utc_offset": "+04:00", "sort_order": 30},
    {"name": "Asia/Riyadh", "display_name": "Riyadh", "utc_offset": "+03:00", "sort_order": 40},
    {"name": "Asia/Baghdad", "display_name": "Baghdad", "utc_offset": "+03:00", "sort_order": 50},
    {"name": "Asia/Kabul", "display_name": "Kabul", "utc_offset": "+04:30", "sort_order": 60},
    {"name": "Asia/Karachi", "display_name": "Karachi", "utc_offset": "+05:00", "sort_order": 70},
    {"name": "Asia/Kolkata", "display_name": "Mumbai / Kolkata", "utc_offset": "+05:30", "sort_order": 80},
    {"name": "Asia/Shanghai", "display_name": "Beijing / Shanghai", "utc_offset": "+08:00", "sort_order": 90},
    {"name": "Asia/Tokyo", "display_name": "Tokyo", "utc_offset": "+09:00", "sort_order": 100},
    {"name": "Asia/Singapore", "display_name": "Singapore", "utc_offset": "+08:00", "sort_order": 110},
    {"name": "Europe/Istanbul", "display_name": "Istanbul", "utc_offset": "+03:00", "sort_order": 120},
    {"name": "Europe/Moscow", "display_name": "Moscow", "utc_offset": "+03:00", "sort_order": 130},
    {"name": "Europe/London", "display_name": "London", "utc_offset": "+00:00", "sort_order": 140},
    {"name": "Europe/Berlin", "display_name": "Berlin / Paris", "utc_offset": "+01:00", "sort_order": 150},
    {"name": "Europe/Paris", "display_name": "Paris", "utc_offset": "+01:00", "sort_order": 155},
    {"name": "America/New_York", "display_name": "New York", "utc_offset": "-05:00", "sort_order": 160},
    {"name": "America/Chicago", "display_name": "Chicago", "utc_offset": "-06:00", "sort_order": 170},
    {"name": "America/Los_Angeles", "display_name": "Los Angeles", "utc_offset": "-08:00", "sort_order": 180},
    {"name": "Australia/Sydney", "display_name": "Sydney", "utc_offset": "+10:00", "sort_order": 190},
]


CURRENCIES: list[dict[str, Any]] = [
    {"code": "USD", "name": "United States Dollar", "symbol": "$", "decimals": 2},
    {"code": "EUR", "name": "Euro", "symbol": "€", "decimals": 2},
    {"code": "GBP", "name": "British Pound", "symbol": "£", "decimals": 2},
    {"code": "IRR", "name": "Iranian Rial", "symbol": "﷼", "decimals": 0},
    {"code": "IRT", "name": "Iranian Toman", "symbol": "تومان", "decimals": 0},
    {"code": "AED", "name": "UAE Dirham", "symbol": "د.إ", "decimals": 2},
    {"code": "SAR", "name": "Saudi Riyal", "symbol": "﷼", "decimals": 2},
    {"code": "TRY", "name": "Turkish Lira", "symbol": "₺", "decimals": 2},
    {"code": "IQD", "name": "Iraqi Dinar", "symbol": "ع.د", "decimals": 3},
    {"code": "AFN", "name": "Afghan Afghani", "symbol": "؋", "decimals": 2},
    {"code": "PKR", "name": "Pakistani Rupee", "symbol": "₨", "decimals": 2},
]


# Country defaults to update/set (iso2 → localization defaults)
COUNTRY_DEFAULTS: dict[str, dict[str, Any]] = {
    "IR": {
        "default_currency": "IRR",
        "default_calendar": CalendarSystem.JALALI,
        "default_direction": TextDirection.RTL,
        "default_timezone": "Asia/Tehran",
        "first_day_of_week": 5,   # Saturday
        "weekend_days": "4,5",    # Thursday–Friday
    },
    "US": {
        "default_currency": "USD",
        "default_calendar": CalendarSystem.GREGORIAN,
        "default_direction": TextDirection.LTR,
        "default_timezone": "America/New_York",
        "first_day_of_week": 6,   # Sunday
        "weekend_days": "5,6",    # Saturday–Sunday
    },
    "GB": {
        "default_currency": "GBP",
        "default_calendar": CalendarSystem.GREGORIAN,
        "default_direction": TextDirection.LTR,
        "default_timezone": "Europe/London",
        "first_day_of_week": 0,   # Monday
        "weekend_days": "5,6",
    },
    "DE": {
        "default_currency": "EUR",
        "default_calendar": CalendarSystem.GREGORIAN,
        "default_direction": TextDirection.LTR,
        "default_timezone": "Europe/Berlin",
        "first_day_of_week": 0,
        "weekend_days": "5,6",
    },
    "FR": {
        "default_currency": "EUR",
        "default_calendar": CalendarSystem.GREGORIAN,
        "default_direction": TextDirection.LTR,
        "default_timezone": "Europe/Paris",
        "first_day_of_week": 0,
        "weekend_days": "5,6",
    },
    "TR": {
        "default_currency": "TRY",
        "default_calendar": CalendarSystem.GREGORIAN,
        "default_direction": TextDirection.LTR,
        "default_timezone": "Europe/Istanbul",
        "first_day_of_week": 0,
        "weekend_days": "5,6",
    },
    "SA": {
        "default_currency": "SAR",
        "default_calendar": CalendarSystem.HIJRI,
        "default_direction": TextDirection.RTL,
        "default_timezone": "Asia/Riyadh",
        "first_day_of_week": 0,   # Monday
        "weekend_days": "5,6",    # Friday–Saturday
    },
    "AE": {
        "default_currency": "AED",
        "default_calendar": CalendarSystem.GREGORIAN,
        "default_direction": TextDirection.RTL,
        "default_timezone": "Asia/Dubai",
        "first_day_of_week": 0,
        "weekend_days": "5,6",
    },
    "IQ": {
        "default_currency": "IQD",
        "default_calendar": CalendarSystem.HIJRI,
        "default_direction": TextDirection.RTL,
        "default_timezone": "Asia/Baghdad",
        "first_day_of_week": 5,
        "weekend_days": "5,6",
    },
    "AF": {
        "default_currency": "AFN",
        "default_calendar": CalendarSystem.JALALI,
        "default_direction": TextDirection.RTL,
        "default_timezone": "Asia/Kabul",
        "first_day_of_week": 5,
        "weekend_days": "4,5",
    },
    "PK": {
        "default_currency": "PKR",
        "default_calendar": CalendarSystem.GREGORIAN,
        "default_direction": TextDirection.RTL,
        "default_timezone": "Asia/Karachi",
        "first_day_of_week": 0,
        "weekend_days": "5,6",
    },
}


class Command(BaseCommand):
    help = "Seed Language, Locale, Currency, Timezone reference data and update Country defaults."

    def add_arguments(self, parser) -> None:
        parser.add_argument(
            "--reset",
            action="store_true",
            help="Delete existing seeded rows before inserting.",
        )

    @transaction.atomic
    def handle(self, *args: Any, **options: Any) -> None:
        if options["reset"]:
            Locale.objects.all().delete()
            Language.objects.all().delete()
            Currency.objects.all().delete()
            Timezone.objects.all().delete()
            self.stdout.write(self.style.WARNING("Cleared existing localization data."))

        # Currencies
        for payload in CURRENCIES:
            Currency.objects.update_or_create(code=payload["code"], defaults=payload)
        self.stdout.write(f"  Seeded {len(CURRENCIES)} currencies.")

        # Languages (no default_calendar — that now lives on Country)
        for payload in LANGUAGES:
            Language.objects.update_or_create(code=payload["code"], defaults=payload)
        Language.objects.exclude(code="en").update(is_default=False)
        self.stdout.write(f"  Seeded {len(LANGUAGES)} languages.")

        # Timezones
        for payload in TIMEZONES:
            Timezone.objects.update_or_create(name=payload["name"], defaults=payload)
        self.stdout.write(f"  Seeded {len(TIMEZONES)} timezones.")

        # Locales
        for payload in LOCALES:
            lang_code = payload.pop("language_code")
            country_iso2 = payload.pop("country_iso2")
            language = Language.objects.get(code=lang_code)
            country = Country.objects.filter(iso2=country_iso2).first()
            Locale.objects.update_or_create(
                code=payload["code"],
                defaults={**payload, "language": language, "country": country},
            )
        Locale.objects.exclude(code="en-US").update(is_default=False)
        self.stdout.write(f"  Seeded {len(LOCALES)} locales.")

        # Country defaults
        updated = 0
        for iso2, defaults in COUNTRY_DEFAULTS.items():
            rows = Country.objects.filter(iso2=iso2).update(**defaults)
            updated += rows
        self.stdout.write(f"  Updated localization defaults for {updated} countries.")

        self.stdout.write(self.style.SUCCESS("Localization seed complete."))

