"""
BYOEH Key Sharing and Klausur Linking Routes

Endpoints for sharing EH access with other examiners
and linking EH to Klausuren.
Extracted from routes/eh.py for file-size compliance.
"""

import uuid
from datetime import datetime, timezone

from fastapi import APIRouter, HTTPException, Request

from models.eh import EHKeyShare, EHKlausurLink
from models.requests import EHShareRequest, EHLinkKlausurRequest
from services.auth_service import get_current_user
from services.eh_service import log_eh_audit
import storage

router = APIRouter()


# =============================================
# BYOEH KEY SHARING
# =============================================

@router.post("/api/v1/eh/{eh_id}/share")
async def share_erwartungshorizont(
    eh_id: str,
    share_request: EHShareRequest,
    request: Request
):
    """
    Share an Erwartungshorizont with another examiner.

    The first examiner shares their EH by providing an encrypted passphrase
    that the recipient can use.
    """
    user = get_current_user(request)
    tenant_id = user.get("tenant_id") or user.get("school_id") or user["user_id"]

    # Check EH exists and belongs to user
    if eh_id not in storage.eh_db:
        raise HTTPException(status_code=404, detail="Erwartungshorizont not found")

    eh = storage.eh_db[eh_id]
    if eh.teacher_id != user["user_id"]:
        raise HTTPException(status_code=403, detail="Only the owner can share this EH")

    # Validate role
    valid_roles = ['second_examiner', 'third_examiner', 'supervisor', 'department_head']
    if share_request.role not in valid_roles:
        raise HTTPException(status_code=400, detail=f"Invalid role. Must be one of: {valid_roles}")

    # Create key share entry
    share_id = str(uuid.uuid4())
    key_share = EHKeyShare(
        id=share_id,
        eh_id=eh_id,
        user_id=share_request.user_id,
        encrypted_passphrase=share_request.encrypted_passphrase,
        passphrase_hint=share_request.passphrase_hint or "",
        granted_by=user["user_id"],
        granted_at=datetime.now(timezone.utc),
        role=share_request.role,
        klausur_id=share_request.klausur_id,
        active=True
    )

    # Store in memory
    if eh_id not in storage.eh_key_shares_db:
        storage.eh_key_shares_db[eh_id] = []
    storage.eh_key_shares_db[eh_id].append(key_share)

    # Audit log
    log_eh_audit(
        tenant_id=tenant_id,
        user_id=user["user_id"],
        action="share",
        eh_id=eh_id,
        details={
            "shared_with": share_request.user_id,
            "role": share_request.role,
            "klausur_id": share_request.klausur_id
        }
    )

    return {
        "status": "shared",
        "share_id": share_id,
        "eh_id": eh_id,
        "shared_with": share_request.user_id,
        "role": share_request.role
    }


@router.get("/api/v1/eh/{eh_id}/shares")
async def list_eh_shares(eh_id: str, request: Request):
    """List all users who have access to an EH."""
    user = get_current_user(request)

    # Check EH exists and belongs to user
    if eh_id not in storage.eh_db:
        raise HTTPException(status_code=404, detail="Erwartungshorizont not found")

    eh = storage.eh_db[eh_id]
    if eh.teacher_id != user["user_id"]:
        raise HTTPException(status_code=403, detail="Only the owner can view shares")

    shares = storage.eh_key_shares_db.get(eh_id, [])
    return [share.to_dict() for share in shares if share.active]


@router.delete("/api/v1/eh/{eh_id}/shares/{share_id}")
async def revoke_eh_share(eh_id: str, share_id: str, request: Request):
    """Revoke a shared EH access."""
    user = get_current_user(request)
    tenant_id = user.get("tenant_id") or user.get("school_id") or user["user_id"]

    # Check EH exists and belongs to user
    if eh_id not in storage.eh_db:
        raise HTTPException(status_code=404, detail="Erwartungshorizont not found")

    eh = storage.eh_db[eh_id]
    if eh.teacher_id != user["user_id"]:
        raise HTTPException(status_code=403, detail="Only the owner can revoke shares")

    # Find and deactivate share
    shares = storage.eh_key_shares_db.get(eh_id, [])
    for share in shares:
        if share.id == share_id:
            share.active = False

            log_eh_audit(
                tenant_id=tenant_id,
                user_id=user["user_id"],
                action="revoke_share",
                eh_id=eh_id,
                details={"revoked_user": share.user_id, "share_id": share_id}
            )

            return {"status": "revoked", "share_id": share_id}

    raise HTTPException(status_code=404, detail="Share not found")


# =============================================
# KLAUSUR LINKING
# =============================================

@router.post("/api/v1/eh/{eh_id}/link-klausur")
async def link_eh_to_klausur(
    eh_id: str,
    link_request: EHLinkKlausurRequest,
    request: Request
):
    """
    Link an Erwartungshorizont to a Klausur.

    This creates an association between the EH and a specific Klausur.
    """
    user = get_current_user(request)
    tenant_id = user.get("tenant_id") or user.get("school_id") or user["user_id"]

    # Check EH exists and user has access
    if eh_id not in storage.eh_db:
        raise HTTPException(status_code=404, detail="Erwartungshorizont not found")

    eh = storage.eh_db[eh_id]
    user_has_access = (
        eh.teacher_id == user["user_id"] or
        any(
            share.user_id == user["user_id"] and share.active
            for share in storage.eh_key_shares_db.get(eh_id, [])
        )
    )

    if not user_has_access:
        raise HTTPException(status_code=403, detail="No access to this EH")

    # Check Klausur exists
    klausur_id = link_request.klausur_id
    if klausur_id not in storage.klausuren_db:
        raise HTTPException(status_code=404, detail="Klausur not found")

    # Create link
    link_id = str(uuid.uuid4())
    link = EHKlausurLink(
        id=link_id,
        eh_id=eh_id,
        klausur_id=klausur_id,
        linked_by=user["user_id"],
        linked_at=datetime.now(timezone.utc)
    )

    if klausur_id not in storage.eh_klausur_links_db:
        storage.eh_klausur_links_db[klausur_id] = []
    storage.eh_klausur_links_db[klausur_id].append(link)

    # Audit log
    log_eh_audit(
        tenant_id=tenant_id,
        user_id=user["user_id"],
        action="link_klausur",
        eh_id=eh_id,
        details={"klausur_id": klausur_id}
    )

    return {
        "status": "linked",
        "link_id": link_id,
        "eh_id": eh_id,
        "klausur_id": klausur_id
    }


@router.get("/api/v1/klausuren/{klausur_id}/linked-eh")
async def get_linked_eh(klausur_id: str, request: Request):
    """Get all EH linked to a specific Klausur."""
    user = get_current_user(request)
    user_id = user["user_id"]

    # Check Klausur exists
    if klausur_id not in storage.klausuren_db:
        raise HTTPException(status_code=404, detail="Klausur not found")

    # Get all links for this Klausur
    links = storage.eh_klausur_links_db.get(klausur_id, [])

    linked_ehs = []
    for link in links:
        if link.eh_id in storage.eh_db:
            eh = storage.eh_db[link.eh_id]

            # Check if user has access to this EH
            is_owner = eh.teacher_id == user_id
            is_shared = any(
                share.user_id == user_id and share.active
                for share in storage.eh_key_shares_db.get(link.eh_id, [])
            )

            if is_owner or is_shared:
                # Find user's share info if shared
                share_info = None
                if is_shared:
                    for share in storage.eh_key_shares_db.get(link.eh_id, []):
                        if share.user_id == user_id and share.active:
                            share_info = share.to_dict()
                            break

                linked_ehs.append({
                    "eh": eh.to_dict(),
                    "link": link.to_dict(),
                    "is_owner": is_owner,
                    "share": share_info
                })

    return linked_ehs


@router.delete("/api/v1/eh/{eh_id}/link-klausur/{klausur_id}")
async def unlink_eh_from_klausur(eh_id: str, klausur_id: str, request: Request):
    """Remove the link between an EH and a Klausur."""
    user = get_current_user(request)
    tenant_id = user.get("tenant_id") or user.get("school_id") or user["user_id"]

    # Check EH exists and user has access
    if eh_id not in storage.eh_db:
        raise HTTPException(status_code=404, detail="Erwartungshorizont not found")

    eh = storage.eh_db[eh_id]
    if eh.teacher_id != user["user_id"]:
        raise HTTPException(status_code=403, detail="Only the owner can unlink")

    # Find and remove link
    links = storage.eh_klausur_links_db.get(klausur_id, [])
    for i, link in enumerate(links):
        if link.eh_id == eh_id:
            del links[i]

            log_eh_audit(
                tenant_id=tenant_id,
                user_id=user["user_id"],
                action="unlink_klausur",
                eh_id=eh_id,
                details={"klausur_id": klausur_id}
            )

            return {"status": "unlinked", "eh_id": eh_id, "klausur_id": klausur_id}

    raise HTTPException(status_code=404, detail="Link not found")


@router.get("/api/v1/eh/{eh_id}/access-chain")
async def get_eh_access_chain(eh_id: str, request: Request):
    """
    Get the complete access chain for an EH.

    Shows the correction chain: EK -> ZK -> DK -> FVL
    with their current access status.
    """
    user = get_current_user(request)

    # Check EH exists
    if eh_id not in storage.eh_db:
        raise HTTPException(status_code=404, detail="Erwartungshorizont not found")

    eh = storage.eh_db[eh_id]

    # Check access - owner or shared user
    is_owner = eh.teacher_id == user["user_id"]
    is_shared = any(
        share.user_id == user["user_id"] and share.active
        for share in storage.eh_key_shares_db.get(eh_id, [])
    )

    if not is_owner and not is_shared:
        raise HTTPException(status_code=403, detail="No access to this EH")

    # Build access chain
    chain = {
        "eh_id": eh_id,
        "eh_title": eh.title,
        "owner": {
            "user_id": eh.teacher_id,
            "role": "erstkorrektor"
        },
        "active_shares": [],
        "pending_invitations": [],
        "revoked_shares": []
    }

    # Active shares
    for share in storage.eh_key_shares_db.get(eh_id, []):
        share_dict = share.to_dict()
        if share.active:
            chain["active_shares"].append(share_dict)
        else:
            chain["revoked_shares"].append(share_dict)

    # Pending invitations (only for owner)
    if is_owner:
        for inv in storage.eh_invitations_db.values():
            if inv.eh_id == eh_id and inv.status == 'pending':
                chain["pending_invitations"].append(inv.to_dict())

    return chain
