"""
Site-admin router — restricted to users with role='site_admin'.
These endpoints are NOT tenant-scoped and operate across all accounts.
"""
from uuid import UUID

from fastapi import APIRouter, Depends, Query, Request
from sqlalchemy import select, func
from sqlalchemy.ext.asyncio import AsyncSession

from src.apps.auth.schemas.requests import LoginRequest
from src.apps.auth.schemas.responses import UserResponse
from src.apps.auth.services.auth_service import AuthService
from src.apps.site_admin.models.lead import Lead
from src.apps.tenants.schemas.requests import (
    AdminCreateTenantRequest,
    SendCredentialsRequest,
    UpdateTenantRequest,
)
from src.apps.tenants.schemas.responses import (
    AccountDetailResponse,
    AccountResponse,
    SignupListItemResponse,
)
from src.apps.tenants.services.tenant_service import TenantService
from src.apps.site_admin.schemas.enquiry import EnquiryListItemResponse, UpdateEnquiryStatusRequest
from src.apps.site_admin.services.enquiry_service import EnquiryService
from src.core.dependencies import get_current_user
from src.core.exceptions import ForbiddenError
from src.core.schemas.response import paginated, success
from src.database.session import get_db

router = APIRouter(prefix="/site-admin", tags=["Site Admin"])


# ---------------------------------------------------------------------------
# Auth guard
# ---------------------------------------------------------------------------

async def require_site_admin(current_user=Depends(get_current_user)):
    """Dependency — allows only users whose role is 'site_admin'."""
    if current_user.role != "site_admin":
        raise ForbiddenError("Site admin access required")
    return current_user


# ---------------------------------------------------------------------------
# Auth
# ---------------------------------------------------------------------------

@router.post("/auth/login", response_model=dict)
async def site_admin_login(
    body: LoginRequest,
    request: Request,
    db: AsyncSession = Depends(get_db),
):
    """
    Login for site admin users.
    No tenant scoping — authenticates against the global user pool.
    """
    service = AuthService(db)
    # Pass tenant_id=None to skip tenant filtering
    access_token, refresh_token, user = await service.login(body.email, body.password, tenant_id=None)

    if user.role != "site_admin":
        raise ForbiddenError("Site admin access required")

    return success(
        data={
            "access_token": access_token,
            "refresh_token": refresh_token,
            "token_type": "bearer",
            "user": UserResponse.model_validate(user).model_dump(),
        },
        message="Login successful",
    )


# ---------------------------------------------------------------------------
# Dashboard KPIs
# ---------------------------------------------------------------------------

@router.get("/dashboard/kpis", response_model=dict)
async def get_kpis(
    current_user=Depends(require_site_admin),
    db: AsyncSession = Depends(get_db),
):
    """High-level KPI snapshot for the site admin dashboard."""
    from src.apps.tenants.models.account import Account
    from src.apps.auth.models.user import User
    from src.apps.records.models.record import Record

    total_tenants_result = await db.execute(select(func.count(Account.id)))
    total_tenants = total_tenants_result.scalar_one()

    active_tenants_result = await db.execute(
        select(func.count(Account.id)).where(Account.status == "active")
    )
    active_tenants = active_tenants_result.scalar_one()

    total_users_result = await db.execute(select(func.count(User.id)))
    total_users = total_users_result.scalar_one()

    total_records_result = await db.execute(
        select(func.count(Record.id)).where(Record.deleted_at.is_(None))
    )
    total_records = total_records_result.scalar_one()

    total_leads_result = await db.execute(select(func.count(Lead.id)))
    total_leads = total_leads_result.scalar_one()

    return success(
        data={
            "total_tenants": total_tenants,
            "active_tenants": active_tenants,
            "total_users": total_users,
            "total_records": total_records,
            "total_leads": total_leads,
        }
    )


# ---------------------------------------------------------------------------
# Tenant management
# ---------------------------------------------------------------------------

@router.get("/signups/kpis", response_model=dict)
async def get_signup_kpis(
    current_user=Depends(require_site_admin),
    db: AsyncSession = Depends(get_db),
):
    """KPI counts by status for the sign-ups dashboard strip cards."""
    service = TenantService(db)
    kpis = await service.get_signup_kpis()
    return success(data=kpis)


@router.get("/signups", response_model=dict)
async def list_signups(
    skip: int = Query(0, ge=0),
    limit: int = Query(20, ge=1, le=500),
    status: str = Query(None),
    plan: str = Query(None),
    q: str = Query(None),
    current_user=Depends(require_site_admin),
    db: AsyncSession = Depends(get_db),
):
    """Paginated list of all sign-up accounts."""
    service = TenantService(db)
    items, total = await service.list_signups(skip=skip, limit=limit, status=status, plan=plan, q=q)

    response_items = []
    for item in items:
        account = item["account"]
        response_items.append(
            SignupListItemResponse(
                id=account.id,
                subdomain=account.subdomain,
                name=account.organization_name,
                cemetery_type=account.cemetery_type,
                plan=account.plan,
                status=account.status,
                contact={
                    "name": item["contact_name"],
                    "email": item["contact_email"],
                    "phone": item["contact_phone"],
                    "title": "",
                },
                size=account.size,
                signup_source=account.signup_source,
                account_manager=account.account_manager,
                feature_flags=account.feature_flags,
                credentials_sent_at=account.credentials_sent_at,
                activated_at=account.activated_at,
                created_at=account.created_at,
            ).model_dump()
        )

    return paginated(
        items=response_items,
        total=total,
        page=(skip // limit) + 1,
        page_size=limit,
    )


@router.get("/tenants", response_model=dict)
async def list_tenants(
    skip: int = Query(0, ge=0),
    limit: int = Query(20, ge=1, le=100),
    current_user=Depends(require_site_admin),
    db: AsyncSession = Depends(get_db),
):
    service = TenantService(db)
    accounts, total = await service.list_all(skip=skip, limit=limit)
    return paginated(
        items=[AccountResponse.model_validate(a).model_dump() for a in accounts],
        total=total,
        page=(skip // limit) + 1,
        page_size=limit,
    )


@router.post("/tenants", response_model=dict, status_code=201)
async def create_tenant(
    body: AdminCreateTenantRequest,
    current_user=Depends(require_site_admin),
    db: AsyncSession = Depends(get_db),
):
    """Create a tenant account on behalf of a customer (admin wizard)."""
    service = TenantService(db)
    account, admin_user, temp_password = await service.admin_create(body.model_dump())
    return success(
        data={
            "account": AccountDetailResponse.model_validate(account).model_dump(),
            "admin_user": UserResponse.model_validate(admin_user).model_dump(),
            "temp_password": temp_password,
        },
        message="Tenant created",
    )


@router.get("/tenants/{tenant_id}", response_model=dict)
async def get_tenant(
    tenant_id: UUID,
    current_user=Depends(require_site_admin),
    db: AsyncSession = Depends(get_db),
):
    service = TenantService(db)
    account = await service.get_by_id(tenant_id)
    from src.core.exceptions import NotFoundError as _NotFoundError
    if not account:
        raise _NotFoundError("Tenant not found")
    return success(data=AccountDetailResponse.model_validate(account).model_dump())


@router.post("/tenants/{tenant_id}/send-credentials", response_model=dict)
async def send_credentials(
    tenant_id: UUID,
    body: SendCredentialsRequest,
    current_user=Depends(require_site_admin),
    db: AsyncSession = Depends(get_db),
):
    """Record credential-send timestamp and trigger welcome email job."""
    service = TenantService(db)
    account = await service.send_credentials(tenant_id, body.credentials_sent_at)
    return success(
        data={"credentials_sent_at": account.credentials_sent_at.isoformat() if account.credentials_sent_at else None},
        message="Credentials recorded",
    )


@router.patch("/tenants/{tenant_id}", response_model=dict)
async def update_tenant(
    tenant_id: UUID,
    body: UpdateTenantRequest,
    current_user=Depends(require_site_admin),
    db: AsyncSession = Depends(get_db),
):
    service = TenantService(db)
    account = await service.update(tenant_id, body.model_dump(exclude_none=True))
    return success(
        data=AccountDetailResponse.model_validate(account).model_dump(),
        message="Tenant updated",
    )


# ---------------------------------------------------------------------------
# Leads
# ---------------------------------------------------------------------------

@router.get("/leads", response_model=dict)
async def list_leads(
    skip: int = Query(0, ge=0),
    limit: int = Query(20, ge=1, le=100),
    status: str = Query(None),
    current_user=Depends(require_site_admin),
    db: AsyncSession = Depends(get_db),
):
    from sqlalchemy import and_

    conditions = []
    if status:
        conditions.append(Lead.status == status)

    where_clause = and_(*conditions) if conditions else True

    count_result = await db.execute(
        select(func.count(Lead.id)).where(where_clause)
        if conditions
        else select(func.count(Lead.id))
    )
    total = count_result.scalar_one()

    query = select(Lead).order_by(Lead.created_at.desc()).offset(skip).limit(limit)
    if conditions:
        query = query.where(where_clause)

    result = await db.execute(query)
    leads = result.scalars().all()

    def _serialize_lead(lead: Lead) -> dict:
        return {
            "id": str(lead.id),
            "organization": lead.organization,
            "contact_name": lead.contact_name,
            "email": lead.email,
            "phone": lead.phone,
            "cemetery_type": lead.cemetery_type,
            "size_estimate": lead.size_estimate,
            "plan_interest": lead.plan_interest,
            "source": lead.source,
            "status": lead.status,
            "notes": lead.notes,
            "created_at": lead.created_at.isoformat(),
        }

    return paginated(
        items=[_serialize_lead(lead) for lead in leads],
        total=total,
        page=(skip // limit) + 1,
        page_size=limit,
    )


# ---------------------------------------------------------------------------
# Enquiries
# ---------------------------------------------------------------------------

@router.get("/enquiries", response_model=dict)
async def list_enquiries(
    skip: int = Query(0, ge=0),
    limit: int = Query(20, ge=1, le=500),
    type: str = Query(None),
    status: str = Query(None),
    q: str = Query(None),
    current_user=Depends(require_site_admin),
    db: AsyncSession = Depends(get_db),
):
    """Paginated list of all website enquiries with optional type/status/search filters."""
    service = EnquiryService(db)
    items, total = await service.list(
        skip=skip,
        limit=limit,
        type_filter=type,
        status_filter=status,
        q=q,
    )
    return paginated(
        items=[EnquiryListItemResponse.model_validate(e).model_dump() for e in items],
        total=total,
        page=(skip // limit) + 1,
        page_size=limit,
    )


@router.get("/enquiries/new-count", response_model=dict)
async def get_enquiry_new_count(
    current_user=Depends(require_site_admin),
    db: AsyncSession = Depends(get_db),
):
    """Count of new (unactioned) enquiries — used by topbar bell badge."""
    service = EnquiryService(db)
    count = await service.count_new()
    return success(data={"count": count})


@router.patch("/enquiries/{enquiry_id}", response_model=dict)
async def update_enquiry_status(
    enquiry_id: UUID,
    body: UpdateEnquiryStatusRequest,
    current_user=Depends(require_site_admin),
    db: AsyncSession = Depends(get_db),
):
    """Update the status of a website enquiry."""
    service = EnquiryService(db)
    enquiry = await service.update_status(enquiry_id, body.status)
    return success(
        data=EnquiryListItemResponse.model_validate(enquiry).model_dump(),
        message="Status updated",
    )
