"""
F-1: 멀티테넌트 관리 API

엔드포인트:
  POST   /api/tenants              — 테넌트 생성 (ADMIN)
  GET    /api/tenants              — 테넌트 목록 (ADMIN)
  GET    /api/tenants/current      — 현재 요청 테넌트 정보
  GET    /api/tenants/{tenant_id}  — 테넌트 상세 (ADMIN)
  PUT    /api/tenants/{tenant_id}  — 테넌트 수정 (ADMIN)
  DELETE /api/tenants/{tenant_id}  — 테넌트 비활성화 (ADMIN)
  POST   /api/tenants/{tenant_id}/quota — 쿼터 설정 (ADMIN)
"""
from __future__ import annotations

import logging
from datetime import datetime
from typing import Dict, Optional
from uuid import uuid4

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

from core.auth import get_current_user
from database import get_db
from middleware.tenant import (
    _tenants,
    get_current_tenant_id,
    get_current_tenant,
    register_tenant,
    require_tenant,
)
from models import User, UserRole

logger = logging.getLogger(__name__)
router = APIRouter(prefix="/api/tenants", tags=["tenants"])

PLAN_OPTIONS = ["STANDARD", "PROFESSIONAL", "ENTERPRISE"]


# ── Pydantic 스키마 ──────────────────────────────────────────────────────────

class TenantIn(BaseModel):
    name:      str
    code:      str = Field(..., min_length=2, max_length=20, pattern=r"^[A-Z0-9_]+$")
    plan:      str = "STANDARD"
    description: str = ""


class TenantUpdateIn(BaseModel):
    name:        Optional[str] = None
    plan:        Optional[str] = None
    description: Optional[str] = None
    is_active:   Optional[bool] = None


class QuotaIn(BaseModel):
    max_users:          Optional[int]   = None
    max_servers:        Optional[int]   = None
    max_sr_per_month:   Optional[int]   = None
    storage_gb:         Optional[float] = None
    rate_limit_rpm:     Optional[int]   = None


# ── 엔드포인트 ───────────────────────────────────────────────────────────────

@router.post("", status_code=201)
async def create_tenant(
    body:         TenantIn,
    current_user: User = Depends(get_current_user),
    _db:          AsyncSession = Depends(get_db),
):
    """테넌트 생성 (ADMIN)."""
    if current_user.role != UserRole.ADMIN:
        raise HTTPException(403, "ADMIN 권한이 필요합니다.")
    if body.plan not in PLAN_OPTIONS:
        raise HTTPException(400, f"유효하지 않은 플랜: {body.plan}. 허용: {PLAN_OPTIONS}")
    if body.code in _tenants:
        raise HTTPException(409, f"테넌트 코드 '{body.code}'가 이미 존재합니다.")

    tenant_id = f"TEN-{uuid4().hex[:8].upper()}"
    try:
        record = register_tenant(
            tenant_id  = tenant_id,
            name       = body.name,
            code       = body.code,
            plan       = body.plan,
            created_by = current_user.username,
        )
    except ValueError as e:
        raise HTTPException(409, str(e))

    if body.description:
        record["description"] = body.description

    logger.info("테넌트 생성: %s (%s) by %s", tenant_id, body.name, current_user.username)
    return record


@router.get("")
async def list_tenants_api(
    include_inactive: bool = False,
    current_user: User = Depends(get_current_user),
    _db:          AsyncSession = Depends(get_db),
):
    """테넌트 목록 (ADMIN)."""
    if current_user.role != UserRole.ADMIN:
        raise HTTPException(403, "ADMIN 권한이 필요합니다.")

    tenants = list(_tenants.values())
    if not include_inactive:
        tenants = [t for t in tenants if t.get("is_active", True)]

    return {
        "total":   len(tenants),
        "tenants": tenants,
    }


@router.get("/current")
async def current_tenant(
    current_user: User = Depends(get_current_user),
    _db:          AsyncSession = Depends(get_db),
):
    """현재 요청의 테넌트 정보 조회."""
    tenant_id = get_current_tenant_id()
    tenant    = get_current_tenant()
    return {
        "tenant_id":   tenant_id,
        "tenant_name": tenant["name"] if tenant else "DEFAULT",
        "plan":        tenant.get("plan", "ENTERPRISE") if tenant else "ENTERPRISE",
        "quota":       tenant.get("quota", {}) if tenant else {},
        "is_default":  tenant_id == "DEFAULT",
    }


@router.get("/{tenant_id}")
async def get_tenant_detail(
    tenant_id:    str,
    current_user: User = Depends(get_current_user),
    _db:          AsyncSession = Depends(get_db),
):
    """테넌트 상세 조회 (ADMIN)."""
    if current_user.role != UserRole.ADMIN:
        raise HTTPException(403, "ADMIN 권한이 필요합니다.")

    t = _tenants.get(tenant_id)
    if not t:
        raise HTTPException(404, f"테넌트 '{tenant_id}'를 찾을 수 없습니다.")
    return t


@router.put("/{tenant_id}")
async def update_tenant(
    tenant_id:    str,
    body:         TenantUpdateIn,
    current_user: User = Depends(get_current_user),
    _db:          AsyncSession = Depends(get_db),
):
    """테넌트 수정 (ADMIN). 시스템 테넌트(DEFAULT)는 비활성화 불가."""
    if current_user.role != UserRole.ADMIN:
        raise HTTPException(403, "ADMIN 권한이 필요합니다.")

    t = _tenants.get(tenant_id)
    if not t:
        raise HTTPException(404, f"테넌트 '{tenant_id}'를 찾을 수 없습니다.")
    if t.get("is_system") and body.is_active is False:
        raise HTTPException(400, "시스템 테넌트는 비활성화할 수 없습니다.")
    if body.plan and body.plan not in PLAN_OPTIONS:
        raise HTTPException(400, f"유효하지 않은 플랜: {body.plan}")

    if body.name        is not None: t["name"]      = body.name
    if body.plan        is not None: t["plan"]      = body.plan
    if body.description is not None: t["description"] = body.description
    if body.is_active   is not None: t["is_active"] = body.is_active
    t["updated_at"] = datetime.utcnow().isoformat()
    t["updated_by"] = current_user.username

    logger.info("테넌트 수정: %s by %s", tenant_id, current_user.username)
    return t


@router.delete("/{tenant_id}")
async def deactivate_tenant(
    tenant_id:    str,
    current_user: User = Depends(get_current_user),
    _db:          AsyncSession = Depends(get_db),
):
    """테넌트 비활성화 (ADMIN, 시스템 테넌트 보호)."""
    if current_user.role != UserRole.ADMIN:
        raise HTTPException(403, "ADMIN 권한이 필요합니다.")

    t = _tenants.get(tenant_id)
    if not t:
        raise HTTPException(404, f"테넌트 '{tenant_id}'를 찾을 수 없습니다.")
    if t.get("is_system"):
        raise HTTPException(400, "시스템 테넌트는 삭제할 수 없습니다.")

    t["is_active"]    = False
    t["deactivated_at"] = datetime.utcnow().isoformat()
    t["deactivated_by"] = current_user.username

    logger.info("테넌트 비활성화: %s by %s", tenant_id, current_user.username)
    return {"message": f"테넌트 '{tenant_id}'가 비활성화되었습니다.", "tenant": t}


@router.post("/{tenant_id}/quota")
async def set_quota(
    tenant_id:    str,
    body:         QuotaIn,
    current_user: User = Depends(get_current_user),
    _db:          AsyncSession = Depends(get_db),
):
    """테넌트 쿼터 설정 (ADMIN)."""
    if current_user.role != UserRole.ADMIN:
        raise HTTPException(403, "ADMIN 권한이 필요합니다.")

    t = _tenants.get(tenant_id)
    if not t:
        raise HTTPException(404, f"테넌트 '{tenant_id}'를 찾을 수 없습니다.")

    quota = t.setdefault("quota", {})
    if body.max_users        is not None: quota["max_users"]        = body.max_users
    if body.max_servers      is not None: quota["max_servers"]      = body.max_servers
    if body.max_sr_per_month is not None: quota["max_sr_per_month"] = body.max_sr_per_month
    if body.storage_gb       is not None: quota["storage_gb"]       = body.storage_gb

    settings = t.setdefault("settings", {})
    if body.rate_limit_rpm   is not None: settings["rate_limit_rpm"] = body.rate_limit_rpm

    t["quota_updated_at"] = datetime.utcnow().isoformat()
    t["quota_updated_by"] = current_user.username

    logger.info("테넌트 쿼터 설정: %s by %s", tenant_id, current_user.username)
    return {"message": "쿼터가 설정되었습니다.", "quota": quota, "settings": settings}
