"""货币管理 Admin API

路由：
  GET    /admin/currencies                  列出该租户所有货币
  POST   /admin/currencies                  新增货币
  PUT    /admin/currencies/{id}             修改货币（汇率 / 名称 / 模式 / 启用）
  DELETE /admin/currencies/{id}             删除货币（基准货币不可删）
  PUT    /admin/currencies/{id}/set-default 设为基准货币
  POST   /admin/currencies/refresh-rates    拉取实时汇率（刷新 auto 模式货币）
  POST   /admin/currencies/convert          金额换算预览
"""
from decimal import Decimal
from typing import Optional, List

from fastapi import APIRouter, Depends, HTTPException, Query
from pydantic import BaseModel, Field, field_validator
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

from app.api.deps import get_db, get_admin_user
from app.core.models.currency import Currency
from app.core.models.user import User
from app.core.services.currency_service import CurrencyService

router = APIRouter(prefix="/admin", tags=["货币管理"])


# ── Schemas ────────────────────────────────────────────────────────────────

class CurrencyOut(BaseModel):
    id: int
    code: str
    name: str
    symbol: str
    exchange_rate: float
    is_default: bool
    is_active: bool
    rate_mode: str
    last_fetched_at: Optional[str] = None
    model_config = {"from_attributes": True}

    @classmethod
    def from_orm(cls, c: Currency) -> "CurrencyOut":
        return cls(
            id=c.id,
            code=c.code,
            name=c.name,
            symbol=c.symbol,
            exchange_rate=float(c.exchange_rate),
            is_default=bool(c.is_default),
            is_active=bool(c.is_active),
            rate_mode=c.rate_mode,
            last_fetched_at=c.last_fetched_at.isoformat() if c.last_fetched_at else None,
        )


class CurrencyCreateIn(BaseModel):
    code: str = Field(..., min_length=3, max_length=3, description="ISO 4217，如 USD")
    name: str = Field(..., min_length=1, max_length=100)
    symbol: str = Field(..., min_length=1, max_length=10)
    exchange_rate: Decimal = Field(..., gt=0, description="相对基准货币汇率，基准货币填 1")
    is_active: bool = Field(True)
    rate_mode: str = Field("manual", description="manual 或 auto")

    @field_validator("code")
    @classmethod
    def upper_code(cls, v: str) -> str:
        return v.upper()

    @field_validator("rate_mode")
    @classmethod
    def valid_mode(cls, v: str) -> str:
        if v not in ("manual", "auto"):
            raise ValueError("rate_mode 只能是 manual 或 auto")
        return v


class CurrencyUpdateIn(BaseModel):
    name: Optional[str] = Field(None, min_length=1, max_length=100)
    symbol: Optional[str] = Field(None, min_length=1, max_length=10)
    exchange_rate: Optional[Decimal] = Field(None, gt=0)
    is_active: Optional[bool] = None
    rate_mode: Optional[str] = None

    @field_validator("rate_mode")
    @classmethod
    def valid_mode(cls, v: Optional[str]) -> Optional[str]:
        if v is not None and v not in ("manual", "auto"):
            raise ValueError("rate_mode 只能是 manual 或 auto")
        return v


class ConvertIn(BaseModel):
    amount: Decimal = Field(..., gt=0)
    from_code: str = Field(..., min_length=3, max_length=3)
    to_code: str = Field(..., min_length=3, max_length=3)


# ── 列表 ───────────────────────────────────────────────────────────────────

@router.get("/currencies", response_model=List[CurrencyOut], summary="货币列表")
async def list_currencies(
    db: AsyncSession = Depends(get_db),
    admin: User = Depends(get_admin_user),
):
    currencies = await CurrencyService.get_all(db, admin.tenant_id)
    return [CurrencyOut.from_orm(c) for c in currencies]


# ── 新增 ───────────────────────────────────────────────────────────────────

@router.post("/currencies", response_model=CurrencyOut, summary="新增货币", status_code=201)
async def create_currency(
    body: CurrencyCreateIn,
    db: AsyncSession = Depends(get_db),
    admin: User = Depends(get_admin_user),
):
    existing = await CurrencyService.get_by_code(db, admin.tenant_id, body.code)
    if existing:
        raise HTTPException(status_code=409, detail=f"货币 {body.code} 已存在")

    # 检查是否已有基准货币（新增时不允许通过此接口创建基准货币，需通过 set-default）
    all_currencies = await CurrencyService.get_all(db, admin.tenant_id)
    is_first = len(all_currencies) == 0  # 第一个货币自动成为基准

    cur = Currency(
        tenant_id=admin.tenant_id,
        code=body.code,
        name=body.name,
        symbol=body.symbol,
        exchange_rate=body.exchange_rate if not is_first else Decimal("1"),
        is_default=is_first,
        is_active=body.is_active,
        rate_mode=body.rate_mode,
    )
    db.add(cur)
    await db.commit()
    await db.refresh(cur)
    return CurrencyOut.from_orm(cur)


# ── 更新 ───────────────────────────────────────────────────────────────────

@router.put("/currencies/{currency_id}", response_model=CurrencyOut, summary="修改货币")
async def update_currency(
    currency_id: int,
    body: CurrencyUpdateIn,
    db: AsyncSession = Depends(get_db),
    admin: User = Depends(get_admin_user),
):
    cur = (
        await db.execute(
            select(Currency).where(
                Currency.id == currency_id,
                Currency.tenant_id == admin.tenant_id,
            )
        )
    ).scalar_one_or_none()
    if not cur:
        raise HTTPException(status_code=404, detail="货币不存在")

    # 基准货币的汇率始终为 1，不允许修改
    if cur.is_default and body.exchange_rate is not None and body.exchange_rate != Decimal("1"):
        raise HTTPException(status_code=400, detail="基准货币汇率固定为 1，请先更换基准货币")

    if body.name is not None:
        cur.name = body.name
    if body.symbol is not None:
        cur.symbol = body.symbol
    if body.exchange_rate is not None and not cur.is_default:
        cur.exchange_rate = body.exchange_rate
    if body.is_active is not None:
        cur.is_active = body.is_active
    if body.rate_mode is not None:
        cur.rate_mode = body.rate_mode

    await db.commit()
    await db.refresh(cur)
    return CurrencyOut.from_orm(cur)


# ── 设为基准货币 ────────────────────────────────────────────────────────────

@router.put("/currencies/{currency_id}/set-default", response_model=CurrencyOut, summary="设为基准货币")
async def set_default_currency(
    currency_id: int,
    db: AsyncSession = Depends(get_db),
    admin: User = Depends(get_admin_user),
):
    new_default = (
        await db.execute(
            select(Currency).where(
                Currency.id == currency_id,
                Currency.tenant_id == admin.tenant_id,
            )
        )
    ).scalar_one_or_none()
    if not new_default:
        raise HTTPException(status_code=404, detail="货币不存在")
    if new_default.is_default:
        return CurrencyOut.from_orm(new_default)

    # 取消旧基准货币
    old_defaults = (
        await db.execute(
            select(Currency).where(
                Currency.tenant_id == admin.tenant_id,
                Currency.is_default == True,
            )
        )
    ).scalars().all()
    for old in old_defaults:
        old.is_default = False

    new_default.is_default = True
    new_default.exchange_rate = Decimal("1.00000000")
    new_default.rate_mode = "manual"  # 基准货币不需要自动拉取

    await db.commit()
    await db.refresh(new_default)
    return CurrencyOut.from_orm(new_default)


# ── 删除 ───────────────────────────────────────────────────────────────────

@router.delete("/currencies/{currency_id}", summary="删除货币")
async def delete_currency(
    currency_id: int,
    db: AsyncSession = Depends(get_db),
    admin: User = Depends(get_admin_user),
):
    cur = (
        await db.execute(
            select(Currency).where(
                Currency.id == currency_id,
                Currency.tenant_id == admin.tenant_id,
            )
        )
    ).scalar_one_or_none()
    if not cur:
        raise HTTPException(status_code=404, detail="货币不存在")
    if cur.is_default:
        raise HTTPException(status_code=400, detail="基准货币不能删除，请先更换基准货币")

    await db.delete(cur)
    await db.commit()
    return {"detail": f"货币 {cur.code} 已删除"}


# ── 刷新实时汇率 ────────────────────────────────────────────────────────────

@router.post("/currencies/refresh-rates", summary="拉取实时汇率（刷新 auto 模式货币）")
async def refresh_rates(
    db: AsyncSession = Depends(get_db),
    admin: User = Depends(get_admin_user),
):
    """从 open.er-api.com 拉取实时汇率，更新所有 rate_mode='auto' 的货币。
    基准货币和 manual 模式货币不受影响。
    """
    result = await CurrencyService.refresh_auto_rates(db, admin.tenant_id)
    if result["error"] and not result["updated"]:
        raise HTTPException(status_code=502, detail=f"获取汇率失败：{result['error']}")
    return result


# ── 金额换算预览 ────────────────────────────────────────────────────────────

@router.post("/currencies/convert", summary="金额换算预览")
async def convert_preview(
    body: ConvertIn,
    db: AsyncSession = Depends(get_db),
    admin: User = Depends(get_admin_user),
):
    from_cur = await CurrencyService.get_by_code(db, admin.tenant_id, body.from_code.upper())
    to_cur = await CurrencyService.get_by_code(db, admin.tenant_id, body.to_code.upper())

    if not from_cur:
        raise HTTPException(status_code=404, detail=f"货币 {body.from_code} 未配置")
    if not to_cur:
        raise HTTPException(status_code=404, detail=f"货币 {body.to_code} 未配置")

    result = CurrencyService.convert_amount(
        body.amount, from_cur.exchange_rate, to_cur.exchange_rate
    )
    return {
        "from_code": from_cur.code,
        "to_code": to_cur.code,
        "from_amount": float(body.amount),
        "to_amount": float(result),
        "rate_used": float(to_cur.exchange_rate / from_cur.exchange_rate),
    }
