import uuid
from datetime import datetime, timedelta
from typing import Dict, List, Optional, Any

from pydantic import BaseModel, Field, validator
from sqlalchemy import String, Text, func
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship
from sqlalchemy.sql import delete

class Base(DeclarativeBase):
    pass

class Metadata(BaseModel):
    authority_id: str = Field(..., description="Authority ID for routing")
    reference_number: str = Field(..., description="Aktenzeichen/Kassenzeichen")
    doc_type: str = Field(..., enum=["NOTICE", "COURT_ORDER", "GENERAL_INQUIRY"])
    issued_at: datetime

    @validator('doc_type')
    def validate_doc_type(cls, v):
        if v not in ["NOTICE", "COURT_ORDER", "GENERAL_INQUIRY"]:
            raise ValueError("Invalid document type")
        return v

class DocumentEnvelope(BaseModel):
    id: Optional[str] = Field(default_factory=lambda: str(uuid.uuid4()), read_only=True)
    metadata: Metadata
    encrypted_payload: str = Field(..., description="Base64 E2E Encrypted PDF")
    status: str = Field(default="RECEIVED", enum=["RECEIVED", "ROUTED", "ASSIGNED", "CLOSED"], read_only=True)
    retention_date: Optional[datetime] = None

class ThreadType(BaseModel):
    type: str = Field(..., enum=["TEXT_CHAT", "CALLBACK_REQUEST", "APPOINTMENT"])
    initial_message: Optional[str] = None

class InteractionThread(BaseModel):
    id: Optional[str] = Field(default_factory=lambda: str(uuid.uuid4()), read_only=True)
    document_id: str
    type: str = Field(..., enum=["TEXT_CHAT", "CALLBACK_REQUEST", "APPOINTMENT"])
    status: str = Field(default="OPEN", enum=["OPEN", "PENDING_OFFICIAL", "PENDING_CITIZEN", "RESOLVED"])
    assigned_official_id: Optional[str] = None

class Message(BaseModel):
    id: Optional[str] = Field(default_factory=lambda: str(uuid.uuid4()), read_only=True)
    thread_id: str
    sender_role: str = Field(..., enum=["CITIZEN", "OFFICIAL"])
    content: str = Field(..., description="Encrypted message content")
    timestamp: datetime = Field(default_factory=datetime.now)

class ExportRequest(BaseModel):
    case_id: str
    target_system: str = "eAkte-Standard-V2"
    include_attachments: bool = True

class ExportJob(BaseModel):
    job_id: str
    status: str = "QUEUED"

# DB Models
class Document(Base):
    __tablename__ = "documents"
    id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
    reference_number: Mapped[str] = mapped_column(String(50), index=True)
    authority_id: Mapped[str] = mapped_column(String(50), index=True)
    doc_type: Mapped[str] = mapped_column(String(20))
    status: Mapped[str] = mapped_column(String(20), default="RECEIVED")
    storage_path: Mapped[str] = mapped_column(String(255))  # S3 key
    issued_at: Mapped[datetime]
    retention_date: Mapped[Optional[datetime]]
    threads: relationship("Thread", back_populates="document")

class Thread(Base):
    __tablename__ = "threads"
    id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
    document_id: Mapped[str] = mapped_column(String(36), index=True)
    type: Mapped[str] = mapped_column(String(20))
    status: Mapped[str] = mapped_column(String(20), default="OPEN")
    assigned_official_id: Mapped[Optional[str]] = mapped_column(String(100))
    document: relationship("Document", back_populates="threads")
    messages: relationship("Message", back_populates="thread")

class Message(Base):
    __tablename__ = "messages"
    id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
    thread_id: Mapped[str] = mapped_column(String(36), index=True)
    sender_role: Mapped[str] = mapped_column(String(20))
    content: Mapped[str] = mapped_column(Text)  # Encrypted
    timestamp: Mapped[datetime] = mapped_column(default=func.now())
    thread: relationship("Thread", back_populates="messages")