from __future__ import annotations

from datetime import datetime
from decimal import Decimal

from sqlalchemy import BigInteger, DateTime, Index, Integer, Numeric, String, Text, func
from sqlalchemy.orm import Mapped, mapped_column

from app.models.base import Base


class Prompt(Base):
    __tablename__ = "sys_prompt"
    __table_args__ = (Index("ix_sys_prompt_updated_at_id", "updated_at", "id"),)

    id: Mapped[int] = mapped_column(
        BigInteger().with_variant(Integer, "sqlite"), primary_key=True, autoincrement=True
    )
    prompt_content: Mapped[str] = mapped_column(Text, nullable=False)
    change_type: Mapped[str] = mapped_column(String(20), default="save", nullable=False)
    source_prompt_id: Mapped[int | None] = mapped_column(BigInteger, nullable=True)
    updated_by: Mapped[int | None] = mapped_column(BigInteger, nullable=True)
    updated_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now(), onupdate=func.now(), nullable=False)


class ContentGenerationConfig(Base):
    __tablename__ = "sys_content_generation_config"
    __table_args__ = (
        Index("ix_content_generation_type_updated", "config_type", "updated_at", "id"),
    )

    id: Mapped[int] = mapped_column(
        BigInteger().with_variant(Integer, "sqlite"), primary_key=True, autoincrement=True
    )
    config_type: Mapped[str] = mapped_column(String(30), nullable=False)
    template_content: Mapped[str] = mapped_column(Text, nullable=False)
    instruction_content: Mapped[str] = mapped_column(Text, nullable=False)
    change_type: Mapped[str] = mapped_column(String(20), default="save", nullable=False)
    source_config_id: Mapped[int | None] = mapped_column(BigInteger, nullable=True)
    updated_by: Mapped[int | None] = mapped_column(BigInteger, nullable=True)
    updated_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now(), nullable=False)


class ModelConfig(Base):
    __tablename__ = "sys_model"

    id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
    provider: Mapped[str] = mapped_column(String(50), nullable=False)
    display_name: Mapped[str | None] = mapped_column(String(100), nullable=True)
    api_type: Mapped[str] = mapped_column(String(50), default="openai_compatible", nullable=False)
    model_name: Mapped[str] = mapped_column(String(100), nullable=False)
    base_url: Mapped[str | None] = mapped_column(String(255), nullable=True)
    api_url: Mapped[str] = mapped_column(String(255), nullable=False)
    api_key: Mapped[str] = mapped_column(Text, nullable=False)
    auth_type: Mapped[str] = mapped_column(String(30), default="bearer", nullable=False)
    api_version: Mapped[str | None] = mapped_column(String(50), nullable=True)
    temperature: Mapped[Decimal | None] = mapped_column(Numeric(4, 2), nullable=True)
    top_p: Mapped[Decimal | None] = mapped_column(Numeric(4, 2), nullable=True)
    top_k: Mapped[int | None] = mapped_column(Integer, nullable=True)
    presence_penalty: Mapped[Decimal | None] = mapped_column(Numeric(4, 2), nullable=True)
    frequency_penalty: Mapped[Decimal | None] = mapped_column(Numeric(4, 2), nullable=True)
    max_token: Mapped[int | None] = mapped_column(Integer, nullable=True)
    context_window: Mapped[int | None] = mapped_column(Integer, nullable=True)
    stream_enabled: Mapped[int] = mapped_column(default=1, nullable=False)
    response_format: Mapped[str | None] = mapped_column(String(50), nullable=True)
    extra_params: Mapped[str | None] = mapped_column(Text, nullable=True)
    remark: Mapped[str | None] = mapped_column(String(255), nullable=True)
    timeout_second: Mapped[int] = mapped_column(Integer, default=30, nullable=False)
    enabled: Mapped[int] = mapped_column(default=0, nullable=False)
    is_default: Mapped[int] = mapped_column(default=0, nullable=False)
    input_price_per_1k: Mapped[Decimal | None] = mapped_column(Numeric(12, 6), nullable=True)
    output_price_per_1k: Mapped[Decimal | None] = mapped_column(Numeric(12, 6), nullable=True)
    currency: Mapped[str] = mapped_column(String(10), default="CNY", nullable=False)
    usage_scenarios: Mapped[str | None] = mapped_column(String(255), nullable=True)
    allow_summary: Mapped[int] = mapped_column(Integer, default=1, nullable=False)
    allow_report: Mapped[int] = mapped_column(Integer, default=1, nullable=False)
    allow_fixed_info: Mapped[int] = mapped_column(Integer, default=1, nullable=False)
    allow_simple_knowledge: Mapped[int] = mapped_column(Integer, default=1, nullable=False)
    allow_deep_chat: Mapped[int] = mapped_column(Integer, default=1, nullable=False)


class SystemConfig(Base):
    __tablename__ = "sys_system_config"

    id: Mapped[int] = mapped_column(BigInteger().with_variant(Integer, "sqlite"), primary_key=True, autoincrement=True)
    config_key: Mapped[str] = mapped_column(String(100), unique=True, nullable=False)
    config_value: Mapped[str] = mapped_column(Text, nullable=False)
    description: Mapped[str | None] = mapped_column(String(255), nullable=True)
    updated_by: Mapped[int | None] = mapped_column(BigInteger, nullable=True)
    updated_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now(), onupdate=func.now(), nullable=False)
