"""Cloud sync — LAN push, cloud ingest, Settings & God Mode triggers."""
from fastapi import APIRouter, Depends, Header, HTTPException, status
from sqlalchemy.orm import Session

from app.core.config import settings
from app.core.database import get_db
from app.core.security import get_current_user
from app.models.user import User
from app.schemas.cloud_sync import (
    SyncIngestRequest,
    SyncIngestResponse,
    SyncProvisionMirrorRequest,
    SyncProvisionMirrorResponse,
    SyncRunResponse,
    SyncSettingsPatch,
    SyncStatusResponse,
)
from app.services.cloud_mirror_service import provision_mirror_from_local_db
from app.services.cloud_sync_service import CloudSyncService, is_lan_sync_client

router = APIRouter()


def _require_admin(user: User) -> User:
    if (user.role or "").lower() not in ("super_admin", "admin"):
        raise HTTPException(status_code=403, detail="Administrator access required")
    return user


def _verify_sync_node(
    x_sync_node_id: str = Header(..., alias="X-Sync-Node-Id"),
    x_sync_token: str = Header(..., alias="X-Sync-Token"),
    db: Session = Depends(get_db),
):
    node = CloudSyncService.verify_node_token(db, x_sync_node_id, x_sync_token)
    if not node:
        raise HTTPException(status_code=401, detail="Invalid sync node credentials")
    return node


@router.get("/status", response_model=SyncStatusResponse)
def sync_status(
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    """LAN Settings — cloud sync queue status."""
    _require_admin(current_user)
    return SyncStatusResponse(**CloudSyncService(db).status())


@router.post("/provision-mirror", response_model=SyncProvisionMirrorResponse)
def provision_mirror_now(
    body: SyncProvisionMirrorRequest,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    """LAN Settings — create or refresh cloud tenant + sync node for an existing local install."""
    _require_admin(current_user)
    if not is_lan_sync_client():
        raise HTTPException(
            status_code=400,
            detail="Create cloud mirror is available on local/hybrid servers only",
        )
    result = provision_mirror_from_local_db(
        db,
        current_user,
        license_key_override=body.license_key,
        public_base_url=body.public_base_url,
    )
    cfg = CloudSyncService(db).status()
    return SyncProvisionMirrorResponse(
        success=bool(result.get("success")),
        message=result.get("message") or "Done",
        cloud_login_url=result.get("cloud_login_url"),
        node_configured=bool(cfg.get("node_configured")),
    )


@router.post("/run", response_model=SyncRunResponse)
async def sync_run_now(
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    """Manual sync from Settings on LAN server."""
    _require_admin(current_user)
    if not is_lan_sync_client():
        raise HTTPException(status_code=400, detail="Cloud sync runs on local/hybrid servers only")
    svc = CloudSyncService(db)
    hb = await svc.heartbeat_and_sync_async()
    pushed = int(hb.get("pushed") or 0)
    failed = int(hb.get("failed") or 0)
    msg = hb.get("message") or "Sync complete"
    if not hb.get("heartbeat") and hb.get("message"):
        return SyncRunResponse(success=False, message=msg, pushed=pushed, failed=failed)
    ok = hb.get("heartbeat") or pushed > 0 or msg.lower().find("nothing") >= 0
    return SyncRunResponse(success=ok, message=msg, pushed=pushed, failed=failed)


@router.patch("/settings")
def sync_settings_patch(
    body: SyncSettingsPatch,
    current_user: User = Depends(get_current_user),
):
    """Toggle realtime sync (in-memory for this process; persist via env for production)."""
    _require_admin(current_user)
    if not is_lan_sync_client():
        raise HTTPException(
            status_code=400,
            detail="Realtime sync toggle applies to local/hybrid servers only",
        )
    if body.realtime_enabled is not None:
        settings.cloud_sync_realtime = body.realtime_enabled
    return {"realtime_enabled": settings.cloud_sync_realtime}


@router.post("/ingest", response_model=SyncIngestResponse)
def sync_ingest(
    body: SyncIngestRequest,
    node=Depends(_verify_sync_node),
    db: Session = Depends(get_db),
):
    """Cloud hub — receive transaction batch from LAN node."""
    if (settings.deployment_mode or "cloud").lower() != "cloud":
        raise HTTPException(status_code=400, detail="Ingest endpoint is for the cloud hub only")
    svc = CloudSyncService(db)
    result = svc.ingest_events(node, [e.model_dump() for e in body.events])
    db.commit()
    return SyncIngestResponse(**result)
