from typing import Annotated
from uuid import UUID
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select

from app.core.database import get_db
from app.core.audit import log_audit
from app.models.user import User
from app.models.plan_limits import PlanLimits
from app.models.account import Account
from app.models.account_limit_override import AccountLimitOverride
from app.schemas.admin import (
    PlanLimitResponse, PlanLimitUpdate,
    AccountOverrideCreate, AccountOverrideUpdate, AccountOverrideResponse,
)
from app.api.deps import require_admin

router = APIRouter(prefix="/admin", tags=["admin-plan-limits"])


@router.get("/plan-limits", response_model=list[PlanLimitResponse])
async def list_plan_limits(
    db: Annotated[AsyncSession, Depends(get_db)],
    current_user: Annotated[User, Depends(require_admin)],
):
    """List all plan limit configurations."""
    result = await db.execute(select(PlanLimits))
    return result.scalars().all()


@router.put("/plan-limits", response_model=PlanLimitResponse)
async def update_plan_limits(
    data: PlanLimitUpdate,
    db: Annotated[AsyncSession, Depends(get_db)],
    current_user: Annotated[User, Depends(require_admin)],
):
    """Update a plan's limits."""
    result = await db.execute(select(PlanLimits).where(PlanLimits.plan == data.plan))
    plan = result.scalar_one_or_none()
    if not plan:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Plan not found")

    plan.max_trees = data.max_trees
    plan.max_sessions_per_month = data.max_sessions_per_month
    plan.max_users = data.max_users
    plan.custom_branding = data.custom_branding
    plan.priority_support = data.priority_support
    plan.export_formats = data.export_formats

    await log_audit(db, current_user.id, "plan_limits.update", "plan_limits", details={"plan": data.plan})
    await db.commit()
    await db.refresh(plan)
    return plan


@router.get("/account-overrides", response_model=list[AccountOverrideResponse])
async def list_account_overrides(
    db: Annotated[AsyncSession, Depends(get_db)],
    current_user: Annotated[User, Depends(require_admin)],
):
    """List all account limit overrides."""
    query = (
        select(
            AccountLimitOverride,
            Account.name.label("account_name"),
            Account.display_code.label("account_display_code"),
        )
        .outerjoin(Account, AccountLimitOverride.account_id == Account.id)
        .order_by(AccountLimitOverride.created_at.desc())
    )
    result = await db.execute(query)
    rows = result.all()

    return [
        AccountOverrideResponse(
            id=row.AccountLimitOverride.id,
            account_id=row.AccountLimitOverride.account_id,
            account_name=row.account_name,
            account_display_code=row.account_display_code,
            override_max_trees=row.AccountLimitOverride.override_max_trees,
            override_max_sessions_per_month=row.AccountLimitOverride.override_max_sessions_per_month,
            override_max_users=row.AccountLimitOverride.override_max_users,
            note=row.AccountLimitOverride.note,
            created_at=row.AccountLimitOverride.created_at,
            updated_at=row.AccountLimitOverride.updated_at,
        )
        for row in rows
    ]


@router.post("/account-overrides", response_model=AccountOverrideResponse, status_code=status.HTTP_201_CREATED)
async def create_account_override(
    data: AccountOverrideCreate,
    db: Annotated[AsyncSession, Depends(get_db)],
    current_user: Annotated[User, Depends(require_admin)],
):
    """Create an account limit override."""
    # Look up account by display_code
    result = await db.execute(select(Account).where(Account.display_code == data.account_display_code))
    account = result.scalar_one_or_none()
    if not account:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Account not found")

    # Check for existing override
    existing = await db.execute(
        select(AccountLimitOverride).where(AccountLimitOverride.account_id == account.id)
    )
    if existing.scalar_one_or_none():
        raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail="Override already exists for this account")

    override = AccountLimitOverride(
        account_id=account.id,
        override_max_trees=data.override_max_trees,
        override_max_sessions_per_month=data.override_max_sessions_per_month,
        override_max_users=data.override_max_users,
        note=data.note,
        created_by_id=current_user.id,
    )
    db.add(override)
    await log_audit(db, current_user.id, "account_override.create", "account", account.id,
                    {"display_code": data.account_display_code})
    await db.commit()
    await db.refresh(override)

    return AccountOverrideResponse(
        id=override.id,
        account_id=override.account_id,
        account_name=account.name,
        account_display_code=account.display_code,
        override_max_trees=override.override_max_trees,
        override_max_sessions_per_month=override.override_max_sessions_per_month,
        override_max_users=override.override_max_users,
        note=override.note,
        created_at=override.created_at,
        updated_at=override.updated_at,
    )


@router.put("/account-overrides/{override_id}", response_model=AccountOverrideResponse)
async def update_account_override(
    override_id: UUID,
    data: AccountOverrideUpdate,
    db: Annotated[AsyncSession, Depends(get_db)],
    current_user: Annotated[User, Depends(require_admin)],
):
    """Update an account limit override."""
    result = await db.execute(select(AccountLimitOverride).where(AccountLimitOverride.id == override_id))
    override = result.scalar_one_or_none()
    if not override:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Override not found")

    if data.override_max_trees is not None:
        override.override_max_trees = data.override_max_trees
    if data.override_max_sessions_per_month is not None:
        override.override_max_sessions_per_month = data.override_max_sessions_per_month
    if data.override_max_users is not None:
        override.override_max_users = data.override_max_users
    if data.note is not None:
        override.note = data.note

    await log_audit(db, current_user.id, "account_override.update", "account", override.account_id)
    await db.commit()
    await db.refresh(override)

    # Fetch account info
    acct = await db.execute(select(Account).where(Account.id == override.account_id))
    account = acct.scalar_one_or_none()

    return AccountOverrideResponse(
        id=override.id,
        account_id=override.account_id,
        account_name=account.name if account else None,
        account_display_code=account.display_code if account else None,
        override_max_trees=override.override_max_trees,
        override_max_sessions_per_month=override.override_max_sessions_per_month,
        override_max_users=override.override_max_users,
        note=override.note,
        created_at=override.created_at,
        updated_at=override.updated_at,
    )


@router.delete("/account-overrides/{override_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_account_override(
    override_id: UUID,
    db: Annotated[AsyncSession, Depends(get_db)],
    current_user: Annotated[User, Depends(require_admin)],
):
    """Delete an account limit override."""
    result = await db.execute(select(AccountLimitOverride).where(AccountLimitOverride.id == override_id))
    override = result.scalar_one_or_none()
    if not override:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Override not found")

    await log_audit(db, current_user.id, "account_override.delete", "account", override.account_id)
    await db.delete(override)
    await db.commit()
