"""One-off seed: registers translation_keys English source_text and hi/mr/hinglish
translation_values for 69 previously-unseeded app-namespace UI strings across the Reports
and Finance pages (Reports Dashboard, Planning Reports History, Reports View, Advanced
Reports, Depreciation Exceptions, Journal Export, Depreciation Run Wizard, CAG Report Pack).

These keys are already wrapped in t(key, englishFallback) calls in the frontend but were
never seeded, so hi/mr/hinglish users were seeing raw English fallback text.

Usage: docker compose exec api python seed_translations_gap_batch4_reportsB_finance.py
"""
import asyncio
import uuid
from datetime import datetime, timezone

from sqlalchemy import text
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine

from ams.core.config import settings

NAMESPACE = "app"

# key -> (english, hi, mr, hinglish)
REPORTSB_FINANCE_GAP = {
    # --- DepreciationExceptionsView.tsx ---
    "finance.deprExceptions.bookDifferences": (
        "Exceptions Found",
        "मिलीं Exceptions",
        "आढळलेल्या Exceptions",
        "Exceptions Mili",
    ),
    "finance.deprExceptions.breadcrumb": (
        "Depreciation Exceptions",
        "मूल्यह्रास अपवाद",
        "घसारा अपवाद",
        "Depreciation Exceptions",
    ),
    "finance.deprExceptions.breadcrumbFinance": (
        "Finance",
        "फाइनेंस",
        "फायनान्स",
        "Finance",
    ),
    "finance.deprExceptions.colAsset": ("Asset", "Asset", "Asset", "Asset"),
    "finance.deprExceptions.colCompaniesActDepr": (
        "Companies Act Depr.",
        "Companies Act Depr.",
        "Companies Act Depr.",
        "Companies Act Depr.",
    ),
    "finance.deprExceptions.colCompaniesActNbv": (
        "Companies Act NBV",
        "Companies Act NBV",
        "Companies Act NBV",
        "Companies Act NBV",
    ),
    "finance.deprExceptions.colIncomeTaxDepr": (
        "Income Tax Depr.",
        "Income Tax Depr.",
        "Income Tax Depr.",
        "Income Tax Depr.",
    ),
    "finance.deprExceptions.colIncomeTaxNbv": (
        "Income Tax NBV",
        "Income Tax NBV",
        "Income Tax NBV",
        "Income Tax NBV",
    ),
    "finance.deprExceptions.colIndAsDepr": (
        "Ind AS Depr.",
        "Ind AS Depr.",
        "Ind AS Depr.",
        "Ind AS Depr.",
    ),
    "finance.deprExceptions.colIndAsNbv": (
        "Ind AS NBV",
        "Ind AS NBV",
        "Ind AS NBV",
        "Ind AS NBV",
    ),
    "finance.deprExceptions.empty": (
        "No exceptions for this period — every asset's books reconciled.",
        "इस अवधि के लिए कोई Exceptions नहीं — हर asset की books मेल खा गईं।",
        "या कालावधीसाठी कोणतेही Exceptions नाहीत — प्रत्येक asset च्या books जुळल्या.",
        "Is period ke liye koi Exceptions nahi — har asset ki books match ho gayin.",
    ),
    "finance.deprExceptions.period": ("Period", "अवधि", "कालावधी", "Period"),
    "finance.deprExceptions.totalAssets": (
        "Assets Compared",
        "तुलना किए गए Assets",
        "तुलना केलेले Assets",
        "Compare kiye gaye Assets",
    ),
    "finance.deprRecon.monthLabel": ("Month", "महीना", "महिना", "Month"),
    "finance.deprRecon.yearLabel": ("Year", "वर्ष", "वर्ष", "Year"),

    # --- DepreciationRunWizardView.tsx ---
    "finance.deprRun.monthLabel": ("Month", "महीना", "महिना", "Month"),
    "finance.deprRun.yearLabel": ("Year", "वर्ष", "वर्ष", "Year"),

    # --- JournalExportView.tsx ---
    "finance.journal.formatPfmsXml": ("PFMS XML", "PFMS XML", "PFMS XML", "PFMS XML"),
    "finance.journal.formatSapCsv": ("SAP CSV", "SAP CSV", "SAP CSV", "SAP CSV"),
    "finance.journal.formatTallyXml": ("Tally XML", "Tally XML", "Tally XML", "Tally XML"),
    "finance.journal.monthLabel": ("Month", "महीना", "महिना", "Month"),
    "finance.journal.yearLabel": ("Year", "वर्ष", "वर्ष", "Year"),

    # --- AdvancedReportsView.tsx ---
    "reports.advanced.infoFieldDateRange": (
        "From / To Date", "From / To Date", "From / To Date", "From / To Date",
    ),
    "reports.advanced.infoFieldDateRangeDesc": (
        "Transfer History only: restricts the audit trail to transfers effective in this range; click Filter to apply.",
        "केवल Transfer History के लिए: audit trail को इस range में प्रभावी transfers तक सीमित करता है; लागू करने के लिए Filter पर क्लिक करें।",
        "फक्त Transfer History साठी: audit trail ला या range मध्ये प्रभावी असलेल्या transfers पुरते मर्यादित करते; लागू करण्यासाठी Filter वर क्लिक करा.",
        "Sirf Transfer History ke liye: audit trail ko is range mein effective transfers tak restrict karta hai; apply karne ke liye Filter par click karein.",
    ),
    "reports.advanced.infoFieldFeedUrl": ("Feed URL", "Feed URL", "Feed URL", "Feed URL"),
    "reports.advanced.infoFieldFeedUrlDesc": (
        "OData Feeds only: the copied link points at the API host on port 8000, not the web app's own origin.",
        "केवल OData Feeds के लिए: copy किया गया link web app के अपने origin पर नहीं, बल्कि port 8000 पर मौजूद API host पर pointing करता है।",
        "फक्त OData Feeds साठी: copy केलेली link वेब अ‍ॅपच्या स्वतःच्या origin वर नाही, तर port 8000 वरील API host वर point करते.",
        "Sirf OData Feeds ke liye: copy kiya gaya link web app ke apne origin par nahi, balki port 8000 par mojood API host par point karta hai.",
    ),
    "reports.advanced.infoFieldWindowDesc": (
        "Warranty Exposure only: 30/60/90/180-day lookahead; changing it re-fetches the report.",
        "केवल Warranty Exposure के लिए: 30/60/90/180-दिन का lookahead; इसे बदलने पर रिपोर्ट फिर से fetch होती है।",
        "फक्त Warranty Exposure साठी: 30/60/90/180-दिवसांचा lookahead; तो बदलल्यास अहवाल पुन्हा fetch होतो.",
        "Sirf Warranty Exposure ke liye: 30/60/90/180-din ka lookahead; ise change karne par report dobara fetch hoti hai.",
    ),
    "reports.advanced.infoStep2Caption": (
        "Highest-value assets expiring within a chosen window.",
        "चुनी गई window के भीतर expire होने वाले सबसे अधिक मूल्य के assets।",
        "निवडलेल्या window मध्ये expire होणाऱ्या सर्वाधिक मूल्याच्या assets.",
        "Chuni gayi window ke andar expire hone wale sabse zyada value ke assets.",
    ),
    "reports.advanced.infoStep3Caption": (
        "Every custody handoff, filterable by date range.",
        "हर custody handoff, जिसे date range के आधार पर filter किया जा सकता है।",
        "प्रत्येक custody handoff, जो date range नुसार filter करता येते.",
        "Har custody handoff, jise date range ke basis par filter kiya ja sakta hai.",
    ),
    "reports.advanced.infoStep3Label": (
        "Transfer History", "Transfer History", "Transfer History", "Transfer History",
    ),
    "reports.advanced.infoStep4Caption": (
        "Copyable live URLs for Excel/Power BI, with a 5-row preview.",
        "Excel/Power BI के लिए copy किए जा सकने वाले live URLs, साथ में 5-row का preview।",
        "Excel/Power BI साठी copy करता येणारे live URLs, सोबत 5-row चा preview.",
        "Excel/Power BI ke liye copy kiye ja sakne wale live URLs, saath mein 5-row ka preview.",
    ),
    "reports.advanced.infoStep4Label": ("OData Feeds", "OData Feeds", "OData Feeds", "OData Feeds"),

    # --- CagReportPackView.tsx ---
    "reports.cag.quarter": ("Quarter", "तिमाही", "तिमाही", "Quarter"),
    "reports.cag.year": ("Year", "वर्ष", "वर्ष", "Year"),

    # --- ReportsDashboard.tsx ---
    "reports.dashboard.info.fieldAssetType": (
        "Asset Type", "एसेट टाइप", "असेट टाइप", "Asset Type",
    ),
    "reports.dashboard.info.fieldAssetTypeDesc": (
        "Optional filter narrowing the custom report to one asset class; leave blank to include all types.",
        "एक optional filter जो custom report को एक asset class तक सीमित करता है; सभी types शामिल करने के लिए इसे खाली छोड़ें।",
        "एक optional filter जो custom report ला एका asset class पुरती मर्यादित करतो; सर्व types समाविष्ट करण्यासाठी हे रिकामे ठेवा.",
        "Ek optional filter jo custom report ko ek asset class tak limit karta hai; sabhi types include karne ke liye ise blank chhod dein.",
    ),
    "reports.dashboard.info.fieldFormat": ("Format", "फॉर्मेट", "फॉरमॅट", "Format"),
    "reports.dashboard.info.fieldFormatDesc": (
        "Output file type for the scheduled export: CSV, PDF or XLSX.",
        "scheduled export के लिए output file type: CSV, PDF या XLSX।",
        "scheduled export साठी output file type: CSV, PDF किंवा XLSX.",
        "Scheduled export ke liye output file type: CSV, PDF ya XLSX.",
    ),
    "reports.dashboard.info.fieldFrequency": ("Frequency", "फ़्रीक्वेंसी", "फ्रिक्वेन्सी", "Frequency"),
    "reports.dashboard.info.fieldFrequencyDesc": (
        "How often the scheduled report regenerates: Daily, Weekly or Monthly.",
        "scheduled report कितनी बार regenerate होती है: Daily, Weekly या Monthly।",
        "scheduled report किती वेळा regenerate होते: Daily, Weekly किंवा Monthly.",
        "Scheduled report kitni baar regenerate hoti hai: Daily, Weekly ya Monthly.",
    ),
    "reports.dashboard.info.fieldRecipients": (
        "Email (optional)", "ईमेल (वैकल्पिक)", "ईमेल (पर्यायी)", "Email (optional)",
    ),
    "reports.dashboard.info.fieldRecipientsDesc": (
        "Comma-separated email addresses to receive each scheduled export; leave blank if no email delivery is needed.",
        "हर scheduled export प्राप्त करने के लिए comma-separated email addresses; अगर email delivery की ज़रूरत नहीं है तो इसे खाली छोड़ें।",
        "प्रत्येक scheduled export प्राप्त करण्यासाठी comma-separated email addresses; email delivery आवश्यक नसल्यास हे रिकामे ठेवा.",
        "Har scheduled export receive karne ke liye comma-separated email addresses; agar email delivery ki zaroorat nahi hai to ise blank chhod dein.",
    ),
    "reports.dashboard.info.step2Caption": (
        "Browse the result table, export to CSV, or close it to pick another report.",
        "result table ब्राउज़ करें, CSV में export करें, या किसी दूसरी report चुनने के लिए इसे बंद करें।",
        "result table ब्राउझ करा, CSV मध्ये export करा, किंवा दुसरी report निवडण्यासाठी ते बंद करा.",
        "Result table browse karein, CSV mein export karein, ya doosri report choose karne ke liye ise band karein.",
    ),
    "reports.dashboard.info.step3Caption": (
        "Live depreciation, insurance coverage, ITC and budget utilisation metrics.",
        "Live depreciation, insurance coverage, ITC और budget utilisation के metrics।",
        "Live depreciation, insurance coverage, ITC आणि budget utilisation चे metrics.",
        "Live depreciation, insurance coverage, ITC aur budget utilisation ke metrics.",
    ),
    "reports.dashboard.info.step3Label": ("KPI Analytics", "KPI एनालिटिक्स", "KPI अॅनालिटिक्स", "KPI Analytics"),
    "reports.dashboard.info.step4Caption": (
        "Filter an ad-hoc report, or automate any report type on a recurring schedule.",
        "किसी ad-hoc report को फ़िल्टर करें, या किसी भी report type को recurring schedule पर automate करें।",
        "एखादी ad-hoc report फिल्टर करा, किंवा कोणत्याही report type ला recurring schedule वर automate करा.",
        "Kisi ad-hoc report ko filter karein, ya kisi bhi report type ko recurring schedule par automate karein.",
    ),
    "reports.dashboard.info.step4Label": (
        "Custom & Schedule", "Custom और Schedule", "Custom आणि Schedule", "Custom & Schedule",
    ),

    # --- ReportsView.tsx ---
    "reports.general.infoFieldAcqCost": (
        "Acquisition Cost", "अधिग्रहण लागत", "संपादन खर्च", "Acquisition Cost",
    ),
    "reports.general.infoFieldAcqCostDesc": (
        "Original booked cost of the asset; shows — when not recorded.",
        "Asset की मूल booked लागत; रिकॉर्ड न होने पर — दिखाता है।",
        "Asset ची मूळ booked किंमत; रेकॉर्ड नसल्यास — दाखवते.",
        "Asset ki original booked cost; record na hone par — dikhata hai.",
    ),
    "reports.general.infoFieldBudgetDesc": (
        "Percentage of allocated budget spent so far, paired with the count of assets pending commissioning.",
        "अब तक खर्च किए गए allocated budget का प्रतिशत, commissioning के लिए pending assets की संख्या के साथ।",
        "आतापर्यंत खर्च झालेल्या allocated budget ची टक्केवारी, commissioning साठी pending असलेल्या assets च्या संख्येसह.",
        "Ab tak spend hue allocated budget ka percentage, commissioning ke liye pending assets ki count ke saath.",
    ),
    "reports.general.infoFieldLifecycle": (
        "Lifecycle State", "लाइफसाइकिल स्थिति", "लाइफसायकल स्थिती", "Lifecycle State",
    ),
    "reports.general.infoFieldLifecycleDesc": (
        "Current status of each asset in the register (e.g. in_operation, retired) — read-only here.",
        "register में प्रत्येक asset की वर्तमान स्थिति (जैसे in_operation, retired) — यहाँ केवल read-only है।",
        "register मधील प्रत्येक asset ची सद्यस्थिती (उदा. in_operation, retired) — येथे फक्त read-only आहे.",
        "Register mein har asset ka current status (jaise in_operation, retired) — yahan sirf read-only hai.",
    ),
    "reports.general.infoStep2Caption": (
        "Latest 10 assets from /reports/asset-list.",
        "/reports/asset-list से नवीनतम 10 assets।",
        "/reports/asset-list मधून नवीनतम 10 assets.",
        "/reports/asset-list se latest 10 assets.",
    ),
    "reports.general.infoStep3Caption": (
        "Scan KPI cards and the NBV-by-class chart.",
        "KPI cards और NBV-by-class chart को स्कैन करें।",
        "KPI cards आणि NBV-by-class chart स्कॅन करा.",
        "KPI cards aur NBV-by-class chart ko scan karein.",
    ),
    "reports.general.infoStep3Label": ("Review", "समीक्षा", "पुनरावलोकन", "Review Karna"),
    "reports.general.infoStep4Caption": (
        "Download the asset table as CSV.",
        "Asset table को CSV के रूप में डाउनलोड करें।",
        "Asset table CSV स्वरूपात डाउनलोड करा.",
        "Asset table ko CSV format mein download karein.",
    ),
    "reports.general.infoStep4Label": ("Export", "एक्सपोर्ट", "एक्सपोर्ट", "Export Karna"),
    "reports.general.kpisUnavailable": (
        "Financial KPI summary isn't available for your role — the asset register below is still shown.",
        "आपके role के लिए Financial KPI summary उपलब्ध नहीं है — नीचे asset register फिर भी दिखाया गया है।",
        "तुमच्या role साठी Financial KPI summary उपलब्ध नाही — खालील asset register तरीही दाखवले आहे.",
        "Aapke role ke liye Financial KPI summary available nahi hai — neeche asset register phir bhi dikhaya gaya hai.",
    ),

    # --- PlanningReportsHistoryView.tsx ---
    "reports.planning.info.fieldCriticality": ("Criticality", "Criticality", "Criticality", "Criticality"),
    "reports.planning.info.fieldCriticalityDesc": (
        "Renewal Recommendations only lists assets scoring 4 or higher, sorted highest first.",
        "Renewal Recommendations में केवल 4 या उससे अधिक score वाले assets सूचीबद्ध होते हैं, जो सबसे ऊँचे score के क्रम में sort किए गए हैं।",
        "Renewal Recommendations मध्ये फक्त 4 किंवा त्याहून जास्त score असलेल्या assets ची यादी असते, जी सर्वाधिक score नुसार sort केलेली असते.",
        "Renewal Recommendations mein sirf 4 ya usse zyada score karne wale assets list hote hain, highest score ke order mein sorted.",
    ),
    "reports.planning.info.fieldHorizon": ("Forecast Horizon", "Forecast Horizon", "Forecast Horizon", "Forecast Horizon"),
    "reports.planning.info.fieldHorizonDesc": (
        "Restricted to 10, 20 or 30 years — both the dropdown and the backend reject any other value.",
        "10, 20 या 30 वर्षों तक सीमित — dropdown और backend दोनों किसी अन्य value को अस्वीकार करते हैं।",
        "10, 20 किंवा 30 वर्षांपुरते मर्यादित — dropdown आणि backend दोन्ही इतर कोणतीही value नाकारतात.",
        "10, 20 ya 30 years tak restricted hai — dropdown aur backend dono koi bhi other value reject kar dete hain.",
    ),
    "reports.planning.info.fieldStatus": ("Status", "स्थिति", "स्थिती", "Status"),
    "reports.planning.info.fieldStatusDesc": (
        "Always shows Pending — no background job exists yet to mark scenarios Complete or Error.",
        "हमेशा Pending दिखाता है — scenarios को Complete या Error mark करने के लिए अभी तक कोई background job मौजूद नहीं है।",
        "नेहमी Pending दाखवते — scenarios ला Complete किंवा Error म्हणून mark करण्यासाठी अजून कोणताही background job अस्तित्वात नाही.",
        "Hamesha Pending dikhata hai — scenarios ko Complete ya Error mark karne ke liye abhi tak koi background job exist nahi karta.",
    ),
    "reports.planning.info.step2Caption": (
        "Name it and pick a 10/20/30-year horizon.",
        "इसे नाम दें और 10/20/30-वर्ष का horizon चुनें।",
        "याला नाव द्या आणि 10/20/30-वर्षांचा horizon निवडा.",
        "Isse naam dein aur 10/20/30-year ka horizon choose karein.",
    ),
    "reports.planning.info.step3Caption": (
        "Every scenario saves as Pending — nothing flips it to Complete or Error yet.",
        "हर scenario Pending के रूप में save होता है — अभी तक कुछ भी इसे Complete या Error में नहीं बदलता।",
        "प्रत्येक scenario Pending म्हणून save होतो — अजून काहीही याला Complete किंवा Error मध्ये बदलत नाही.",
        "Har scenario Pending ke roop mein save hota hai — abhi tak kuch bhi ise Complete ya Error mein nahi badalta.",
    ),
    "reports.planning.info.step3Label": ("Status: Pending", "स्थिति: Pending", "स्थिती: Pending", "Status: Pending"),
    "reports.planning.info.step4Caption": (
        "Switch tabs for assets auto-flagged by criticality score, independent of scenarios.",
        "criticality score द्वारा auto-flag किए गए assets के लिए tab बदलें, जो scenarios से स्वतंत्र है।",
        "criticality score द्वारे auto-flag केलेल्या assets साठी tab बदला, जे scenarios पासून स्वतंत्र आहे.",
        "Criticality score se auto-flag hue assets ke liye tab switch karein, jo scenarios se independent hai.",
    ),
    "reports.planning.info.step4Label": (
        "Renewal Recommendations", "Renewal Recommendations", "Renewal Recommendations", "Renewal Recommendations",
    ),
}


async def seed_for_session(session: AsyncSession) -> tuple[int, int]:
    now = datetime.now(timezone.utc)
    keys_upserted = 0
    values_upserted = 0
    for key, (en, hi, mr, hinglish) in REPORTSB_FINANCE_GAP.items():
        key_id = (await session.execute(
            text("SELECT id FROM translation_keys WHERE namespace = :ns AND key = :key"),
            {"ns": NAMESPACE, "key": key},
        )).scalar_one_or_none()
        if key_id:
            await session.execute(
                text("UPDATE translation_keys SET source_text = :src WHERE id = :id"),
                {"src": en, "id": key_id},
            )
        else:
            key_id = str(uuid.uuid4())
            await session.execute(
                text("""INSERT INTO translation_keys (id, namespace, key, source_text, created_at)
                        VALUES (:id, :ns, :key, :src, :now)"""),
                {"id": key_id, "ns": NAMESPACE, "key": key, "src": en, "now": now},
            )
            keys_upserted += 1

        for lang_code, value in (("hi", hi), ("mr", mr), ("hinglish", hinglish)):
            existing = (await session.execute(
                text("SELECT id FROM translation_values WHERE key_id = :kid AND language_code = :lc"),
                {"kid": key_id, "lc": lang_code},
            )).scalar_one_or_none()
            if existing:
                await session.execute(
                    text("UPDATE translation_values SET value = :val, updated_at = :now WHERE id = :id"),
                    {"val": value, "now": now, "id": existing},
                )
            else:
                await session.execute(
                    text("""INSERT INTO translation_values (id, key_id, language_code, value, updated_by, updated_at)
                            VALUES (:id, :kid, :lc, :val, NULL, :now)"""),
                    {"id": str(uuid.uuid4()), "kid": key_id, "lc": lang_code, "val": value, "now": now},
                )
                values_upserted += 1
    await session.commit()
    return keys_upserted, values_upserted


async def main() -> None:
    engine = create_async_engine(settings.DATABASE_URL, echo=False)
    Session = async_sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)

    async with Session() as session:
        tenants = (await session.execute(
            text("SELECT id::text AS id, slug FROM public.tenants WHERE status != 'archived'")
        )).fetchall()

    for tenant in tenants:
        schema = f"tenant_{tenant.id.replace('-', '_')}"
        async with Session() as session:
            await session.execute(text(f"SET search_path TO {schema}, public"))
            try:
                k, v = await seed_for_session(session)
                print(f"  seeded {k} new keys, {v} new values: {tenant.slug}")
            except Exception as exc:
                print(f"  SKIPPED {tenant.slug}: {exc}")
                await session.rollback()

    await engine.dispose()
    print(f"Done — {len(tenants)} tenant(s) processed, {len(REPORTSB_FINANCE_GAP)} reportsB-finance-gap keys.")


if __name__ == "__main__":
    asyncio.run(main())
