from fastapi import APIRouter, Depends, Header, HTTPException
from pydantic import BaseModel, Field
from sqlalchemy import select, func
from sqlalchemy.orm import Session
from app.api.deps import get_db,current_user,require_roles
from app.models.entities import User,Role,Tenant,TenantMembership,SaaSPlan,SaaSModule,SaaSSubscription,TenantBranding,TenantEntitlement,TenantUsageMeter,TenantProvisioningRun
from app.services.saas_tenancy import provision_tenant,resolve_membership,meter_usage,tenant_summary,seed_catalog

router=APIRouter(prefix='/api/v020',tags=['V020 Enterprise SaaS Foundation'])
PLATFORM=(Role.admin,Role.director)

class ProvisionIn(BaseModel):
    slug:str=Field(min_length=3,max_length=100); legal_name:str; trade_name:str=''; tax_id:str=''
    admin_email:str; admin_password:str=Field(min_length=12); admin_name:str='Tenant Administrator'
    plan_code:str='enterprise'; seats:int=10; trial_days:int=14; modules:list[str]=[]
    isolation_mode:str='shared_schema'; region:str='sa-east-1'; default_locale:str='pt-BR'; default_timezone:str='America/Sao_Paulo'
    product_name:str=''; primary_color:str='#16324F'; secondary_color:str='#2E7D32'; support_email:str=''
class PlanIn(BaseModel):
    code:str; name:str; currency:str='BRL'; monthly_price_cents:int=0; annual_price_cents:int=0; limits_json:dict={}
class BrandingIn(BaseModel):
    logo_url:str=''; favicon_url:str=''; primary_color:str='#16324F'; secondary_color:str='#2E7D32'; custom_domain:str=''; product_name:str='Enterprise Data Platform'; support_email:str=''
class UsageIn(BaseModel):
    metric_code:str; quantity:int=1; unit:str='unit'; dimensions:dict={}

def tenant_access(x_tenant_id:str=Header(...,alias='X-Tenant-ID'),db:Session=Depends(get_db),user:User=Depends(current_user)):
    membership=resolve_membership(db,user,x_tenant_id)
    if not membership and user.role not in PLATFORM: raise HTTPException(403,'Acesso ao tenant negado')
    tenant=db.get(Tenant,x_tenant_id)
    if not tenant or tenant.status!='active': raise HTTPException(404,'Tenant ativo não encontrado')
    return tenant

@router.get('/summary')
def summary(db:Session=Depends(get_db),user:User=Depends(require_roles(*PLATFORM))):
    return {'tenants':db.scalar(select(func.count(Tenant.id))) or 0,'active_tenants':db.scalar(select(func.count(Tenant.id)).where(Tenant.status=='active')) or 0,'plans':db.scalar(select(func.count(SaaSPlan.id))) or 0,'modules':db.scalar(select(func.count(SaaSModule.id))) or 0,'subscriptions':db.scalar(select(func.count(SaaSSubscription.id))) or 0}
@router.post('/catalog/seed')
def seed(db:Session=Depends(get_db),user:User=Depends(require_roles(*PLATFORM))): seed_catalog(db); return {'status':'ok'}
@router.post('/plans')
def create_plan(p:PlanIn,db:Session=Depends(get_db),user:User=Depends(require_roles(*PLATFORM))):
    if db.scalar(select(SaaSPlan).where(SaaSPlan.code==p.code)): raise HTTPException(409,'Plano já existe')
    obj=SaaSPlan(**p.model_dump()); db.add(obj); db.commit(); db.refresh(obj); return obj
@router.get('/plans')
def plans(db:Session=Depends(get_db),user:User=Depends(current_user)): return db.scalars(select(SaaSPlan).where(SaaSPlan.enabled==True)).all()
@router.post('/tenants/provision')
def provision(p:ProvisionIn,db:Session=Depends(get_db),user:User=Depends(require_roles(*PLATFORM))):
    try:return provision_tenant(db,user,p.model_dump())
    except ValueError as exc: raise HTTPException(400,str(exc))
@router.get('/tenants')
def tenants(db:Session=Depends(get_db),user:User=Depends(require_roles(*PLATFORM))): return db.scalars(select(Tenant).order_by(Tenant.created_at.desc())).all()
@router.get('/tenant/context')
def context(tenant:Tenant=Depends(tenant_access),db:Session=Depends(get_db),user:User=Depends(current_user)):
    data=tenant_summary(db,tenant.id); data['membership']=resolve_membership(db,user,tenant.id); return data
@router.put('/tenant/branding')
def branding(p:BrandingIn,tenant:Tenant=Depends(tenant_access),db:Session=Depends(get_db),user:User=Depends(current_user)):
    membership=resolve_membership(db,user,tenant.id)
    if user.role not in PLATFORM and (not membership or membership.tenant_role not in ('owner','admin')): raise HTTPException(403,'Administração do tenant necessária')
    obj=db.scalar(select(TenantBranding).where(TenantBranding.tenant_id==tenant.id)) or TenantBranding(tenant_id=tenant.id)
    for k,v in p.model_dump().items(): setattr(obj,k,v)
    db.add(obj); db.commit(); db.refresh(obj); return obj
@router.get('/tenant/modules')
def modules(tenant:Tenant=Depends(tenant_access),db:Session=Depends(get_db),user:User=Depends(current_user)):
    return db.execute(select(SaaSModule.code,SaaSModule.name,TenantEntitlement.enabled,TenantEntitlement.limits_json).join(TenantEntitlement,TenantEntitlement.module_id==SaaSModule.id).where(TenantEntitlement.tenant_id==tenant.id)).mappings().all()
@router.post('/tenant/usage')
def usage(p:UsageIn,tenant:Tenant=Depends(tenant_access),db:Session=Depends(get_db),user:User=Depends(current_user)): return meter_usage(db,tenant.id,p.metric_code,p.quantity,p.unit,p.dimensions)
@router.get('/provisioning-runs')
def runs(db:Session=Depends(get_db),user:User=Depends(require_roles(*PLATFORM))): return db.scalars(select(TenantProvisioningRun).order_by(TenantProvisioningRun.created_at.desc()).limit(200)).all()
