"""
CNP Solutions platform operator portal (God Mode).
Separate from tenant super_admin — requires PLATFORM_ADMIN_SECRET or LICENSE_ADMIN_SECRET.
"""
from typing import List, Optional

from fastapi import APIRouter, Depends, HTTPException, Request, status
from sqlalchemy.orm import Session

from app.core.config import settings
from app.core.database import get_db
from app.core.platform_admin import (
    create_platform_access_token,
    effective_platform_admin_secret,
    require_platform_admin,
    verify_platform_secret,
)
from app.models.company import Company
from app.schemas.licensing import (
    LicenseIssueRequest,
    LicenseIssueResponse,
    LicenseRenewRequest,
    LicenseUpgradeRequest,
)
from app.schemas.platform_admin import (
    PlatformAssignLicenseRequest,
    PlatformActiveSessionRow,
    PlatformBranchLicenseCreate,
    PlatformCompanyLicensing,
    PlatformCompanyPatch,
    PlatformCompanyRow,
    PlatformDashboard,
    PlatformImpersonateResponse,
    PlatformLicenseRow,
    PlatformLoginRequest,
    PlatformLoginResponse,
    PlatformResetPasswordRequest,
    PlatformUserRow,
)
from app.services.licensing_service import LicensingService
from app.services.platform_admin_service import PlatformAdminService
from app.services.session_tracking_service import SessionTrackingService

router = APIRouter()


@router.post("/auth/login", response_model=PlatformLoginResponse)
def platform_login(payload: PlatformLoginRequest):
    """Exchange platform secret for an operator JWT (non-expiring when token_hours=0)."""
    if not effective_platform_admin_secret():
        raise HTTPException(
            status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
            detail="Platform admin is not configured. Set PLATFORM_ADMIN_SECRET or LICENSE_ADMIN_SECRET on the server.",
        )
    if not verify_platform_secret(payload.secret):
        raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Invalid platform credentials")
    token_hours = int(settings.platform_admin_token_hours or 0)
    if token_hours < 0:
        token_hours = 0
    elif token_hours > 0:
        token_hours = min(token_hours, 8760)
    return PlatformLoginResponse(
        access_token=create_platform_access_token(hours=token_hours),
        expires_hours=token_hours,
    )


@router.get("/auth/configured")
def platform_configured():
    """Whether God Mode is enabled (no secret required)."""
    return {"configured": bool(effective_platform_admin_secret())}


@router.get("/dashboard", response_model=PlatformDashboard)
def platform_dashboard(
    _admin=Depends(require_platform_admin),
    db: Session = Depends(get_db),
):
    return PlatformDashboard(**PlatformAdminService(db).dashboard())


@router.get("/sessions/active", response_model=List[PlatformActiveSessionRow])
def platform_active_sessions(
    company_id: Optional[str] = None,
    search: Optional[str] = None,
    minutes: int = 45,
    _admin=Depends(require_platform_admin),
    db: Session = Depends(get_db),
):
    """Tenant users currently logged in (recent heartbeat via token check)."""
    rows = SessionTrackingService(db).list_active_for_platform(
        company_id=company_id,
        search=search,
        stale_minutes=max(5, min(minutes, 240)),
    )
    return [PlatformActiveSessionRow(**r) for r in rows]


@router.get("/companies", response_model=List[PlatformCompanyRow])
def platform_list_companies(
    search: Optional[str] = None,
    active_only: Optional[bool] = None,
    _admin=Depends(require_platform_admin),
    db: Session = Depends(get_db),
):
    return PlatformAdminService(db).list_companies(search=search, active_only=active_only)


@router.patch("/companies/{company_id}")
def platform_patch_company(
    company_id: str,
    body: PlatformCompanyPatch,
    _admin=Depends(require_platform_admin),
    db: Session = Depends(get_db),
):
    svc = PlatformAdminService(db)
    try:
        company = svc.patch_company(
            company_id,
            body.model_dump(exclude_unset=True),
        )
    except ValueError as e:
        raise HTTPException(status_code=404, detail=str(e))
    return {
        "success": True,
        "id": company.id,
        "name": company.name,
        "is_active": company.is_active,
        "subscription_plan": company.subscription_plan,
    }


@router.get("/companies/{company_id}/licensing", response_model=PlatformCompanyLicensing)
def platform_company_licensing(
    company_id: str,
    _admin=Depends(require_platform_admin),
    db: Session = Depends(get_db),
):
    try:
        return PlatformAdminService(db).get_company_licensing(company_id)
    except ValueError as e:
        raise HTTPException(status_code=404, detail=str(e))


@router.post("/companies/{company_id}/licensing/assign", response_model=PlatformCompanyLicensing)
def platform_assign_license(
    company_id: str,
    body: PlatformAssignLicenseRequest,
    _admin=Depends(require_platform_admin),
    db: Session = Depends(get_db),
):
    try:
        return PlatformAdminService(db).assign_license_to_company(company_id, body.license_id)
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))


@router.post("/companies/{company_id}/branch-licenses")
def platform_add_branch_licenses(
    company_id: str,
    body: PlatformBranchLicenseCreate,
    _admin=Depends(require_platform_admin),
    db: Session = Depends(get_db),
):
    svc = LicensingService(db)
    created = []
    try:
        for i in range(body.count):
            label = body.label
            if body.count > 1 and label:
                label = f"{label} ({i + 1})"
            bl = svc.issue_branch_license(
                company_id,
                label=label,
                branch_id=body.branch_id if body.count == 1 else None,
                notes=body.notes,
            )
            created.append({
                "id": bl.id,
                "slot_code": bl.slot_code,
                "label": bl.label,
                "valid_until": bl.valid_until.isoformat(),
            })
        db.commit()
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))
    return {
        "success": True,
        "created": created,
        "message": f"Added {len(created)} branch license(s). They expire with the main license.",
    }


@router.post("/branch-licenses/{branch_license_id}/revoke")
def platform_revoke_branch_license(
    branch_license_id: str,
    _admin=Depends(require_platform_admin),
    db: Session = Depends(get_db),
):
    svc = LicensingService(db)
    try:
        bl = svc.revoke_branch_license(branch_license_id)
        db.commit()
    except ValueError as e:
        raise HTTPException(status_code=404, detail=str(e))
    return {"success": True, "id": bl.id, "slot_code": bl.slot_code, "status": bl.status}


@router.post("/companies/{company_id}/license/upgrade")
def platform_upgrade_company_main_license(
    company_id: str,
    payload: LicenseUpgradeRequest,
    _admin=Depends(require_platform_admin),
    db: Session = Depends(get_db),
):
    company = db.query(Company).filter(Company.id == company_id).first()
    if not company or not company.license_key_id:
        raise HTTPException(status_code=404, detail="Company has no main license")
    svc = LicensingService(db)
    try:
        record = svc.upgrade_license(
            company.license_key_id,
            max_branches=payload.max_branches,
            max_users=payload.max_users,
            add_years=payload.add_years,
        )
        db.commit()
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))
    return {
        "success": True,
        "license_id": record.id,
        "max_branches": record.max_branches,
        "max_users": record.max_users,
        "valid_until": record.valid_until.isoformat(),
        "message": "Main license upgraded.",
    }


@router.post("/companies/{company_id}/license/renew")
def platform_renew_company_main_license(
    company_id: str,
    payload: LicenseRenewRequest,
    _admin=Depends(require_platform_admin),
    db: Session = Depends(get_db),
):
    company = db.query(Company).filter(Company.id == company_id).first()
    if not company or not company.license_key_id:
        raise HTTPException(status_code=404, detail="Company has no main license")
    svc = LicensingService(db)
    try:
        record = svc.renew_license(company.license_key_id, years=payload.years)
        db.commit()
    except ValueError as e:
        raise HTTPException(status_code=404, detail=str(e))
    return {
        "success": True,
        "license_id": record.id,
        "valid_until": record.valid_until.isoformat(),
        "renewals_count": record.renewals_count,
        "message": "Main license renewed. All active branch licenses were extended to match.",
    }


@router.post("/companies/{company_id}/license/revoke")
def platform_revoke_company_main_license(
    company_id: str,
    _admin=Depends(require_platform_admin),
    db: Session = Depends(get_db),
):
    company = db.query(Company).filter(Company.id == company_id).first()
    if not company or not company.license_key_id:
        raise HTTPException(status_code=404, detail="Company has no main license")
    svc = LicensingService(db)
    try:
        record = svc.revoke_license(company.license_key_id)
        db.commit()
    except ValueError as e:
        raise HTTPException(status_code=404, detail=str(e))
    return {
        "success": True,
        "license_id": record.id,
        "status": record.status,
        "message": "Main license revoked. All branch licenses for this company were revoked.",
    }


@router.get("/companies/{company_id}/users", response_model=List[PlatformUserRow])
def platform_company_users(
    company_id: str,
    _admin=Depends(require_platform_admin),
    db: Session = Depends(get_db),
):
    return PlatformAdminService(db).list_company_users(company_id)


@router.post("/users/{user_id}/reset-password")
def platform_reset_password(
    user_id: str,
    body: PlatformResetPasswordRequest,
    _admin=Depends(require_platform_admin),
    db: Session = Depends(get_db),
):
    try:
        user = PlatformAdminService(db).reset_user_password(user_id, body.new_password)
    except ValueError as e:
        raise HTTPException(status_code=404, detail=str(e))
    return {"success": True, "user_id": user.id, "username": user.username}


@router.patch("/users/{user_id}/active")
def platform_set_user_active(
    user_id: str,
    active: bool,
    _admin=Depends(require_platform_admin),
    db: Session = Depends(get_db),
):
    try:
        user = PlatformAdminService(db).set_user_active(user_id, active)
    except ValueError as e:
        raise HTTPException(status_code=404, detail=str(e))
    return {"success": True, "user_id": user.id, "active": user.active}


@router.post("/users/{user_id}/impersonate", response_model=PlatformImpersonateResponse)
def platform_impersonate(
    user_id: str,
    request: Request,
    _admin=Depends(require_platform_admin),
    db: Session = Depends(get_db),
):
    base = str(request.base_url).rstrip("/")
    if settings.license_cloud_url:
        base = settings.license_cloud_url.rstrip("/")
    try:
        data = PlatformAdminService(db).impersonate_user(user_id, base)
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))
    return PlatformImpersonateResponse(
        **data,
        message="Use this token in the ERP (sessionStorage auth_token) or open ERP with auto-login.",
    )


@router.get("/licenses/keys", response_model=List[PlatformLicenseRow])
def platform_list_licenses(
    status_filter: Optional[str] = None,
    _admin=Depends(require_platform_admin),
    db: Session = Depends(get_db),
):
    return PlatformAdminService(db).list_licenses(status_filter=status_filter)


@router.get("/licenses/keys/{license_id}", response_model=PlatformLicenseRow)
def platform_get_license(
    license_id: str,
    _admin=Depends(require_platform_admin),
    db: Session = Depends(get_db),
):
    rows = PlatformAdminService(db).list_licenses()
    match = next((r for r in rows if r["id"] == license_id), None)
    if not match:
        raise HTTPException(status_code=404, detail="License not found")
    return match


@router.post("/licenses/keys", response_model=LicenseIssueResponse)
def platform_issue_license(
    payload: LicenseIssueRequest,
    _admin=Depends(require_platform_admin),
    db: Session = Depends(get_db),
):
    svc = LicensingService(db)
    record, full_key = svc.issue_license(
        plan=payload.plan,
        years=payload.years,
        deployment_mode=payload.deployment_mode,
        customer_name=payload.customer_name,
        customer_email=payload.customer_email,
        max_users=payload.max_users,
        max_branches=payload.max_branches,
        notes=payload.notes,
    )
    db.commit()
    return LicenseIssueResponse(
        license_id=record.id,
        license_key=full_key,
        key_prefix=record.key_prefix,
        valid_until=record.valid_until,
        plan=record.plan,
        message="License created. Copy the full key now — it cannot be retrieved again.",
    )


@router.post("/licenses/keys/{license_id}/upgrade")
def platform_upgrade_license(
    license_id: str,
    payload: LicenseUpgradeRequest,
    _admin=Depends(require_platform_admin),
    db: Session = Depends(get_db),
):
    svc = LicensingService(db)
    try:
        record = svc.upgrade_license(
            license_id,
            max_branches=payload.max_branches,
            max_users=payload.max_users,
            add_years=payload.add_years,
        )
        db.commit()
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))
    return {
        "success": True,
        "license_id": record.id,
        "max_branches": record.max_branches,
        "max_users": record.max_users,
        "valid_until": record.valid_until.isoformat(),
        "message": "License upgraded.",
    }


@router.post("/licenses/keys/{license_id}/renew")
def platform_renew_license(
    license_id: str,
    payload: LicenseRenewRequest,
    _admin=Depends(require_platform_admin),
    db: Session = Depends(get_db),
):
    svc = LicensingService(db)
    try:
        record = svc.renew_license(license_id, years=payload.years)
        db.commit()
    except ValueError as e:
        raise HTTPException(status_code=404, detail=str(e))
    return {
        "success": True,
        "license_id": record.id,
        "valid_until": record.valid_until.isoformat(),
        "renewals_count": record.renewals_count,
    }


@router.post("/licenses/keys/{license_id}/revoke")
def platform_revoke_license(
    license_id: str,
    _admin=Depends(require_platform_admin),
    db: Session = Depends(get_db),
):
    svc = LicensingService(db)
    try:
        record = svc.revoke_license(license_id)
        db.commit()
    except ValueError as e:
        raise HTTPException(status_code=404, detail=str(e))
    return {"success": True, "license_id": record.id, "status": record.status}


@router.get("/nodes")
def platform_list_nodes(
    _admin=Depends(require_platform_admin),
    db: Session = Depends(get_db),
):
    return {"success": True, "data": PlatformAdminService(db).list_deployment_nodes()}


@router.post("/nodes/{node_id}/request-sync")
def platform_request_node_sync(
    node_id: str,
    _admin=Depends(require_platform_admin),
    db: Session = Depends(get_db),
):
    """Ask a LAN node to push pending transactions on its next heartbeat."""
    try:
        result = PlatformAdminService(db).request_node_sync(node_id)
        db.commit()
    except ValueError as e:
        raise HTTPException(status_code=404, detail=str(e))
    return {"success": True, **result}


@router.get("/update/check")
def platform_update_check(_admin=Depends(require_platform_admin)):
    from app.services.app_update_service import check_for_updates

    return check_for_updates()


@router.get("/update/status")
def platform_update_status(_admin=Depends(require_platform_admin)):
    from app.services.app_update_service import read_log_tail

    return read_log_tail()


@router.post("/update/trigger")
def platform_trigger_update(_admin=Depends(require_platform_admin)):
    from app.services.app_update_service import trigger_update

    return trigger_update(triggered_by="platform_admin")
