"""
Idempotent IFRS-compliant Chart of Accounts seed.

Rules:
  - NEVER deletes existing codes (user may have created custom accounts)
  - Creates missing codes
  - Updates name / category / reporting_tag on existing codes if they differ
  - Re-wires all parent_id relationships on every run
  - Sets is_parent automatically based on parent relationships

Runs on every startup via the seed registry.
Standards: IAS 1/2/7/12/16/36/37/38/40, IFRS 9/15/16
"""

from __future__ import annotations
import uuid
from sqlalchemy.orm import Session

from app.models.accounting import AccountingCode
from .registry import register

# ─────────────────────────────────────────────────────────────────────────────
# Complete IFRS chart of accounts
# Each tuple: (code, name, account_type, category, is_parent, reporting_tag)
# ─────────────────────────────────────────────────────────────────────────────
IFRS_COA: list[tuple] = [
    # ── ASSETS 1xxx ──────────────────────────────────────────────────────────
    ("1000","Assets","Asset","Current Asset",True,None),

    # Current Assets
    ("1100","Current Assets","Asset","Current Asset",True,None),

    # Cash & Cash Equivalents (IAS 7)
    ("1110","Cash and Cash Equivalents","Asset","Cash",True,None),
    ("1111","Cash in Hand","Asset","Cash",False,None),
    ("1112","Petty Cash","Asset","Cash",False,None),
    ("1113","Credit Card Clearing","Asset","Cash",False,None),
    ("1114","Undeposited Funds","Asset","Cash",False,None),

    # Bank Accounts
    ("1120","Bank Accounts","Asset","Bank",True,None),
    ("1121","Main Bank Account","Asset","Bank",False,None),
    ("1122","Savings Account","Asset","Bank",False,None),
    ("1123","Business Cheque Account","Asset","Bank",False,None),
    ("1124","Foreign Currency Account","Asset","Bank",False,None),

    # Trade Receivables (IFRS 9 – ECL)
    ("1130","Trade and Other Receivables","Asset","Trade Receivables",True,None),
    ("1131","Accounts Receivable - Trade","Asset","Trade Receivables",False,None),
    ("1132","Allowance for Doubtful Debts","Asset","Trade Receivables",False,None),
    ("1133","Notes Receivable","Asset","Trade Receivables",False,None),
    ("1134","Staff Loans Receivable","Asset","Trade Receivables",False,None),
    ("1135","Intercompany Receivables","Asset","Trade Receivables",False,None),

    # Inventories (IAS 2)
    ("1140","Inventories","Asset","Inventory",True,None),
    ("1141","Raw Materials","Asset","Inventory",False,None),
    ("1142","Work in Progress","Asset","Inventory",False,None),
    ("1143","Finished Goods","Asset","Inventory",False,None),
    ("1144","Merchandise Inventory","Asset","Inventory",False,None),
    ("1145","Goods in Transit","Asset","Inventory",False,None),
    ("1146","Inventory Write-down Provision","Asset","Inventory",False,None),

    # Prepayments & Other Current Assets
    ("1150","Prepayments and Other Current Assets","Asset","Prepaid Expenses",True,None),
    ("1151","Prepaid Expenses","Asset","Prepaid Expenses",False,None),
    ("1152","Advance Payments to Suppliers","Asset","Prepaid Expenses",False,None),
    ("1153","Short-term Deposits","Asset","Prepaid Expenses",False,None),
    ("1154","Other Current Assets","Asset","Prepaid Expenses",False,None),

    # VAT & Tax Receivable
    ("1160","VAT and Tax Receivable","Asset","Current Asset",True,None),
    ("1161","Input VAT - Standard Rate","Asset","Current Asset",False,None),
    ("1162","Input VAT - Zero Rate","Asset","Current Asset",False,None),
    ("1163","Deferred VAT","Asset","Current Asset",False,None),
    ("1164","Corporate Tax Receivable","Asset","Current Asset",False,None),
    ("1165","PAYE Receivable","Asset","Current Asset",False,None),

    # Non-Current Assets
    ("1200","Non-Current Assets","Asset","Fixed Asset",True,None),

    # PPE – IAS 16  (reporting_tag A2.1 used by asset management)
    ("1210","Property, Plant and Equipment","Asset","Fixed Asset",True,"A2.1"),
    ("1211","Land","Asset","Fixed Asset",False,None),
    ("1212","Buildings","Asset","Fixed Asset",False,None),
    ("1213","Plant and Machinery","Asset","Fixed Asset",False,None),
    ("1214","Motor Vehicles","Asset","Fixed Asset",False,None),
    ("1215","Computer Equipment","Asset","Fixed Asset",False,None),
    ("1216","Office Furniture and Equipment","Asset","Fixed Asset",False,None),
    ("1217","Leasehold Improvements","Asset","Fixed Asset",False,None),
    ("1218","Capital Work in Progress","Asset","Fixed Asset",False,None),

    # Accumulated Depreciation – contra-asset
    ("1220","Accumulated Depreciation - PPE","Asset","Accumulated Depreciation",True,None),
    ("1221","Accum. Dep. - Buildings","Asset","Accumulated Depreciation",False,None),
    ("1222","Accum. Dep. - Plant and Machinery","Asset","Accumulated Depreciation",False,None),
    ("1223","Accum. Dep. - Motor Vehicles","Asset","Accumulated Depreciation",False,None),
    ("1224","Accum. Dep. - Computer Equipment","Asset","Accumulated Depreciation",False,None),
    ("1225","Accum. Dep. - Furniture & Equipment","Asset","Accumulated Depreciation",False,None),

    # Intangible Assets – IAS 38
    ("1230","Intangible Assets","Asset","Intangible Assets",True,None),
    ("1231","Goodwill","Asset","Intangible Assets",False,None),
    ("1232","Patents and Trademarks","Asset","Intangible Assets",False,None),
    ("1233","Computer Software and Licenses","Asset","Intangible Assets",False,None),
    ("1234","Accumulated Amortization","Asset","Accumulated Depreciation",False,None),

    # Right-of-Use Assets – IFRS 16
    ("1240","Right-of-Use Assets","Asset","Fixed Asset",True,None),
    ("1241","ROU Asset - Buildings","Asset","Fixed Asset",False,None),
    ("1242","ROU Asset - Vehicles","Asset","Fixed Asset",False,None),
    ("1243","Accum. Dep. - ROU Assets","Asset","Accumulated Depreciation",False,None),

    # Long-term Investments & Other
    ("1260","Long-term Investments and Other","Asset","Investments",True,None),
    ("1261","Investment in Subsidiaries","Asset","Investments",False,None),
    ("1262","Investment in Associates","Asset","Investments",False,None),
    ("1263","Other Long-term Investments","Asset","Investments",False,None),
    ("1264","Long-term Deposits","Asset","Investments",False,None),
    ("1265","Deferred Tax Asset","Asset","Investments",False,None),

    # ── LIABILITIES 2xxx ─────────────────────────────────────────────────────
    ("2000","Liabilities","Liability","Current Liability",True,None),

    # Current Liabilities
    ("2100","Current Liabilities","Liability","Current Liability",True,None),

    # Trade Payables
    ("2110","Trade and Other Payables","Liability","Trade Payables",True,None),
    ("2111","Accounts Payable - Trade Suppliers","Liability","Trade Payables",False,None),
    ("2112","Accrued Expenses","Liability","Accrued Liabilities",False,None),
    ("2113","Goods Received Not Invoiced","Liability","Trade Payables",False,None),
    ("2114","Customer Deposits and Advances","Liability","Deferred Revenue",False,None),

    # Short-term Borrowings
    ("2120","Short-term Borrowings","Liability","Loans Payable",True,None),
    ("2121","Bank Overdraft","Liability","Loans Payable",False,None),
    ("2122","Short-term Loans","Liability","Loans Payable",False,None),
    ("2123","Current Portion of Long-term Debt","Liability","Loans Payable",False,None),

    # Tax Liabilities
    ("2130","Tax Liabilities","Liability","Tax Payable",True,None),
    ("2131","VAT Control Account","Liability","VAT Payable",False,None),
    ("2132","VAT Payable (Output VAT)","Liability","VAT Payable",False,None),
    ("2133","VAT Receivable Contra","Liability","VAT Payable",False,None),
    ("2134","PAYE Payable","Liability","Tax Payable",False,None),
    ("2135","Corporate Tax Payable","Liability","Tax Payable",False,None),
    ("2136","Withholding Tax Payable","Liability","Tax Payable",False,None),

    # Other Current Liabilities
    ("2140","Other Current Liabilities","Liability","Current Liability",True,None),
    ("2141","Deferred Revenue","Liability","Deferred Revenue",False,None),
    ("2142","Dividends Payable","Liability","Current Liability",False,None),
    ("2143","Wages and Salaries Payable","Liability","Accrued Liabilities",False,None),
    ("2144","Intercompany Payables","Liability","Current Liability",False,None),

    # Non-Current Liabilities
    ("2200","Non-Current Liabilities","Liability","Long-Term Liability",True,None),

    # Long-term Borrowings
    ("2210","Long-term Borrowings","Liability","Loans Payable",True,None),
    ("2211","Long-term Bank Loans","Liability","Loans Payable",False,None),
    ("2212","Bonds Payable","Liability","Notes Payable",False,None),
    ("2213","Mortgage Payable","Liability","Loans Payable",False,None),

    # Lease Liabilities – IFRS 16
    ("2220","Lease Liabilities","Liability","Long-Term Liability",True,None),
    ("2221","Lease Liability - Current Portion","Liability","Current Liability",False,None),
    ("2222","Lease Liability - Non-Current","Liability","Long-Term Liability",False,None),

    # Provisions – IAS 37
    ("2230","Provisions","Liability","Long-Term Liability",True,None),
    ("2231","Provision for Employee Benefits","Liability","Long-Term Liability",False,None),
    ("2232","Provision for Warranties","Liability","Long-Term Liability",False,None),
    ("2233","Provision for Legal Claims","Liability","Long-Term Liability",False,None),
    ("2234","Provision for Restructuring","Liability","Long-Term Liability",False,None),

    # Deferred Tax – IAS 12
    ("2240","Deferred Tax Liabilities","Liability","Long-Term Liability",False,None),

    # ── EQUITY 3xxx ──────────────────────────────────────────────────────────
    ("3000","Equity","Equity","Equity Capital",True,None),

    # Share Capital
    ("3100","Share Capital","Equity","Common Stock",True,None),
    ("3110","Ordinary Share Capital","Equity","Common Stock",False,None),
    ("3120","Share Premium","Equity","Common Stock",False,None),

    # Retained Earnings
    ("3200","Retained Earnings","Equity","Retained Earnings",True,None),
    ("3210","Opening Retained Earnings","Equity","Opening Balance Equity",False,None),
    ("3220","Current Year Profit / (Loss)","Equity","Retained Earnings",False,None),
    ("3230","Dividends Declared","Equity","Dividends",False,None),

    # Other Comprehensive Income – IAS 1
    ("3300","Other Comprehensive Income Reserves","Equity","Equity Capital",True,None),
    ("3310","Revaluation Surplus","Equity","Equity Capital",False,None),
    ("3320","Foreign Currency Translation Reserve","Equity","Equity Capital",False,None),
    ("3330","Fair Value Reserve","Equity","Equity Capital",False,None),

    ("3400","Drawings / Owner Distributions","Equity","Drawings",False,None),

    # ── REVENUE 4xxx ─────────────────────────────────────────────────────────
    ("4000","Revenue","Revenue","Operating Revenue",True,None),

    # Operating Revenue – IFRS 15
    ("4100","Operating Revenue","Revenue","Operating Revenue",True,None),
    ("4110","Sales Revenue - Goods","Revenue","Sales Revenue",False,None),
    ("4120","Sales Revenue - Services","Revenue","Service Revenue",False,None),
    ("4130","Sales Returns and Allowances","Revenue","Sales Revenue",False,None),
    ("4140","Sales Discounts","Revenue","Sales Revenue",False,None),

    # Other Income
    ("4200","Other Income","Revenue","Other Revenue",True,None),
    ("4210","Interest Income","Revenue","Interest Income",False,None),
    ("4220","Dividend Income","Revenue","Dividend Income",False,None),
    ("4230","Rental Income","Revenue","Rental Income",False,None),
    ("4240","Foreign Exchange Gain","Revenue","Other Revenue",False,None),
    ("4250","Gain on Disposal of Assets","Revenue","Gain on Sale of Assets",False,None),
    ("4260","Government Grants","Revenue","Other Revenue",False,None),
    ("4270","Miscellaneous Income","Revenue","Other Revenue",False,None),

    # ── EXPENSES 5xxx ────────────────────────────────────────────────────────
    ("5000","Expenses","Expense","Operating Expense",True,None),

    # Cost of Sales (IAS 2)
    ("5100","Cost of Sales","Expense","Cost of Sales",True,None),
    ("5110","Cost of Goods Sold - Merchandise","Expense","Cost of Sales",False,None),
    ("5120","Cost of Goods Sold - Manufacturing","Expense","Cost of Sales",False,None),
    ("5130","Direct Labour","Expense","Cost of Sales",False,None),
    ("5140","Manufacturing Overhead","Expense","Cost of Sales",False,None),
    ("5150","Freight and Delivery - Inbound","Expense","Cost of Sales",False,None),
    ("5160","Inventory Write-down","Expense","Cost of Sales",False,None),

    # Selling Expenses
    ("5200","Selling and Distribution Expenses","Expense","Operating Expense",True,None),
    ("5210","Advertising and Marketing","Expense","Marketing",False,None),
    ("5220","Sales Commission","Expense","Operating Expense",False,None),
    ("5230","Freight and Delivery - Outbound","Expense","Operating Expense",False,None),
    ("5240","Customer Entertainment","Expense","Operating Expense",False,None),

    # Administrative Expenses
    ("5300","Administrative Expenses","Expense","Operating Expense",True,None),
    ("5310","Salaries and Wages","Expense","Salaries and Wages",False,None),
    ("5320","Employer Payroll Contributions","Expense","Salaries and Wages",False,None),
    ("5330","Rent and Occupancy","Expense","Rent Expense",False,None),
    ("5340","Utilities","Expense","Utilities",False,None),
    ("5350","Office Supplies and Consumables","Expense","Office Supplies",False,None),
    ("5360","Telephone and Internet","Expense","Operating Expense",False,None),
    ("5370","Insurance","Expense","Insurance",False,None),
    ("5380","Professional and Legal Fees","Expense","Professional Fees",False,None),
    ("5390","Bank Charges and Fees","Expense","Operating Expense",False,None),
    ("5391","Travel and Accommodation","Expense","Travel Expense",False,None),
    ("5392","Training and Development","Expense","Operating Expense",False,None),
    ("5393","Repairs and Maintenance","Expense","Repairs and Maintenance",False,None),
    ("5394","Printing and Stationery","Expense","Office Supplies",False,None),
    ("5395","Subscriptions and Memberships","Expense","Operating Expense",False,None),
    ("5396","Donations and Sponsorships","Expense","Operating Expense",False,None),
    ("5397","Vehicle Running Expenses","Expense","Operating Expense",False,None),
    ("5398","Security Expenses","Expense","Operating Expense",False,None),
    ("5399","Miscellaneous Expenses","Expense","Operating Expense",False,None),

    # Depreciation & Amortization (IAS 16 / IAS 38 / IFRS 16)
    ("5400","Depreciation and Amortization","Expense","Depreciation",True,None),
    ("5410","Depreciation - Buildings","Expense","Depreciation",False,None),
    ("5420","Depreciation - Plant and Machinery","Expense","Depreciation",False,None),
    ("5430","Depreciation - Motor Vehicles","Expense","Depreciation",False,None),
    ("5440","Depreciation - Equipment","Expense","Depreciation",False,None),
    ("5450","Depreciation - ROU Assets","Expense","Depreciation",False,None),
    ("5460","Amortization - Intangible Assets","Expense","Depreciation",False,None),

    # Impairment – IAS 36 / IFRS 9 ECL
    ("5500","Impairment Losses","Expense","Bad Debts",True,None),
    ("5510","Impairment - Goodwill","Expense","Bad Debts",False,None),
    ("5520","ECL - Trade Receivables (IFRS 9)","Expense","Bad Debts",False,None),
    ("5530","Impairment - Property and Equipment","Expense","Bad Debts",False,None),

    # Finance Costs
    ("5600","Finance Costs","Expense","Interest Expense",True,None),
    ("5610","Interest Expense - Bank Loans","Expense","Interest Expense",False,None),
    ("5620","Interest Expense - Lease Liabilities","Expense","Interest Expense",False,None),
    ("5630","Interest Expense - Other Borrowings","Expense","Interest Expense",False,None),
    ("5640","Foreign Exchange Loss","Expense","Operating Expense",False,None),

    # Income Tax Expense – IAS 12
    ("5700","Income Tax Expense","Expense","Tax Expense",True,None),
    ("5710","Current Tax Expense","Expense","Tax Expense",False,None),
    ("5720","Deferred Tax Expense / (Credit)","Expense","Tax Expense",False,None),
]

# Parent relationships: child_code -> parent_code
PARENTS: dict[str, str] = {
    # Assets
    "1100":"1000", "1200":"1000",
    "1110":"1100", "1120":"1100", "1130":"1100", "1140":"1100",
    "1150":"1100", "1160":"1100",
    "1111":"1110", "1112":"1110", "1113":"1110", "1114":"1110",
    "1121":"1120", "1122":"1120", "1123":"1120", "1124":"1120",
    "1131":"1130", "1132":"1130", "1133":"1130", "1134":"1130", "1135":"1130",
    "1141":"1140", "1142":"1140", "1143":"1140", "1144":"1140", "1145":"1140", "1146":"1140",
    "1151":"1150", "1152":"1150", "1153":"1150", "1154":"1150",
    "1161":"1160", "1162":"1160", "1163":"1160", "1164":"1160", "1165":"1160",
    "1210":"1200", "1220":"1200", "1230":"1200", "1240":"1200", "1260":"1200",
    "1211":"1210", "1212":"1210", "1213":"1210", "1214":"1210", "1215":"1210",
    "1216":"1210", "1217":"1210", "1218":"1210",
    "1221":"1220", "1222":"1220", "1223":"1220", "1224":"1220", "1225":"1220",
    "1231":"1230", "1232":"1230", "1233":"1230", "1234":"1230",
    "1241":"1240", "1242":"1240", "1243":"1240",
    "1261":"1260", "1262":"1260", "1263":"1260", "1264":"1260", "1265":"1260",
    # Liabilities
    "2100":"2000", "2200":"2000",
    "2110":"2100", "2120":"2100", "2130":"2100", "2140":"2100",
    "2111":"2110", "2112":"2110", "2113":"2110", "2114":"2110",
    "2121":"2120", "2122":"2120", "2123":"2120",
    "2131":"2130", "2132":"2130", "2133":"2130", "2134":"2130", "2135":"2130", "2136":"2130",
    "2141":"2140", "2142":"2140", "2143":"2140", "2144":"2140",
    "2210":"2200", "2220":"2200", "2230":"2200", "2240":"2200",
    "2211":"2210", "2212":"2210", "2213":"2210",
    "2221":"2220", "2222":"2220",
    "2231":"2230", "2232":"2230", "2233":"2230", "2234":"2230",
    # Equity
    "3100":"3000", "3200":"3000", "3300":"3000", "3400":"3000",
    "3110":"3100", "3120":"3100",
    "3210":"3200", "3220":"3200", "3230":"3200",
    "3310":"3300", "3320":"3300", "3330":"3300",
    # Revenue
    "4100":"4000", "4200":"4000",
    "4110":"4100", "4120":"4100", "4130":"4100", "4140":"4100",
    "4210":"4200", "4220":"4200", "4230":"4200", "4240":"4200",
    "4250":"4200", "4260":"4200", "4270":"4200",
    # Expenses
    "5100":"5000", "5200":"5000", "5300":"5000",
    "5400":"5000", "5500":"5000", "5600":"5000", "5700":"5000",
    "5110":"5100", "5120":"5100", "5130":"5100", "5140":"5100", "5150":"5100", "5160":"5100",
    "5210":"5200", "5220":"5200", "5230":"5200", "5240":"5200",
    "5310":"5300", "5320":"5300", "5330":"5300", "5340":"5300", "5350":"5300",
    "5360":"5300", "5370":"5300", "5380":"5300", "5390":"5300", "5391":"5300",
    "5392":"5300", "5393":"5300", "5394":"5300", "5395":"5300", "5396":"5300",
    "5397":"5300", "5398":"5300", "5399":"5300",
    "5410":"5400", "5420":"5400", "5430":"5400", "5440":"5400", "5450":"5400", "5460":"5400",
    "5510":"5500", "5520":"5500", "5530":"5500",
    "5610":"5600", "5620":"5600", "5630":"5600", "5640":"5600",
    "5710":"5700", "5720":"5700",
}


@register("accounts")
def seed_accounts(db: Session) -> None:
    """Idempotent upsert of the IFRS chart of accounts."""
    existing: dict[str, AccountingCode] = {
        c.code: c for c in db.query(AccountingCode).all()
    }
    created = updated = 0

    for code, name, a_type, cat, is_par, rtag in IFRS_COA:
        if code in existing:
            obj = existing[code]
            changed = False
            # Soft-update: only overwrite fields that differ (preserve user edits to other fields)
            if obj.name != name:
                obj.name = name; changed = True
            if str(obj.account_type) != a_type:
                obj.account_type = a_type; changed = True
            if obj.category != cat:
                obj.category = cat; changed = True
            if rtag and obj.reporting_tag != rtag:
                obj.reporting_tag = rtag; changed = True
            if changed:
                db.add(obj); updated += 1
        else:
            obj = AccountingCode(
                id=str(uuid.uuid4()),
                code=code,
                name=name,
                account_type=a_type,
                category=cat,
                is_parent=is_par,
                reporting_tag=rtag,
                balance=0.0,
                total_debits=0.0,
                total_credits=0.0,
            )
            db.add(obj)
            db.flush()
            existing[code] = obj
            created += 1

    db.flush()

    # Wire parent relationships
    for child_code, parent_code in PARENTS.items():
        child = existing.get(child_code)
        parent = existing.get(parent_code)
        if child and parent and child.parent_id != parent.id:
            child.parent_id = parent.id
            db.add(child)

    # Auto-set is_parent based on who has children
    parent_ids = {obj.parent_id for obj in existing.values() if obj.parent_id}
    for obj in existing.values():
        should_be_parent = obj.id in parent_ids
        if obj.is_parent != should_be_parent:
            obj.is_parent = should_be_parent
            db.add(obj)

    db.commit()
    total = db.query(AccountingCode).count()
    print(f"[SEED][COA] IFRS chart of accounts: {created} created, {updated} updated, {total} total")
