"""
CalDAV-Konfiguration und manueller Sync-Trigger.

Firmenkalender: nur COMPANY_ADMIN / SUPER_ADMIN
Persönlicher Kalender: jeder eingeloggte Nutzer für sich selbst
"""
import uuid

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

from app.core.database import get_db
from app.core.dependencies import CurrentUser, require_role
from app.models.caldav_config import CaldavCompanyConfig, CaldavUserConfig
from app.models.user import User, UserRole
from app.schemas.caldav import (
    CaldavCompanyConfigOut,
    CaldavCompanyConfigSave,
    CaldavUserConfigOut,
    CaldavUserConfigSave,
    ResyncResult,
)
from app.services.caldav_service import caldav_service, encrypt_password

router = APIRouter(prefix="/caldav", tags=["CalDAV"])

_admin_roles = (UserRole.COMPANY_ADMIN, UserRole.SUPER_ADMIN)


# ── Firmenkalender ─────────────────────────────────────────────────────────────

@router.get("/company/config", response_model=CaldavCompanyConfigOut | None)
async def get_company_config(
    current_user: User = require_role(*_admin_roles),
    db: AsyncSession = Depends(get_db),
):
    cfg = await caldav_service.get_company_config(current_user.company_id, db)
    return CaldavCompanyConfigOut.model_validate(cfg) if cfg else None


@router.post("/company/config", response_model=CaldavCompanyConfigOut)
async def save_company_config(
    data: CaldavCompanyConfigSave,
    current_user: User = require_role(*_admin_roles),
    db: AsyncSession = Depends(get_db),
):
    cfg = await caldav_service.get_company_config(current_user.company_id, db)
    if cfg is None:
        cfg = CaldavCompanyConfig(company_id=current_user.company_id, id=uuid.uuid4())
        db.add(cfg)

    # SSRF-Schutz: URL validieren bevor sie gespeichert wird
    if data.calendar_url:
        try:
            from app.services.caldav_service import _validate_caldav_url
            _validate_caldav_url(data.calendar_url)
        except ValueError as exc:
            raise HTTPException(status_code=400, detail=f"Ungültige Kalender-URL: {exc}")
    if data.principal_url:
        try:
            from app.services.caldav_service import _validate_caldav_url
            _validate_caldav_url(data.principal_url)
        except ValueError as exc:
            raise HTTPException(status_code=400, detail=f"Ungültige Principal-URL: {exc}")

    cfg.enabled = data.enabled
    cfg.principal_url = data.principal_url
    cfg.calendar_url = data.calendar_url
    cfg.username = data.username
    cfg.calendar_display_name = data.calendar_display_name
    cfg.verify_ssl = data.verify_ssl
    if data.password:
        cfg.password_encrypted = encrypt_password(data.password)
    elif not cfg.password_encrypted:
        raise HTTPException(status_code=400, detail="Passwort wird beim ersten Speichern benötigt.")

    await db.commit()
    return CaldavCompanyConfigOut.model_validate(cfg)


@router.post("/company/test")
async def test_company_config(
    current_user: User = require_role(*_admin_roles),
    db: AsyncSession = Depends(get_db),
):
    cfg = await caldav_service.get_company_config(current_user.company_id, db)
    if not cfg:
        raise HTTPException(status_code=404, detail="Keine Firmen-CalDAV-Konfiguration vorhanden.")
    result = await caldav_service.test_config(cfg)
    if not result["ok"]:
        raise HTTPException(status_code=502, detail=result["error"])
    return {"message": "Verbindung erfolgreich.", "http_status": result.get("status")}


@router.post("/company/resync", response_model=ResyncResult)
async def resync_all(
    current_user: User = require_role(*_admin_roles),
    db: AsyncSession = Depends(get_db),
):
    """Alle genehmigten Abwesenheiten neu in den Firmenkalender synchronisieren."""
    result = await caldav_service.resync_all_approved(current_user.company_id, db)
    await db.commit()
    return ResyncResult(**result)


# ── Persönlicher Kalender ──────────────────────────────────────────────────────

@router.get("/user/config", response_model=CaldavUserConfigOut | None)
async def get_user_config(
    current_user: CurrentUser,
    db: AsyncSession = Depends(get_db),
):
    cfg = await caldav_service.get_user_config(current_user.id, db)
    return CaldavUserConfigOut.model_validate(cfg) if cfg else None


@router.post("/user/config", response_model=CaldavUserConfigOut)
async def save_user_config(
    data: CaldavUserConfigSave,
    current_user: CurrentUser,
    db: AsyncSession = Depends(get_db),
):
    cfg = await caldav_service.get_user_config(current_user.id, db)
    if cfg is None:
        cfg = CaldavUserConfig(user_id=current_user.id, id=uuid.uuid4())
        db.add(cfg)

    # SSRF-Schutz: URL validieren bevor sie gespeichert wird
    if data.calendar_url:
        try:
            from app.services.caldav_service import _validate_caldav_url
            _validate_caldav_url(data.calendar_url)
        except ValueError as exc:
            raise HTTPException(status_code=400, detail=f"Ungültige Kalender-URL: {exc}")
    if data.principal_url:
        try:
            from app.services.caldav_service import _validate_caldav_url
            _validate_caldav_url(data.principal_url)
        except ValueError as exc:
            raise HTTPException(status_code=400, detail=f"Ungültige Principal-URL: {exc}")

    cfg.enabled = data.enabled
    cfg.principal_url = data.principal_url
    cfg.calendar_url = data.calendar_url
    cfg.username = data.username
    cfg.calendar_display_name = data.calendar_display_name
    cfg.verify_ssl = data.verify_ssl
    if data.password:
        cfg.password_encrypted = encrypt_password(data.password)
    elif not cfg.password_encrypted:
        raise HTTPException(status_code=400, detail="Passwort wird beim ersten Speichern benötigt.")

    await db.commit()
    return CaldavUserConfigOut.model_validate(cfg)


@router.post("/user/test")
async def test_user_config(
    current_user: CurrentUser,
    db: AsyncSession = Depends(get_db),
):
    cfg = await caldav_service.get_user_config(current_user.id, db)
    if not cfg:
        raise HTTPException(status_code=404, detail="Keine persönliche CalDAV-Konfiguration vorhanden.")
    result = await caldav_service.test_config(cfg)
    if not result["ok"]:
        raise HTTPException(status_code=502, detail=result["error"])
    return {"message": "Verbindung erfolgreich.", "http_status": result.get("status")}
