"""
Microsoft Intune / Graph integration HTTP endpoints.

- POST /api/v1/integrations/intune/test   auth/connectivity probe
- POST /api/v1/integrations/intune/sync    trigger device+inventory sync

Config lives in settings table key `intune_config` (encrypted JSON:
tenant_id, client_id, client_secret, verify_ssl, auto_create_assets,
detected_apps).
"""
from __future__ import annotations

import logging
import threading
import time
from typing import Optional

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

from app.auth.dependencies import RequireAdmin, RequireEditor
from app.database import get_db, SessionLocal
from app.models.user import User
from app.services.intune_service import load_intune_config, run_intune_sync, _build_client

logger = logging.getLogger(__name__)

router = APIRouter(prefix="/api/v1/integrations/intune", tags=["Intune"])

# Last/current manual-sync state so the GUI can poll for completion (the sync
# itself is fire-and-forget 202). ponytail: module-level state assumes the
# single uvicorn worker we ship with; if you add --workers, move this to the DB.
_INTUNE_SYNC: dict = {"running": False, "result": None, "error": None,
                      "started_at": None, "finished_at": None}


@router.post("/test")
async def test_intune(
    db: Session = Depends(get_db),
    current_user: User = Depends(RequireAdmin),
):
    """Verify the Intune/Graph credentials: acquire a token + read 1 device."""
    cfg = load_intune_config(db)
    if not cfg:
        raise HTTPException(400, "Intune is not configured (tenant_id/client_id/client_secret missing).")
    client = _build_client(cfg)
    try:
        return client.test_connection()
    finally:
        client.close()


def _run_intune_sync_threaded() -> None:
    db = SessionLocal()
    try:
        stats = run_intune_sync(db)
        result = {k: v for k, v in stats.items() if k != "errors"}
        _INTUNE_SYNC["result"] = result
        _INTUNE_SYNC["error"] = None
        logger.info("Intune sync (manual) done: %s", result)
    except Exception as e:
        _INTUNE_SYNC["result"] = None
        _INTUNE_SYNC["error"] = str(e)
        logger.error("Intune sync (manual) failed: %s", e)
    finally:
        db.close()
        _INTUNE_SYNC["running"] = False
        _INTUNE_SYNC["finished_at"] = time.time()


@router.post("/sync", status_code=202)
async def sync_intune(
    db: Session = Depends(get_db),
    current_user: User = Depends(RequireEditor),
):
    """Kick off an Intune device/inventory sync in the background (202).

    Fire-and-forget so a large tenant can't trip the reverse-proxy request
    timeout. Poll GET /sync/status for completion."""
    if not load_intune_config(db):
        raise HTTPException(400, "Intune is not configured.")
    if _INTUNE_SYNC["running"]:
        return {"status": "already_running", "detail": "An Intune sync is already in progress."}
    _INTUNE_SYNC.update({"running": True, "result": None, "error": None,
                         "started_at": time.time(), "finished_at": None})
    threading.Thread(target=_run_intune_sync_threaded, daemon=True).start()
    return {"status": "started", "detail": "Intune sync started in the background."}


@router.get("/sync/status")
async def sync_intune_status(current_user: User = Depends(RequireEditor)):
    """Poll target for the GUI: current/last manual-sync state + result stats."""
    s = _INTUNE_SYNC
    state = ("running" if s["running"]
             else "error" if s["error"]
             else "done" if s["result"]
             else "idle")
    return {"state": state, "running": s["running"], "result": s["result"],
            "error": s["error"], "finished_at": s["finished_at"]}
