"""SUPER_ADMIN: Mandantenübersicht (alle Firmen) + Reseller-Verwaltung.

SUPER_ADMIN läuft mit aktivem RLS-Bypass und sieht daher alle Firmen.
Nur SUPER_ADMIN darf Reseller anlegen und Firmen einem Reseller zuordnen.
"""
import secrets
from datetime import datetime, timedelta, timezone
from uuid import UUID

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

from app.core.database import get_db
from app.core.dependencies import require_role
from app.core.security import generate_invite_token, hash_password
from app.models.audit_log import AuditLog
from app.models.company import Company
from app.models.user import User, UserRole
from app.schemas.reseller import (
    ResellerCreate,
    ResellerOut,
    TenantAssignReseller,
    TenantCreate,
    TenantOut,
    TenantUpdate,
)
from app.services.tenant_service import tenant_service

router = APIRouter(prefix="/admin", tags=["Admin · Tenants"])

_sa = (UserRole.SUPER_ADMIN,)


# ── Mandanten ────────────────────────────────────────────────────────────────
@router.get("/tenants", response_model=list[TenantOut])
async def list_tenants(
    current_user: User = require_role(*_sa),
    db: AsyncSession = Depends(get_db),
):
    return await tenant_service.list_tenants(db)


@router.post("/tenants", response_model=TenantOut, status_code=201)
async def create_tenant(
    data: TenantCreate,
    reseller_id: UUID | None = None,
    current_user: User = require_role(*_sa),
    db: AsyncSession = Depends(get_db),
):
    if reseller_id is not None:
        reseller = await db.get(User, reseller_id)
        if reseller is None or reseller.role != UserRole.RESELLER:
            raise HTTPException(status_code=400, detail="Ungültiger Reseller.")
    company, admin, initial_password = await tenant_service.create_tenant(
        data, actor=current_user, db=db, reseller_id=reseller_id,
    )
    tenants = {t.id: t for t in await tenant_service.list_tenants(db)}
    result = tenants[company.id]
    result.initial_password = initial_password
    return result


@router.patch("/tenants/{company_id}", response_model=TenantOut)
async def update_tenant(
    company_id: UUID,
    data: TenantUpdate,
    current_user: User = require_role(*_sa),
    db: AsyncSession = Depends(get_db),
):
    company = await db.get(Company, company_id)
    if company is None:
        raise HTTPException(status_code=404, detail="Firma nicht gefunden.")
    changes = data.model_dump(exclude_none=True)
    for field, value in changes.items():
        setattr(company, field, value)
    if changes:
        db.add(AuditLog(
            company_id=company.id, user_id=current_user.id,
            action="tenant_updated", entity_type="company", entity_id=company.id,
            new_value=changes,
        ))
    await db.flush()
    tenants = {t.id: t for t in await tenant_service.list_tenants(db)}
    return tenants[company.id]


@router.patch("/tenants/{company_id}/reseller", response_model=TenantOut)
async def assign_reseller(
    company_id: UUID,
    data: TenantAssignReseller,
    current_user: User = require_role(*_sa),
    db: AsyncSession = Depends(get_db),
):
    company = await db.get(Company, company_id)
    if company is None:
        raise HTTPException(status_code=404, detail="Firma nicht gefunden.")
    if data.reseller_id is not None:
        reseller = await db.get(User, data.reseller_id)
        if reseller is None or reseller.role != UserRole.RESELLER:
            raise HTTPException(status_code=400, detail="Ungültiger Reseller.")
    company.reseller_id = data.reseller_id
    db.add(AuditLog(
        company_id=company.id, user_id=current_user.id,
        action="tenant_reseller_assigned", entity_type="company", entity_id=company.id,
        new_value={"reseller_id": str(data.reseller_id) if data.reseller_id else None},
    ))
    await db.flush()
    tenants = {t.id: t for t in await tenant_service.list_tenants(db)}
    return tenants[company.id]


# ── Reseller ─────────────────────────────────────────────────────────────────
async def _reseller_company_counts(db: AsyncSession) -> dict[UUID, int]:
    rows = await db.execute(
        select(Company.reseller_id, func.count(Company.id))
        .where(Company.reseller_id.isnot(None))
        .group_by(Company.reseller_id)
    )
    return {rid: cnt for rid, cnt in rows}


@router.get("/resellers", response_model=list[ResellerOut])
async def list_resellers(
    current_user: User = require_role(*_sa),
    db: AsyncSession = Depends(get_db),
):
    resellers = (await db.scalars(
        select(User).where(User.role == UserRole.RESELLER).order_by(User.last_name, User.first_name)
    )).all()
    counts = await _reseller_company_counts(db)
    return [
        ResellerOut(
            id=r.id, email=r.email, first_name=r.first_name, last_name=r.last_name,
            is_active=r.is_active, created_at=r.created_at,
            company_count=counts.get(r.id, 0),
        )
        for r in resellers
    ]


@router.post("/resellers", response_model=ResellerOut, status_code=201)
async def create_reseller(
    data: ResellerCreate,
    current_user: User = require_role(*_sa),
    db: AsyncSession = Depends(get_db),
):
    if data.email and await db.scalar(select(User).where(User.email == data.email)):
        raise HTTPException(status_code=400, detail="E-Mail ist bereits vergeben.")

    initial_password: str | None = None
    if data.email:
        raw_token, token_hash = generate_invite_token()
        reseller = User(
            company_id=None, email=data.email,
            first_name=data.first_name, last_name=data.last_name,
            role=UserRole.RESELLER,
            password_hash=hash_password(raw_token),  # temporär, beim Accept überschrieben
            invite_token_hash=token_hash,
            invite_expires=datetime.now(timezone.utc) + timedelta(days=7),
            is_active=False,
        )
    else:
        # Kein Mailversand: interne Kennung + sofort nutzbares Temp-Passwort
        login = await tenant_service._unique_email(
            f"{data.first_name}.{data.last_name}", "reseller", db
        )
        initial_password = secrets.token_urlsafe(9)
        reseller = User(
            company_id=None, email=login,
            first_name=data.first_name, last_name=data.last_name,
            role=UserRole.RESELLER,
            password_hash=hash_password(initial_password),
            is_active=True,
        )
    db.add(reseller)
    await db.flush()
    db.add(AuditLog(
        company_id=None, user_id=current_user.id,
        action="reseller_created", entity_type="user", entity_id=reseller.id,
        new_value={"email": reseller.email, "invited": bool(data.email)},
    ))
    await db.flush()

    if data.email:
        from app.services.email_service import email_service
        await email_service.send_invite(reseller, current_user, raw_token, db)

    return ResellerOut(
        id=reseller.id, email=reseller.email, first_name=reseller.first_name,
        last_name=reseller.last_name, is_active=reseller.is_active,
        created_at=reseller.created_at, company_count=0,
        initial_password=initial_password,
    )


@router.patch("/resellers/{reseller_id}", response_model=ResellerOut)
async def update_reseller(
    reseller_id: UUID,
    is_active: bool,
    current_user: User = require_role(*_sa),
    db: AsyncSession = Depends(get_db),
):
    reseller = await db.get(User, reseller_id)
    if reseller is None or reseller.role != UserRole.RESELLER:
        raise HTTPException(status_code=404, detail="Reseller nicht gefunden.")
    reseller.is_active = is_active
    db.add(AuditLog(
        company_id=None, user_id=current_user.id,
        action="reseller_updated", entity_type="user", entity_id=reseller.id,
        new_value={"is_active": is_active},
    ))
    await db.flush()
    counts = await _reseller_company_counts(db)
    return ResellerOut(
        id=reseller.id, email=reseller.email, first_name=reseller.first_name,
        last_name=reseller.last_name, is_active=reseller.is_active,
        created_at=reseller.created_at, company_count=counts.get(reseller.id, 0),
    )


@router.post("/run-retention-purge")
async def run_global_retention_purge(
    current_user: User = require_role(*_sa),
    db: AsyncSession = Depends(get_db),
):
    """Globaler DSGVO-Purge über alle Firmen: Zeiterfassung/Auszahlungen je Firma
    (Frist konfigurierbar) plus firmenübergreifende technische Tabellen
    (audit_logs > 3 Jahre, abgelaufene sessions/password_resets). Gleiche Logik
    wie der tägliche Scheduler-Job."""
    from app.services.retention_service import run_retention_purge
    result = await run_retention_purge(db, company_id=None)
    await db.commit()
    return {"deleted": result}
