"""Predefined Chart of Accounts templates + import."""
from __future__ import annotations

from uuid import UUID

from sqlalchemy.ext.asyncio import AsyncSession

from app.models.foundation import Account, ChartOfAccounts
from app.models.types import AccountCategory, AccountStatus, AccountType
from app.repositories.foundation import AccountRepository, ChartOfAccountsRepository
from app.schemas.foundation import CoaTemplateAccount, CoaTemplateRead
from shared.exceptions import AppError, NotFoundError

COA_TEMPLATES: dict[str, CoaTemplateRead] = {
    "general-trading": CoaTemplateRead(
        id="general-trading",
        name="بازرگانی عمومی",
        description="چارت استاندارد برای کسب‌وکارهای بازرگانی و خرده‌فروشی",
        business_type="trading",
        accounts=[
            CoaTemplateAccount(
                code="1",
                name="دارایی‌ها",
                account_type=AccountType.ASSET,
                account_category=AccountCategory.CURRENT_ASSET,
                level=1,
                is_group=True,
                is_postable=False,
            ),
            CoaTemplateAccount(
                code="11",
                name="دارایی‌های جاری",
                account_type=AccountType.ASSET,
                account_category=AccountCategory.CURRENT_ASSET,
                level=2,
                is_group=True,
                is_postable=False,
                parent_code="1",
            ),
            CoaTemplateAccount(
                code="1101",
                name="صندوق",
                account_type=AccountType.ASSET,
                account_category=AccountCategory.CURRENT_ASSET,
                level=3,
                parent_code="11",
            ),
            CoaTemplateAccount(
                code="1102",
                name="بانک",
                account_type=AccountType.ASSET,
                account_category=AccountCategory.CURRENT_ASSET,
                level=3,
                parent_code="11",
            ),
            CoaTemplateAccount(
                code="1103",
                name="حساب‌های دریافتنی",
                account_type=AccountType.ASSET,
                account_category=AccountCategory.CURRENT_ASSET,
                level=3,
                parent_code="11",
            ),
            CoaTemplateAccount(
                code="2",
                name="بدهی‌ها",
                account_type=AccountType.LIABILITY,
                account_category=AccountCategory.CURRENT_LIABILITY,
                level=1,
                is_group=True,
                is_postable=False,
            ),
            CoaTemplateAccount(
                code="21",
                name="بدهی‌های جاری",
                account_type=AccountType.LIABILITY,
                account_category=AccountCategory.CURRENT_LIABILITY,
                level=2,
                is_group=True,
                is_postable=False,
                parent_code="2",
            ),
            CoaTemplateAccount(
                code="2101",
                name="حساب‌های پرداختنی",
                account_type=AccountType.LIABILITY,
                account_category=AccountCategory.CURRENT_LIABILITY,
                level=3,
                parent_code="21",
            ),
            CoaTemplateAccount(
                code="3",
                name="حقوق صاحبان سهام",
                account_type=AccountType.EQUITY,
                account_category=AccountCategory.EQUITY,
                level=1,
                is_group=True,
                is_postable=False,
            ),
            CoaTemplateAccount(
                code="3101",
                name="سرمایه",
                account_type=AccountType.EQUITY,
                account_category=AccountCategory.EQUITY,
                level=2,
                parent_code="3",
            ),
            CoaTemplateAccount(
                code="4",
                name="درآمدها",
                account_type=AccountType.REVENUE,
                account_category=AccountCategory.OPERATING_REVENUE,
                level=1,
                is_group=True,
                is_postable=False,
            ),
            CoaTemplateAccount(
                code="4101",
                name="فروش کالا",
                account_type=AccountType.REVENUE,
                account_category=AccountCategory.OPERATING_REVENUE,
                level=2,
                parent_code="4",
            ),
            CoaTemplateAccount(
                code="5",
                name="هزینه‌ها",
                account_type=AccountType.EXPENSE,
                account_category=AccountCategory.OPERATING_EXPENSE,
                level=1,
                is_group=True,
                is_postable=False,
            ),
            CoaTemplateAccount(
                code="5101",
                name="بهای تمام‌شده کالای فروش‌رفته",
                account_type=AccountType.EXPENSE,
                account_category=AccountCategory.OPERATING_EXPENSE,
                level=2,
                parent_code="5",
            ),
            CoaTemplateAccount(
                code="5201",
                name="هزینه‌های اداری",
                account_type=AccountType.EXPENSE,
                account_category=AccountCategory.OPERATING_EXPENSE,
                level=2,
                parent_code="5",
            ),
        ],
    ),
    "services": CoaTemplateRead(
        id="services",
        name="خدمات حرفه‌ای",
        description="چارت ساده برای شرکت‌های خدماتی و مشاوره",
        business_type="services",
        accounts=[
            CoaTemplateAccount(
                code="1",
                name="دارایی‌ها",
                account_type=AccountType.ASSET,
                account_category=AccountCategory.CURRENT_ASSET,
                level=1,
                is_group=True,
                is_postable=False,
            ),
            CoaTemplateAccount(
                code="1101",
                name="صندوق و بانک",
                account_type=AccountType.ASSET,
                account_category=AccountCategory.CURRENT_ASSET,
                level=2,
                parent_code="1",
            ),
            CoaTemplateAccount(
                code="1102",
                name="مطالبات مشتریان",
                account_type=AccountType.ASSET,
                account_category=AccountCategory.CURRENT_ASSET,
                level=2,
                parent_code="1",
            ),
            CoaTemplateAccount(
                code="2",
                name="بدهی‌ها",
                account_type=AccountType.LIABILITY,
                account_category=AccountCategory.CURRENT_LIABILITY,
                level=1,
                is_group=True,
                is_postable=False,
            ),
            CoaTemplateAccount(
                code="2101",
                name="بدهی‌های جاری",
                account_type=AccountType.LIABILITY,
                account_category=AccountCategory.CURRENT_LIABILITY,
                level=2,
                parent_code="2",
            ),
            CoaTemplateAccount(
                code="3",
                name="حقوق صاحبان سهام",
                account_type=AccountType.EQUITY,
                account_category=AccountCategory.EQUITY,
                level=1,
                is_group=True,
                is_postable=False,
            ),
            CoaTemplateAccount(
                code="3101",
                name="سرمایه",
                account_type=AccountType.EQUITY,
                account_category=AccountCategory.EQUITY,
                level=2,
                parent_code="3",
            ),
            CoaTemplateAccount(
                code="4",
                name="درآمد خدمات",
                account_type=AccountType.REVENUE,
                account_category=AccountCategory.OPERATING_REVENUE,
                level=1,
                is_group=False,
                is_postable=True,
            ),
            CoaTemplateAccount(
                code="5",
                name="هزینه‌های عملیاتی",
                account_type=AccountType.EXPENSE,
                account_category=AccountCategory.OPERATING_EXPENSE,
                level=1,
                is_group=False,
                is_postable=True,
            ),
        ],
    ),
}


async def import_coa_template(
    session: AsyncSession,
    *,
    tenant_id: UUID,
    template_id: str,
    chart_id: UUID | None = None,
    chart_name: str | None = None,
    chart_code: str | None = None,
) -> list[Account]:
    tpl = COA_TEMPLATES.get(template_id)
    if tpl is None:
        raise NotFoundError("قالب یافت نشد", error_code="template_not_found")

    chart_repo = ChartOfAccountsRepository(session)
    account_repo = AccountRepository(session)

    if chart_id is not None:
        chart = await chart_repo.get(tenant_id, chart_id)
        if chart is None:
            raise NotFoundError("دفتر حساب یافت نشد", error_code="chart_not_found")
    else:
        code = chart_code or f"TPL-{template_id[:12].upper()}"
        existing = await chart_repo.get_by_code(tenant_id, code)
        if existing is not None:
            raise AppError("کد دفتر حساب تکراری است", status_code=409, error_code="chart_code_exists")
        chart = ChartOfAccounts(
            tenant_id=tenant_id,
            name=chart_name or tpl.name,
            code=code,
            description=tpl.description,
            is_default=False,
            is_active=True,
        )
        await chart_repo.add(chart)
        await session.flush()

    created: list[Account] = []
    code_to_id: dict[str, UUID] = {}
    for item in sorted(tpl.accounts, key=lambda a: a.level):
        parent_id = code_to_id.get(item.parent_code) if item.parent_code else None
        if item.parent_code and parent_id is None:
            raise AppError(
                f"والد حساب {item.code} یافت نشد",
                status_code=422,
                error_code="parent_missing",
            )
        existing_acc = await account_repo.get_by_code(tenant_id, item.code)
        if existing_acc is not None:
            # Reuse existing account code so re-import / overlapping COA does not crash
            code_to_id[item.code] = existing_acc.id
            continue
        acc = Account(
            tenant_id=tenant_id,
            chart_id=chart.id,
            parent_id=parent_id,
            code=item.code,
            name=item.name,
            account_type=item.account_type,
            account_category=item.account_category,
            level=item.level,
            is_group=item.is_group,
            is_postable=item.is_postable,
            status=AccountStatus.ACTIVE,
        )
        await account_repo.add(acc)
        await session.flush()
        code_to_id[item.code] = acc.id
        created.append(acc)
    return created
