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

Usage: docker compose exec api python seed_translations_pageinfo_physical_verification.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)
PHYSICAL_VERIFICATION = {
    "physical-verification.title": (
        "Physical Verification",
        "भौतिक सत्यापन",
        "भौतिक पडताळणी",
        "Physical Verification",
    ),
    "physical-verification.subtitle": (
        "Cycle counts and stock audits, reconciled against system quantities.",
        "Cycle count और stock audit, जिन्हें system की quantities के विरुद्ध reconcile किया जाता है।",
        "Cycle count आणि stock audit, जे system च्या quantities विरुद्ध reconcile केले जातात.",
        "Cycle counts aur stock audits, jo system ki quantities ke against reconcile kiye jaate hain.",
    ),
    "physical-verification.body.0": (
        "Scheduled and completed inventory audits, with variance reconciliation.",
        "अनुसूचित (scheduled) और पूर्ण किए गए inventory audits, variance reconciliation के साथ।",
        "नियोजित (scheduled) आणि पूर्ण झालेले inventory audits, variance reconciliation सह.",
        "Scheduled aur completed inventory audits, variance reconciliation ke saath.",
    ),
    "physical-verification.body.1": (
        "Schedule a Cycle Count, Physical Verification, or Reconciliation audit for a planned date, then record physically counted quantities per item. The system computes variance automatically against current stock — it never overwrites stock, so a separate adjustment is still needed to correct it.",
        "किसी planned date के लिए Cycle Count, Physical Verification, या Reconciliation audit शेड्यूल करें, फिर प्रत्येक item की भौतिक रूप से गिनी गई quantities दर्ज करें। सिस्टम current stock के विरुद्ध variance स्वचालित रूप से गणना करता है — यह कभी भी stock को overwrite नहीं करता, इसलिए इसे ठीक करने के लिए एक अलग adjustment अभी भी आवश्यक है।",
        "एखाद्या planned date साठी Cycle Count, Physical Verification, किंवा Reconciliation audit schedule करा, नंतर प्रत्येक item साठी प्रत्यक्ष मोजलेल्या quantities नोंदवा. सिस्टम current stock विरुद्ध variance आपोआप गणना करते — ते कधीही stock overwrite करत नाही, त्यामुळे ते दुरुस्त करण्यासाठी वेगळे adjustment अजूनही आवश्यक असते.",
        "Ek planned date ke liye Cycle Count, Physical Verification, ya Reconciliation audit schedule karein, phir har item ki physically counted quantities record karein. System current stock ke against variance automatically compute karta hai — ye kabhi bhi stock ko overwrite nahi karta, isliye ise correct karne ke liye ek separate adjustment abhi bhi zaroori hai.",
    ),
    "physical-verification.stepsHeading": (
        "Audit lifecycle",
        "ऑडिट जीवनचक्र (lifecycle)",
        "ऑडिट जीवनचक्र (lifecycle)",
        "Audit lifecycle",
    ),
    "physical-verification.steps.0.label": ("Planned", "योजनाबद्ध", "नियोजित", "Planned"),
    "physical-verification.steps.0.caption": (
        "Audit scheduled with a type and planned date.",
        "Audit को एक type और planned date के साथ शेड्यूल किया गया।",
        "Audit एका type आणि planned date सह schedule केले गेले.",
        "Audit ek type aur planned date ke saath schedule kiya gaya.",
    ),
    "physical-verification.steps.1.label": ("In Progress", "प्रगति में", "प्रगतीपथावर", "In Progress"),
    "physical-verification.steps.1.caption": (
        "Counting underway; still open to reconcile.",
        "गिनती जारी है; अभी भी reconcile करने के लिए खुला है।",
        "मोजणी सुरू आहे; अजूनही reconcile करण्यासाठी खुले आहे.",
        "Counting chal rahi hai; abhi bhi reconcile karne ke liye open hai.",
    ),
    "physical-verification.steps.2.label": ("Reconciled", "मिलान किया गया", "जुळणी झाली", "Reconciled"),
    "physical-verification.steps.2.caption": (
        "Counted quantities entered; variances calculated.",
        "गिनी गई quantities दर्ज की गईं; variances की गणना की गई।",
        "मोजलेल्या quantities नोंदवल्या गेल्या; variances ची गणना केली गेली.",
        "Counted quantities enter ki gayi; variances calculate kiye gaye.",
    ),
    "physical-verification.steps.3.label": ("Completed", "पूर्ण", "पूर्ण", "Completed"),
    "physical-verification.steps.3.caption": (
        "Closed with a completed date; results viewable via Details.",
        "एक completed date के साथ बंद किया गया; परिणाम Details के माध्यम से देखे जा सकते हैं।",
        "एका completed date सह बंद केले गेले; परिणाम Details द्वारे पाहता येतात.",
        "Ek completed date ke saath close kiya gaya; results Details ke through dekhe ja sakte hain.",
    ),
    "physical-verification.fieldRules.0.name": ("Audit Type", "ऑडिट प्रकार", "ऑडिट प्रकार", "Audit Type"),
    "physical-verification.fieldRules.0.description": (
        "Cycle Count, Physical Verification, or Reconciliation — must match the backend's fixed set of allowed types.",
        "Cycle Count, Physical Verification, या Reconciliation — यह backend के निश्चित allowed types के सेट से बिल्कुल मेल खाना चाहिए।",
        "Cycle Count, Physical Verification, किंवा Reconciliation — हे backend च्या निश्चित allowed types च्या संचाशी तंतोतंत जुळले पाहिजे.",
        "Cycle Count, Physical Verification, ya Reconciliation — backend ke fixed allowed types ke set se exactly match hona chahiye.",
    ),
    "physical-verification.fieldRules.1.name": ("Planned Date", "नियोजित तिथि", "नियोजित तारीख", "Planned Date"),
    "physical-verification.fieldRules.1.description": (
        "Optional target date for the audit; left blank if not yet scheduled.",
        "Audit के लिए वैकल्पिक (optional) target date; यदि अभी तक शेड्यूल नहीं हुआ है तो खाली छोड़ दें।",
        "Audit साठी ऐच्छिक (optional) target date; अद्याप schedule झाले नसल्यास रिकामे ठेवा.",
        "Audit ke liye optional target date; agar abhi tak schedule nahi hua hai to blank chhod dein.",
    ),
    "physical-verification.fieldRules.2.name": ("Item", "आइटम", "आयटम", "Item"),
    "physical-verification.fieldRules.2.description": (
        "Which stock item a count row applies to — picked from active items only.",
        "कौन-सा stock item किसी count row पर लागू होता है — केवल active items में से चुना जाता है।",
        "कोणता stock item एखाद्या count row ला लागू होतो — फक्त active items मधून निवडला जातो.",
        "Kaunsa stock item kisi count row par apply hota hai — sirf active items mein se pick kiya jaata hai.",
    ),
    "physical-verification.fieldRules.3.name": ("Counted Qty", "गिनी गई मात्रा", "मोजलेली मात्रा", "Counted Qty"),
    "physical-verification.fieldRules.3.description": (
        "Physically counted quantity; the system computes variance against current stock on hand.",
        "भौतिक रूप से गिनी गई quantity; सिस्टम current stock on hand के विरुद्ध variance की गणना करता है।",
        "प्रत्यक्ष मोजलेली quantity; सिस्टम current stock on hand विरुद्ध variance ची गणना करते.",
        "Physically counted quantity; system current stock on hand ke against variance compute karta hai.",
    ),
    "physical-verification.tip.title": (
        "Blank rows are dropped, not zeroed",
        "खाली rows हटा दी जाती हैं, zero नहीं की जातीं",
        "रिकाम्या rows वगळल्या जातात, zero केल्या जात नाहीत",
        "Blank rows drop ho jaati hain, zero nahi hoti",
    ),
    "physical-verification.tip.body": (
        "Only count rows with an item selected are sent when you reconcile — a row left with no item is silently skipped, not submitted as a zero count. Add a row per item you actually counted.",
        "Reconcile करते समय केवल वे count rows भेजी जाती हैं जिनमें कोई item चुना गया हो — बिना item वाली row चुपचाप छोड़ दी जाती है, न कि zero count के रूप में सबमिट होती है। जिस item की आपने वास्तव में गिनती की है, उसके लिए एक row जोड़ें।",
        "Reconcile करताना फक्त item निवडलेल्या count rows पाठवल्या जातात — item नसलेली row गुपचूप वगळली जाते, zero count म्हणून सबमिट होत नाही. आपण प्रत्यक्ष मोजलेल्या प्रत्येक item साठी एक row जोडा.",
        "Reconcile karte waqt sirf wahi count rows bheji jaati hain jinme koi item select kiya gaya ho — bina item wali row silently skip ho jaati hai, zero count ke roop mein submit nahi hoti. Jis item ko aapne actually count kiya hai uske liye ek row add karein.",
    ),
}


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 PHYSICAL_VERIFICATION.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(PHYSICAL_VERIFICATION)} physical-verification keys.")


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