import asyncio
import uuid
import time
from concurrent.futures import ProcessPoolExecutor
from contextlib import asynccontextmanager
from typing import Optional
from datetime import datetime

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

from app.database import engine, Base, get_db
from app.models import Document, InteractionThread, Message
from app.schemas import DocumentCreate, DocumentResponse, ThreadCreate, MessageListResponse, MessageResponse

# --- Hybrid Concurrency Config (ADR-007) ---
process_pool = ProcessPoolExecutor(max_workers=4)

@asynccontextmanager
async def lifespan(app: FastAPI):
    # Initialize DB (Auto-create tables for demo)
    async with engine.begin() as conn:
        await conn.run_sync(Base.metadata.create_all)
    yield
    process_pool.shutdown()
    await engine.dispose()

app = FastAPI(title="DirektVermittlungDe API", lifespan=lifespan)

# --- Dependencies ---
async def get_current_user():
    return {"id": "citizen-123", "role": "citizen"}

# --- CPU Bound Logic (Isolated) ---
def cpu_bound_validation(payload_base64: str) -> bool:
    '''Simulates heavy crypto validation away from the Event Loop'''
    time.sleep(0.1) # Simulate CPU work
    return True

# --- Routes ---

@app.post("/documents", response_model=DocumentResponse, status_code=201)
async def upload_document(
    doc_in: DocumentCreate, 
    db: AsyncSession = Depends(get_db),
    user = Depends(get_current_user)
):
    # 1. Offload CPU heavy validation
    loop = asyncio.get_running_loop()
    is_valid = await loop.run_in_executor(
        process_pool, 
        cpu_bound_validation, 
        doc_in.encryptedPayload
    )
    if not is_valid:
        raise HTTPException(status_code=400, detail="Invalid payload")

    # 2. Mock S3 Upload
    s3_key = f"s3://bucket/{uuid.uuid4()}.enc"

    # 3. Create Record
    new_doc = Document(
        authority_id=doc_in.metadata.authorityId,
        reference_number=doc_in.metadata.referenceNumber,
        doc_type=doc_in.metadata.docType.value,
        storage_path=s3_key,
        status="ROUTED"
    )
    db.add(new_doc)
    await db.commit()
    await db.refresh(new_doc)

    return DocumentResponse(
        id=new_doc.id, 
        status=new_doc.status, 
        assignedUnit="Tax-Team-A"
    )

@app.get("/threads/{thread_id}/messages", response_model=MessageListResponse)
async def get_messages(
    thread_id: str,
    limit: int = 20,
    before: Optional[datetime] = Query(None),
    db: AsyncSession = Depends(get_db)
):
    # Cursor Pagination Logic
    query = select(Message).where(Message.thread_id == uuid.UUID(thread_id))
    if before:
        query = query.where(Message.timestamp < before)
    
    query = query.order_by(Message.timestamp.desc()).limit(limit)
    result = await db.execute(query)
    messages = result.scalars().all()

    next_cursor = messages[-1].timestamp if messages else None

    return MessageListResponse(
        data=[
            MessageResponse(
                id=m.id, 
                senderRole=m.sender_role, 
                content=m.content_blob, 
                timestamp=m.timestamp
            ) for m in messages
        ],
        nextCursor=next_cursor
    )