"""
SQLAlchemy ORM models — Son of Anton v4.2.0
"""

from datetime import datetime
from uuid import uuid4

from sqlalchemy import (
    Column, String, Text, Boolean, BigInteger, Integer, DateTime, ForeignKey,
)
from sqlalchemy.orm import relationship

from backend.database import Base


def new_id() -> str:
    return str(uuid4())


def next_month() -> datetime:
    now = datetime.utcnow()
    if now.month == 12:
        return datetime(now.year + 1, 1, 1)
    return datetime(now.year, now.month + 1, 1)


class User(Base):
    __tablename__ = "users"

    id = Column(String(36), primary_key=True, default=new_id)
    username = Column(String(50), unique=True, nullable=False, index=True)
    email = Column(String(120), unique=True, nullable=False)
    password_hash = Column(String(200), nullable=False)
    role = Column(String(20), default="user")
    is_active = Column(Boolean, default=True)
    quota_tokens_monthly = Column(BigInteger, default=2_000_000)
    tokens_used_this_month = Column(BigInteger, default=0)
    quota_reset_date = Column(DateTime, default=next_month)
    created_at = Column(DateTime, default=datetime.utcnow)

    chats = relationship("Chat", back_populates="user", cascade="all,delete-orphan")
    permissions = relationship(
        "UserPermissions", back_populates="user", uselist=False,
        cascade="all,delete-orphan",
    )


class UserPermissions(Base):
    __tablename__ = "user_permissions"

    id = Column(String(36), primary_key=True, default=new_id)
    user_id = Column(
        String(36), ForeignKey("users.id", ondelete="CASCADE"),
        unique=True, nullable=False, index=True,
    )

    can_use_web_search = Column(Boolean, default=False)
    can_use_ui_design = Column(Boolean, default=False)
    can_use_knowledge_base = Column(Boolean, default=True)
    can_use_gitlab = Column(Boolean, default=False)
    can_use_attachments = Column(Boolean, default=True)
    can_export_pptx = Column(Boolean, default=True)
    can_export_docx = Column(Boolean, default=True)

    allowed_models = Column(Text, default="eu.anthropic.claude-haiku-4-5-20251001-v1:0")

    max_tokens_cap = Column(Integer, default=4096)
    max_reasoning_budget = Column(Integer, default=0)
    max_chats = Column(Integer, default=50)
    max_messages_per_day = Column(Integer, default=100)
    max_knowledge_bases = Column(Integer, default=3)
    max_documents_per_kb = Column(Integer, default=20)
    max_attachment_size_mb = Column(Integer, default=10)
    max_attachments_per_message = Column(Integer, default=5)

    updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)

    user = relationship("User", back_populates="permissions")


class AppSettings(Base):
    __tablename__ = "app_settings"

    id = Column(String(36), primary_key=True, default=new_id)
    registration_enabled = Column(Boolean, default=True)
    updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)


class Chat(Base):
    __tablename__ = "chats"

    id = Column(String(36), primary_key=True, default=new_id)
    user_id = Column(String(36), ForeignKey("users.id", ondelete="CASCADE"), nullable=False)
    title = Column(String(200), default="New Chat")
    model = Column(String(100), default="eu.anthropic.claude-opus-4-6-v1")
    knowledge_base_id = Column(String(36), nullable=True)
    linked_repo_id = Column(String(36), nullable=True)
    max_tokens = Column(Integer, default=4096)
    reasoning_budget = Column(Integer, default=0)
    created_at = Column(DateTime, default=datetime.utcnow)
    updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)

    user = relationship("User", back_populates="chats")
    messages = relationship(
        "Message", back_populates="chat",
        cascade="all,delete-orphan", order_by="Message.created_at",
    )
    attachments = relationship(
        "ChatAttachment", back_populates="chat",
        cascade="all,delete-orphan",
    )


class Message(Base):
    __tablename__ = "messages"

    id = Column(String(36), primary_key=True, default=new_id)
    chat_id = Column(String(36), ForeignKey("chats.id", ondelete="CASCADE"), nullable=False)
    role = Column(String(20), nullable=False)
    content = Column(Text, default="")
    thinking_content = Column(Text, nullable=True)
    input_tokens = Column(Integer, default=0)
    output_tokens = Column(Integer, default=0)
    created_at = Column(DateTime, default=datetime.utcnow)

    chat = relationship("Chat", back_populates="messages")
    attachments = relationship("ChatAttachment", back_populates="message")


class ChatAttachment(Base):
    __tablename__ = "chat_attachments"

    id = Column(String(36), primary_key=True, default=new_id)
    chat_id = Column(String(36), ForeignKey("chats.id", ondelete="CASCADE"), nullable=False)
    message_id = Column(String(36), ForeignKey("messages.id", ondelete="SET NULL"), nullable=True)
    filename = Column(String(200), nullable=False)
    original_filename = Column(String(200), nullable=False)
    mime_type = Column(String(100), nullable=False)
    file_type = Column(String(20), nullable=False)
    file_size = Column(Integer, default=0)
    storage_path = Column(String(500), nullable=False)
    text_extract = Column(Text, nullable=True)
    created_at = Column(DateTime, default=datetime.utcnow)

    chat = relationship("Chat", back_populates="attachments")
    message = relationship("Message", back_populates="attachments")


class KnowledgeBase(Base):
    __tablename__ = "knowledge_bases"

    id = Column(String(36), primary_key=True, default=new_id)
    user_id = Column(String(36), ForeignKey("users.id", ondelete="CASCADE"), nullable=True)
    name = Column(String(200), nullable=False)
    description = Column(Text, default="")
    document_count = Column(Integer, default=0)
    chunk_count = Column(Integer, default=0)
    total_characters = Column(BigInteger, default=0)
    created_at = Column(DateTime, default=datetime.utcnow)


class KnowledgeDocument(Base):
    __tablename__ = "knowledge_documents"

    id = Column(String(36), primary_key=True, default=new_id)
    knowledge_base_id = Column(
        String(36), ForeignKey("knowledge_bases.id", ondelete="CASCADE"), nullable=False,
    )
    filename = Column(String(200), nullable=False)
    file_size = Column(Integer, default=0)
    chunk_count = Column(Integer, default=0)
    created_at = Column(DateTime, default=datetime.utcnow)


# ═══════════════════════════════════════════════════════════
#  GitLab Integration Models
# ═══════════════════════════════════════════════════════════

class GitLabSettings(Base):
    __tablename__ = "gitlab_settings"

    id = Column(String(36), primary_key=True, default=new_id)
    gitlab_url = Column(String(500), nullable=False, default="")
    gitlab_token = Column(String(500), nullable=False, default="")
    is_active = Column(Boolean, default=False)
    updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)


class LinkedRepo(Base):
    __tablename__ = "linked_repos"

    id = Column(String(36), primary_key=True, default=new_id)
    gitlab_project_id = Column(Integer, nullable=False)
    name = Column(String(300), nullable=False)
    path_with_namespace = Column(String(500), nullable=False)
    default_branch = Column(String(100), default="main")
    web_url = Column(String(500), default="")
    description = Column(Text, default="")
    architecture_map = Column(Text, nullable=True)
    map_status = Column(String(20), default="none")
    map_generated_at = Column(DateTime, nullable=True)
    created_at = Column(DateTime, default=datetime.utcnow)

    actions = relationship("PendingAction", back_populates="repo", cascade="all,delete-orphan")


class PendingAction(Base):
    __tablename__ = "pending_actions"

    id = Column(String(36), primary_key=True, default=new_id)
    linked_repo_id = Column(
        String(36), ForeignKey("linked_repos.id", ondelete="CASCADE"), nullable=False,
    )
    action_type = Column(String(50), nullable=False)
    title = Column(String(300), default="")
    payload = Column(Text, nullable=False)
    status = Column(String(20), default="pending")
    result_message = Column(Text, default="")
    created_at = Column(DateTime, default=datetime.utcnow)
    resolved_at = Column(DateTime, nullable=True)

    repo = relationship("LinkedRepo", back_populates="actions")