"""
BreakPilot Meeting Consent API

DSGVO-konforme Zustimmungsverwaltung fuer Meeting-Aufzeichnungen.
Alle Teilnehmer muessen zustimmen bevor eine Aufzeichnung gestartet wird.
"""

import os
import uuid
from datetime import datetime
from typing import Optional, List
from pydantic import BaseModel, Field

from fastapi import APIRouter, HTTPException, Query

router = APIRouter(prefix="/api/meeting-consent", tags=["Meeting Consent"])


# ==========================================
# PYDANTIC MODELS
# ==========================================

class ConsentRequest(BaseModel):
    """Request to initiate consent for recording."""
    meeting_id: str = Field(..., description="Jitsi meeting room ID")
    consent_type: str = Field(
        default="opt_in",
        description="Consent type: opt_in (explicit), announced (verbal)"
    )
    participant_count: int = Field(
        default=0,
        description="Expected number of participants"
    )
    requested_by: Optional[str] = Field(None, description="User ID of requester")


class ParticipantConsent(BaseModel):
    """Individual participant consent."""
    participant_id: str = Field(..., description="Participant identifier")
    participant_name: Optional[str] = Field(None, description="Display name")
    consented: bool = Field(..., description="Whether consent was given")


class ConsentStatus(BaseModel):
    """Current consent status for a meeting."""
    id: str
    meeting_id: str
    consent_type: str
    participant_count: int
    consented_count: int
    all_consented: bool
    can_record: bool
    status: str  # pending, approved, rejected, withdrawn
    requested_at: datetime
    approved_at: Optional[datetime]
    expires_at: Optional[datetime]


class ConsentWithdrawal(BaseModel):
    """Request to withdraw consent."""
    reason: Optional[str] = Field(None, description="Reason for withdrawal")


# ==========================================
# IN-MEMORY STORAGE (Dev Mode)
# ==========================================

_consent_store: dict = {}
_participant_consents: dict = {}  # consent_id -> [participant consents]


# ==========================================
# API ENDPOINTS
# ==========================================

@router.get("/health")
async def consent_health():
    """Health check for consent service."""
    return {
        "status": "healthy",
        "active_consents": len([c for c in _consent_store.values() if c["status"] in ["pending", "approved"]]),
        "total_consents": len(_consent_store)
    }


@router.post("/request", response_model=ConsentStatus)
async def request_recording_consent(request: ConsentRequest):
    """
    Initiate a consent request for meeting recording.

    This creates a new consent record and returns a status object.
    Recording can only start when all_consented is True.
    """
    # Check if consent already exists for this meeting
    existing = next(
        (c for c in _consent_store.values()
         if c["meeting_id"] == request.meeting_id and c["status"] not in ["withdrawn", "expired"]),
        None
    )
    if existing:
        raise HTTPException(
            status_code=409,
            detail=f"Consent request already exists for meeting {request.meeting_id}"
        )

    consent_id = str(uuid.uuid4())
    now = datetime.utcnow()

    consent = {
        "id": consent_id,
        "meeting_id": request.meeting_id,
        "consent_type": request.consent_type,
        "participant_count": request.participant_count,
        "consented_count": 0,
        "all_consented": False,
        "status": "pending",
        "requested_by": request.requested_by,
        "requested_at": now.isoformat(),
        "approved_at": None,
        "withdrawn_at": None,
        "created_at": now.isoformat(),
        "updated_at": now.isoformat()
    }

    _consent_store[consent_id] = consent
    _participant_consents[consent_id] = []

    return ConsentStatus(
        id=consent_id,
        meeting_id=request.meeting_id,
        consent_type=request.consent_type,
        participant_count=request.participant_count,
        consented_count=0,
        all_consented=False,
        can_record=False,
        status="pending",
        requested_at=now,
        approved_at=None,
        expires_at=None
    )


@router.get("/{meeting_id}", response_model=ConsentStatus)
async def get_consent_status(meeting_id: str):
    """
    Get current consent status for a meeting.

    Returns the consent status including whether recording is allowed.
    """
    consent = next(
        (c for c in _consent_store.values()
         if c["meeting_id"] == meeting_id and c["status"] not in ["withdrawn", "expired"]),
        None
    )

    if not consent:
        # Return default status (no consent requested)
        return ConsentStatus(
            id="",
            meeting_id=meeting_id,
            consent_type="none",
            participant_count=0,
            consented_count=0,
            all_consented=False,
            can_record=False,
            status="not_requested",
            requested_at=datetime.utcnow(),
            approved_at=None,
            expires_at=None
        )

    requested_at = datetime.fromisoformat(consent["requested_at"])
    approved_at = (
        datetime.fromisoformat(consent["approved_at"])
        if consent.get("approved_at") else None
    )

    return ConsentStatus(
        id=consent["id"],
        meeting_id=consent["meeting_id"],
        consent_type=consent["consent_type"],
        participant_count=consent["participant_count"],
        consented_count=consent["consented_count"],
        all_consented=consent["all_consented"],
        can_record=consent["all_consented"] and consent["status"] == "approved",
        status=consent["status"],
        requested_at=requested_at,
        approved_at=approved_at,
        expires_at=None
    )


@router.post("/{meeting_id}/participant")
async def record_participant_consent(
    meeting_id: str,
    consent: ParticipantConsent
):
    """
    Record individual participant consent.

    Each participant must explicitly consent to recording.
    When all participants have consented, recording is automatically approved.
    """
    consent_record = next(
        (c for c in _consent_store.values()
         if c["meeting_id"] == meeting_id and c["status"] == "pending"),
        None
    )

    if not consent_record:
        raise HTTPException(
            status_code=404,
            detail="No pending consent request found for this meeting"
        )

    consent_id = consent_record["id"]

    # Check if participant already consented
    existing = next(
        (p for p in _participant_consents.get(consent_id, [])
         if p["participant_id"] == consent.participant_id),
        None
    )
    if existing:
        # Update existing consent
        existing["consented"] = consent.consented
        existing["updated_at"] = datetime.utcnow().isoformat()
    else:
        # Add new participant consent
        _participant_consents[consent_id].append({
            "participant_id": consent.participant_id,
            "participant_name": consent.participant_name,
            "consented": consent.consented,
            "created_at": datetime.utcnow().isoformat(),
            "updated_at": datetime.utcnow().isoformat()
        })

    # Recalculate consent count
    participants = _participant_consents.get(consent_id, [])
    consented_count = sum(1 for p in participants if p["consented"])

    consent_record["consented_count"] = consented_count
    consent_record["updated_at"] = datetime.utcnow().isoformat()

    # Check if all participants have consented
    if consent_record["participant_count"] > 0:
        all_consented = consented_count >= consent_record["participant_count"]
    else:
        # If participant_count is 0, check if we have at least one consent
        all_consented = consented_count > 0 and all(p["consented"] for p in participants)

    consent_record["all_consented"] = all_consented

    # Auto-approve if all consented
    if all_consented and consent_record["status"] == "pending":
        consent_record["status"] = "approved"
        consent_record["approved_at"] = datetime.utcnow().isoformat()

    return {
        "success": True,
        "meeting_id": meeting_id,
        "participant_id": consent.participant_id,
        "consented": consent.consented,
        "consented_count": consented_count,
        "all_consented": consent_record["all_consented"],
        "can_record": consent_record["status"] == "approved"
    }


@router.get("/{meeting_id}/participants")
async def get_participant_consents(meeting_id: str):
    """
    Get list of participant consents for a meeting.

    Returns all recorded consents with anonymized participant IDs.
    """
    consent_record = next(
        (c for c in _consent_store.values() if c["meeting_id"] == meeting_id),
        None
    )

    if not consent_record:
        raise HTTPException(
            status_code=404,
            detail="No consent request found for this meeting"
        )

    participants = _participant_consents.get(consent_record["id"], [])

    return {
        "meeting_id": meeting_id,
        "consent_id": consent_record["id"],
        "participant_count": consent_record["participant_count"],
        "participants": [
            {
                "participant_id": p["participant_id"][-8:],  # Anonymize
                "consented": p["consented"],
                "timestamp": p["created_at"]
            }
            for p in participants
        ]
    }


@router.post("/{meeting_id}/withdraw")
async def withdraw_consent(
    meeting_id: str,
    withdrawal: ConsentWithdrawal
):
    """
    Withdraw consent for a meeting recording (DSGVO right).

    This immediately stops any ongoing recording and marks the consent as withdrawn.
    Existing recordings will be marked for deletion.
    """
    consent_record = next(
        (c for c in _consent_store.values()
         if c["meeting_id"] == meeting_id and c["status"] in ["pending", "approved"]),
        None
    )

    if not consent_record:
        raise HTTPException(
            status_code=404,
            detail="No active consent found for this meeting"
        )

    consent_record["status"] = "withdrawn"
    consent_record["withdrawn_at"] = datetime.utcnow().isoformat()
    consent_record["withdrawal_reason"] = withdrawal.reason
    consent_record["updated_at"] = datetime.utcnow().isoformat()

    return {
        "success": True,
        "meeting_id": meeting_id,
        "status": "withdrawn",
        "message": "Consent withdrawn. Recording stopped if active.",
        "reason": withdrawal.reason
    }


@router.delete("/{meeting_id}")
async def delete_consent_request(
    meeting_id: str,
    reason: str = Query(..., description="Reason for deletion")
):
    """
    Delete a consent request (admin only).

    This removes the consent request entirely. Use withdraw for user-initiated cancellation.
    """
    consent_record = next(
        (c for c in _consent_store.values() if c["meeting_id"] == meeting_id),
        None
    )

    if not consent_record:
        raise HTTPException(
            status_code=404,
            detail="No consent request found for this meeting"
        )

    consent_id = consent_record["id"]

    # Remove from stores
    del _consent_store[consent_id]
    if consent_id in _participant_consents:
        del _participant_consents[consent_id]

    return {
        "success": True,
        "meeting_id": meeting_id,
        "deleted": True,
        "reason": reason
    }


# ==========================================
# BULK OPERATIONS
# ==========================================

@router.post("/announce")
async def announce_recording(
    meeting_id: str = Query(...),
    announced_by: str = Query(..., description="Name of person announcing")
):
    """
    Mark recording as verbally announced.

    For scenarios where verbal announcement is used instead of explicit opt-in.
    This creates an 'announced' consent type that allows recording.
    """
    # Check if consent already exists
    existing = next(
        (c for c in _consent_store.values()
         if c["meeting_id"] == meeting_id and c["status"] not in ["withdrawn", "expired"]),
        None
    )
    if existing:
        raise HTTPException(
            status_code=409,
            detail="Consent already exists for this meeting"
        )

    consent_id = str(uuid.uuid4())
    now = datetime.utcnow()

    consent = {
        "id": consent_id,
        "meeting_id": meeting_id,
        "consent_type": "announced",
        "participant_count": 0,
        "consented_count": 0,
        "all_consented": True,  # Announced = implicit consent
        "status": "approved",
        "requested_by": announced_by,
        "announced_by": announced_by,
        "requested_at": now.isoformat(),
        "approved_at": now.isoformat(),
        "withdrawn_at": None,
        "created_at": now.isoformat(),
        "updated_at": now.isoformat()
    }

    _consent_store[consent_id] = consent

    return {
        "success": True,
        "meeting_id": meeting_id,
        "consent_id": consent_id,
        "consent_type": "announced",
        "can_record": True,
        "announced_by": announced_by,
        "message": "Recording announced. Participants should be informed verbally."
    }


