"""One-off seed: registers translation_keys English source_text and hi/mr/hinglish
translation_values for the "budget-allocation" PageInfoButton content.

Usage: docker compose exec api python seed_translations_pageinfo_budget_allocation.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 = "help"

# key -> (english, hi, mr, hinglish)
BUDGET_ALLOCATION = {
    "budget-allocation.title": (
        "Budget Allocation",
        "Budget आवंटन",
        "Budget वाटप",
        "Budget Allocation",
    ),
    "budget-allocation.subtitle": (
        "Set fiscal-year budgets per cost centre and enforce maker-checker approval before they take effect.",
        "प्रत्येक cost centre के लिए fiscal-year Budget सेट करें और प्रभावी होने से पहले maker-checker approval लागू करें।",
        "प्रत्येक cost centre साठी fiscal-year Budget सेट करा आणि प्रभावी होण्यापूर्वी maker-checker approval लागू करा.",
        "Har cost centre ke liye fiscal-year Budget set karein aur effective hone se pehle maker-checker approval enforce karein.",
    ),
    "budget-allocation.body.0": (
        "Each budget line ties a fiscal year, cost centre and budget head to an approved amount. Available balance is tracked automatically as commitments and actuals post against it.",
        "प्रत्येक Budget line एक fiscal year, cost centre और budget head को एक approved amount से जोड़ती है। Commitments और actuals इसके विरुद्ध post होने पर Available balance स्वतः ट्रैक होता है।",
        "प्रत्येक Budget line एक fiscal year, cost centre आणि budget head ला एका approved amount शी जोडते. Commitments आणि actuals याविरुद्ध post झाल्यावर Available balance आपोआप ट्रॅक केली जाते.",
        "Har Budget line ek fiscal year, cost centre aur budget head ko ek approved amount se link karti hai. Jaise-jaise commitments aur actuals iske against post hote hain, Available balance automatically track hoti hai.",
    ),
    "budget-allocation.body.1": (
        "New lines start Pending and can be edited freely. Once approved, a line is locked — only View remains available.",
        "नई lines Pending स्थिति में शुरू होती हैं और स्वतंत्र रूप से edit की जा सकती हैं। Approve होने के बाद, line लॉक हो जाती है — केवल View उपलब्ध रहता है।",
        "नवीन lines Pending स्थितीत सुरू होतात आणि मुक्तपणे edit करता येतात. Approve झाल्यावर, line लॉक होते — फक्त View उपलब्ध राहते.",
        "Nayi lines Pending status mein start hoti hain aur freely edit ki ja sakti hain. Ek baar Approve hone ke baad, line lock ho jaati hai — sirf View hi available rehta hai.",
    ),
    "budget-allocation.stepsHeading": (
        "Budget line lifecycle",
        "Budget line का lifecycle",
        "Budget line चा lifecycle",
        "Budget line ka lifecycle",
    ),
    "budget-allocation.steps.0.label": ("Create", "Create", "Create", "Create"),
    "budget-allocation.steps.0.caption": (
        "Set fiscal year, cost centre, budget head and approved amount — status starts Pending.",
        "Fiscal year, cost centre, budget head और approved amount सेट करें — status Pending से शुरू होता है।",
        "Fiscal year, cost centre, budget head आणि approved amount सेट करा — status Pending ने सुरू होते.",
        "Fiscal year, cost centre, budget head aur approved amount set karein — status Pending se start hota hai.",
    ),
    "budget-allocation.steps.1.label": ("Edit", "Edit", "Edit", "Edit"),
    "budget-allocation.steps.1.caption": (
        "Pending lines can be corrected any time before approval.",
        "Pending lines को approval से पहले कभी भी ठीक किया जा सकता है।",
        "Pending lines approval होण्यापूर्वी कधीही दुरुस्त करता येतात.",
        "Pending lines ko approval se pehle kabhi bhi correct kiya ja sakta hai.",
    ),
    "budget-allocation.steps.2.label": ("Approve", "Approve", "Approve", "Approve"),
    "budget-allocation.steps.2.caption": (
        "A different user — never the creator — approves the line.",
        "एक अलग user — कभी भी creator नहीं — line को approve करता है।",
        "एक वेगळा user — कधीही creator नाही — line approve करतो.",
        "Ek different user — kabhi bhi creator nahi — line ko approve karta hai.",
    ),
    "budget-allocation.steps.3.label": ("Locked", "Locked", "Locked", "Locked"),
    "budget-allocation.steps.3.caption": (
        "Approved lines are read-only; only View is available.",
        "Approved lines read-only होती हैं; केवल View उपलब्ध होता है।",
        "Approved lines read-only असतात; फक्त View उपलब्ध असते.",
        "Approved lines read-only hoti hain; sirf View available hota hai.",
    ),
    "budget-allocation.fieldRules.0.name": ("Fiscal Year", "Fiscal Year", "Fiscal Year", "Fiscal Year"),
    "budget-allocation.fieldRules.0.description": (
        "The budget period this line applies to; defaults to the current fiscal year.",
        "वह budget अवधि जिस पर यह line लागू होती है; डिफ़ॉल्ट रूप से वर्तमान fiscal year होती है।",
        "ही line ज्या budget कालावधीसाठी लागू होते; डीफॉल्टनुसार सध्याचे fiscal year असते.",
        "Wo budget period jispar ye line apply hoti hai; default current fiscal year hota hai.",
    ),
    "budget-allocation.fieldRules.1.name": ("Cost Centre", "Cost Centre", "Cost Centre", "Cost Centre"),
    "budget-allocation.fieldRules.1.description": (
        "Which cost centre the budget is allocated against; drives available-balance tracking.",
        "किस cost centre के विरुद्ध Budget allocate किया गया है; यह available-balance tracking को नियंत्रित करता है।",
        "कोणत्या cost centre विरुद्ध Budget allocate केले आहे; हे available-balance tracking नियंत्रित करते.",
        "Kis cost centre ke against Budget allocate hua hai; ye available-balance tracking ko drive karta hai.",
    ),
    "budget-allocation.fieldRules.2.name": ("Budget Head", "Budget Head", "Budget Head", "Budget Head"),
    "budget-allocation.fieldRules.2.description": (
        "Expense category from Budget Head Masters; with cost centre it identifies the line.",
        "Budget Head Masters से expense category; cost centre के साथ मिलकर यह line की पहचान करता है।",
        "Budget Head Masters मधील expense category; cost centre सोबत मिळून हे line ओळखते.",
        "Budget Head Masters se expense category; cost centre ke saath milkar ye line ko identify karta hai.",
    ),
    "budget-allocation.fieldRules.3.name": ("Approved Amount", "Approved Amount", "Approved Amount", "Approved Amount"),
    "budget-allocation.fieldRules.3.description": (
        "The sanctioned budget ceiling; Available = Approved − Committed − Actual.",
        "स्वीकृत Budget सीमा; Available = Approved − Committed − Actual.",
        "मंजूर Budget मर्यादा; Available = Approved − Committed − Actual.",
        "Sanctioned budget ceiling; Available = Approved − Committed − Actual.",
    ),
    "budget-allocation.fieldRules.4.name": ("Status", "Status", "Status", "Status"),
    "budget-allocation.fieldRules.4.description": (
        "Pending lines can be edited or approved; Approved lines are locked to read-only.",
        "Pending lines को edit या approve किया जा सकता है; Approved lines read-only पर लॉक हो जाती हैं।",
        "Pending lines edit किंवा approve करता येतात; Approved lines read-only वर लॉक होतात.",
        "Pending lines ko edit ya approve kiya ja sakta hai; Approved lines read-only par lock ho jaati hain.",
    ),
    "budget-allocation.tip.title": (
        "Self-approval is blocked",
        "Self-approval अवरुद्ध है",
        "Self-approval अवरोधित आहे",
        "Self-approval blocked hai",
    ),
    "budget-allocation.tip.body": (
        "You can't approve a budget line you created yourself — the backend enforces this even for Super Admin. In a test environment with only one admin user, create a second user to complete approvals, or every line will stay stuck Pending.",
        "आप स्वयं द्वारा बनाई गई Budget line को approve नहीं कर सकते — backend इसे Super Admin के लिए भी लागू करता है। यदि test environment में केवल एक ही admin user है, तो approvals पूरे करने के लिए एक दूसरा user बनाएं, अन्यथा हर line Pending में अटकी रहेगी।",
        "तुम्ही स्वतः तयार केलेली Budget line approve करू शकत नाही — backend हे Super Admin साठी सुद्धा लागू करते. जर test environment मध्ये फक्त एकच admin user असेल, तर approvals पूर्ण करण्यासाठी दुसरा user तयार करा, अन्यथा प्रत्येक line Pending मध्ये अडकून राहील.",
        "Aap khud banayi hui Budget line ko approve nahi kar sakte — backend ye Super Admin ke liye bhi enforce karta hai. Agar test environment mein sirf ek hi admin user hai, to approvals complete karne ke liye ek second user banaein, warna har line Pending mein stuck reh jaayegi.",
    ),
}


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 BUDGET_ALLOCATION.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(BUDGET_ALLOCATION)} budget-allocation keys.")


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