"""Tax rate service — CRUD, default tax management, seeding."""

from __future__ import annotations

import uuid
from datetime import UTC, datetime
from typing import Any

from sqlalchemy import select, update
from sqlalchemy.ext.asyncio import AsyncSession

from app.core.audit import log_audit
from app.models.tax import TaxRate


def _tax_to_dict(t: TaxRate) -> dict[str, Any]:
    """Serialize a TaxRate ORM object to dict."""
    return {
        "id": str(t.id),
        "name": t.name,
        "rate": float(t.rate),
        "is_default": t.is_default,
        "country": t.country,
        "created_at": t.created_at.isoformat() if t.created_at else None,
        "updated_at": t.updated_at.isoformat() if t.updated_at else None,
    }


async def list_tax_rates(
    db: AsyncSession,
    tenant_id: uuid.UUID,
) -> dict[str, Any]:
    """List all tax rates for a tenant."""
    q = select(TaxRate).where(
        TaxRate.tenant_id == tenant_id,
        TaxRate.deleted_at.is_(None),
    ).order_by(TaxRate.rate.asc())
    result = await db.execute(q)
    tax_rates = result.scalars().all()
    return {
        "items": [_tax_to_dict(t) for t in tax_rates],
        "total": len(tax_rates),
    }


async def create_tax_rate(
    db: AsyncSession,
    tenant_id: uuid.UUID,
    user_id: uuid.UUID,
    data: dict[str, Any],
) -> dict[str, Any]:
    """Create a new tax rate. If is_default=True, unset other defaults first."""
    if data.get("is_default"):
        await db.execute(
            update(TaxRate)
            .where(TaxRate.tenant_id == tenant_id, TaxRate.is_default.is_(True))
            .values(is_default=False)
        )

    tax_rate = TaxRate(
        tenant_id=tenant_id,
        name=data["name"],
        rate=data["rate"],
        is_default=data.get("is_default", False),
        country=data.get("country"),
    )
    db.add(tax_rate)
    await db.flush()
    await db.refresh(tax_rate)
    await log_audit(
        db, tenant_id, user_id, "create", "tax_rate", tax_rate.id,
        changes={"name": tax_rate.name, "rate": float(tax_rate.rate)},
    )
    return _tax_to_dict(tax_rate)


async def update_tax_rate(
    db: AsyncSession,
    tenant_id: uuid.UUID,
    user_id: uuid.UUID,
    tax_id: uuid.UUID,
    data: dict[str, Any],
) -> dict[str, Any] | None:
    """Update a tax rate. If setting is_default=True, unset other defaults first."""
    q = select(TaxRate).where(
        TaxRate.id == tax_id,
        TaxRate.tenant_id == tenant_id,
        TaxRate.deleted_at.is_(None),
    )
    result = await db.execute(q)
    tax_rate = result.scalar_one_or_none()
    if tax_rate is None:
        return None

    if data.get("is_default") is True and not tax_rate.is_default:
        await db.execute(
            update(TaxRate)
            .where(
                TaxRate.tenant_id == tenant_id,
                TaxRate.is_default.is_(True),
                TaxRate.id != tax_id,
            )
            .values(is_default=False)
        )

    changes: dict[str, Any] = {}
    for field in ("name", "rate", "is_default", "country"):
        if field in data and data[field] is not None:
            old_val = getattr(tax_rate, field)
            changes[field] = {"old": old_val, "new": data[field]}
            setattr(tax_rate, field, data[field])

    await db.flush()
    await db.refresh(tax_rate)
    await log_audit(db, tenant_id, user_id, "update", "tax_rate", tax_id, changes=changes)
    return _tax_to_dict(tax_rate)


async def delete_tax_rate(
    db: AsyncSession,
    tenant_id: uuid.UUID,
    user_id: uuid.UUID,
    tax_id: uuid.UUID,
) -> bool:
    """Soft-delete a tax rate."""
    q = select(TaxRate).where(
        TaxRate.id == tax_id,
        TaxRate.tenant_id == tenant_id,
        TaxRate.deleted_at.is_(None),
    )
    result = await db.execute(q)
    tax_rate = result.scalar_one_or_none()
    if tax_rate is None:
        return False

    tax_rate.deleted_at = datetime.now(UTC)
    await db.flush()
    await log_audit(
        db, tenant_id, user_id, "delete", "tax_rate", tax_id,
        changes={"name": tax_rate.name},
    )
    return True


async def seed_default_tax_rates(db: AsyncSession, tenant_id: uuid.UUID) -> None:
    """Seed default 19% and 7% tax rates for a new tenant if none exist."""
    q = select(TaxRate).where(TaxRate.tenant_id == tenant_id, TaxRate.deleted_at.is_(None))
    result = await db.execute(q)
    if result.scalars().first() is not None:
        return

    tax_19 = TaxRate(
        tenant_id=tenant_id,
        name="Mehrwertsteuer 19%",
        rate=19.00,
        is_default=True,
        country="DE",
    )
    tax_7 = TaxRate(
        tenant_id=tenant_id,
        name="Mehrwertsteuer 7%",
        rate=7.00,
        is_default=False,
        country="DE",
    )
    db.add_all([tax_19, tax_7])
    await db.flush()
