# AI history and template models
from sqlalchemy import BigInteger, Column, DateTime, Integer, Numeric, String, Text, Boolean, Float
from sqlalchemy.dialects import postgresql
from sqlalchemy.ext.compiler import compiles
from sqlalchemy.types import JSON, UserDefinedType
from database.models import Base
from datetime import datetime


class Vector(UserDefinedType):
    """pgvector column with a SQLite-safe fallback for local metadata tests."""

    cache_ok = True

    def __init__(self, dimensions):
        self.dimensions = dimensions

    def get_col_spec(self, **kw):
        return f"VECTOR({self.dimensions})"


@compiles(Vector, "sqlite")
def _compile_vector_sqlite(type_, compiler, **kw):
    return "TEXT"


def _jsonb_type():
    return JSON().with_variant(postgresql.JSONB, "postgresql")


def _bigint_array_type():
    return Text().with_variant(postgresql.ARRAY(BigInteger), "postgresql")

class AIGenerationHistory(Base):
    """
    AI generation history tracking
    """
    __tablename__ = 'ai_generation_history'

    id = Column(Integer, primary_key=True, autoincrement=True)
    generation_type = Column(String(50), nullable=False)  # product_desc, marketing_copy, etc.
    product_name = Column(String(200))
    input_keywords = Column(Text)  # JSON string
    input_trend_topic = Column(String(500))
    output_content = Column(Text)
    generation_duration = Column(Float)  # seconds
    is_favorite = Column(Boolean, default=False)
    is_used = Column(Boolean, default=False)
    created_by = Column(String(100))
    created_at = Column(DateTime, default=datetime.now)

    def to_dict(self):
        return {
            'id': self.id,
            'generation_type': self.generation_type,
            'product_name': self.product_name,
            'input_keywords': self.input_keywords,
            'input_trend_topic': self.input_trend_topic,
            'output_content': self.output_content,
            'generation_duration': self.generation_duration,
            'is_favorite': self.is_favorite,
            'is_used': self.is_used,
            'created_by': self.created_by,
            'created_at': self.created_at.isoformat() if self.created_at else None
        }

class AIPromptTemplate(Base):
    """
    AI prompt templates
    """
    __tablename__ = 'ai_prompt_templates'

    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(200), nullable=False)
    description = Column(Text)
    template_type = Column(String(50), nullable=False)  # product_desc, marketing_copy, etc.
    prompt_content = Column(Text, nullable=False)
    variables = Column(Text)  # JSON string of variable definitions
    is_active = Column(Boolean, default=True)
    is_system = Column(Boolean, default=False)
    created_by = Column(String(100))
    created_at = Column(DateTime, default=datetime.now)
    updated_at = Column(DateTime, default=datetime.now, onupdate=datetime.now)

    def to_dict(self):
        return {
            'id': self.id,
            'name': self.name,
            'description': self.description,
            'template_type': self.template_type,
            'prompt_content': self.prompt_content,
            'variables': self.variables,
            'is_active': self.is_active,
            'is_system': self.is_system,
            'created_by': self.created_by,
            'created_at': self.created_at.isoformat() if self.created_at else None,
            'updated_at': self.updated_at.isoformat() if self.updated_at else None
        }

class AIUsageTracking(Base):
    """
    AI usage tracking for analytics and billing
    """
    __tablename__ = 'ai_usage_tracking'

    id = Column(Integer, primary_key=True, autoincrement=True)
    user_id = Column(String(100))
    session_id = Column(String(100))
    service_type = Column(String(50), nullable=False)  # openai, ollama, etc.
    model_name = Column(String(100))
    prompt_tokens = Column(Integer, default=0)
    completion_tokens = Column(Integer, default=0)
    total_tokens = Column(Integer, default=0)
    cost_usd = Column(Float, default=0.0)
    request_type = Column(String(50))  # generation, analysis, etc.
    status = Column(String(20), default='success')  # success, failed
    error_message = Column(Text)
    duration_ms = Column(Float)
    created_at = Column(DateTime, default=datetime.now)

    def to_dict(self):
        return {
            'id': self.id,
            'user_id': self.user_id,
            'session_id': self.session_id,
            'service_type': self.service_type,
            'model_name': self.model_name,
            'prompt_tokens': self.prompt_tokens,
            'completion_tokens': self.completion_tokens,
            'total_tokens': self.total_tokens,
            'cost_usd': self.cost_usd,
            'request_type': self.request_type,
            'status': self.status,
            'error_message': self.error_message,
            'duration_ms': self.duration_ms,
            'created_at': self.created_at.isoformat() if self.created_at else None
        }

class AIInsight(Base):
    """
    AI 洞察知識庫（ai_insights 表）— KM 沉澱核心，支援 RAG 向量化。
    對應 openclaw_learning_service / scheduler 各任務寫入。
    """
    __tablename__ = 'ai_insights'

    id = Column(Integer, primary_key=True, autoincrement=True)
    insight_type = Column(String(50), nullable=False)   # backup_status / human_review / auto_heal_playbook 等
    period = Column(String(50))                          # 分析週期，e.g. "2026-04-20"
    product_sku = Column(String(50))
    content = Column(Text, nullable=False)
    metadata_json = Column(Text)                         # JSON extra payload
    avg_quality = Column(Float, default=0.5)
    status = Column(String(20), default='approved')      # approved / pending / rejected / archived
    decay_exempt = Column(Boolean, default=False)
    ai_model = Column(String(50))
    feedback_up = Column(Integer, default=0)
    feedback_down = Column(Integer, default=0)
    confidence = Column(Float, default=0.5)
    created_by = Column(String(50), default='system')
    created_at = Column(DateTime, default=datetime.now)
    updated_at = Column(DateTime, default=datetime.now, onupdate=datetime.now)
    # embedding 欄位為 pgvector 型別，透過 raw SQL 寫入，此處不聲明以避免型別衝突

    def to_dict(self):
        return {
            'id': self.id,
            'insight_type': self.insight_type,
            'period': self.period,
            'product_sku': self.product_sku,
            'content': self.content,
            'avg_quality': self.avg_quality,
            'status': self.status,
            'ai_model': self.ai_model,
            'feedback_up': self.feedback_up,
            'feedback_down': self.feedback_down,
            'confidence': self.confidence,
            'created_by': self.created_by,
            'created_at': self.created_at.isoformat() if self.created_at else None,
        }


class AICall(Base):
    """ai_calls unified LLM call telemetry table (migration 024)."""

    __tablename__ = 'ai_calls'
    __table_args__ = {'extend_existing': True}

    id = Column(BigInteger, primary_key=True, autoincrement=True)
    called_at = Column(DateTime(timezone=True), default=datetime.now, nullable=False)
    caller = Column(String(64), nullable=False)
    provider = Column(String(32), nullable=False)
    model = Column(String(128), nullable=False)
    input_tokens = Column(Integer, default=0, nullable=False)
    output_tokens = Column(Integer, default=0, nullable=False)
    duration_ms = Column(Integer)
    status = Column(String(16), nullable=False)
    fallback_to = Column(String(64))
    cost_usd = Column(Numeric(10, 6), default=0, nullable=False)
    cache_hit = Column(Boolean, default=False, nullable=False)
    rag_hit = Column(Boolean, default=False, nullable=False)
    request_id = Column(String(64))
    error = Column(Text)
    meta = Column(_jsonb_type())


class MCPCall(Base):
    """mcp_calls MCP server call telemetry table (migration 025)."""

    __tablename__ = 'mcp_calls'
    __table_args__ = {'extend_existing': True}

    id = Column(BigInteger, primary_key=True, autoincrement=True)
    called_at = Column(DateTime(timezone=True), default=datetime.now, nullable=False)
    caller = Column(String(64), nullable=False)
    server = Column(String(64), nullable=False)
    tool = Column(String(128), nullable=False)
    input_args = Column(_jsonb_type())
    output_size = Column(Integer)
    duration_ms = Column(Integer)
    status = Column(String(16), nullable=False)
    error = Column(Text)
    cost_usd = Column(Numeric(10, 6), default=0, nullable=False)
    cache_hit = Column(Boolean, default=False, nullable=False)
    request_id = Column(String(64))
    insight_id = Column(BigInteger)


class AICallBudget(Base):
    """ai_call_budgets budget guardrail table (migration 025)."""

    __tablename__ = 'ai_call_budgets'
    __table_args__ = {'extend_existing': True}

    id = Column(Integer, primary_key=True, autoincrement=True)
    period = Column(String(16), nullable=False)
    provider = Column(String(32))
    budget_usd = Column(Numeric(10, 2), nullable=False)
    alert_pct = Column(Integer, default=80, nullable=False)
    updated_at = Column(DateTime(timezone=True), default=datetime.now)


class RAGQueryLog(Base):
    """rag_query_log RAG recall telemetry table (migration 027)."""

    __tablename__ = 'rag_query_log'
    __table_args__ = {'extend_existing': True}

    id = Column(BigInteger, primary_key=True, autoincrement=True)
    queried_at = Column(DateTime(timezone=True), default=datetime.now, nullable=False)
    caller = Column(String(64), nullable=False)
    query_text = Column(Text, nullable=False)
    query_embedding = Column(Vector(1024))
    embedding_signature = Column(String(64))
    top_k = Column(Integer, default=5, nullable=False)
    threshold = Column(Numeric(4, 3), default=0.85, nullable=False)
    hit_count = Column(Integer, default=0, nullable=False)
    used_results = Column(_bigint_array_type())
    saved_call = Column(Boolean, default=False, nullable=False)
    feedback_score = Column(Integer)
    request_id = Column(String(64))


class LearningEpisode(Base):
    """learning_episodes PromotionGate staging table (migration 028)."""

    __tablename__ = 'learning_episodes'
    __table_args__ = {'extend_existing': True}

    id = Column(BigInteger, primary_key=True, autoincrement=True)
    created_at = Column(DateTime(timezone=True), default=datetime.now, nullable=False)
    episode_type = Column(String(32), nullable=False)
    source_table = Column(String(32))
    source_id = Column(BigInteger)
    distilled_text = Column(Text, nullable=False)
    embedding = Column(Vector(1024))
    embedding_signature = Column(String(64))
    quality_score = Column(Numeric(4, 3), default=0.0, nullable=False)
    weight = Column(Numeric(4, 3), default=0.5, nullable=False)
    promotion_status = Column(String(32), default='pending', nullable=False)
    insight_id = Column(BigInteger)
    rejected_reason = Column(Text)
    human_approver = Column(String(64))
    reviewed_at = Column(DateTime(timezone=True))


class HostHealthProbe(Base):
    """host_health_probes Ollama failover health history table (migration 029)."""

    __tablename__ = 'host_health_probes'
    __table_args__ = {'extend_existing': True}

    id = Column(BigInteger, primary_key=True, autoincrement=True)
    probed_at = Column(DateTime(timezone=True), default=datetime.now, nullable=False)
    host_label = Column(String(64), nullable=False)
    host_url = Column(String(256), nullable=False)
    healthy = Column(Boolean, nullable=False)
    unhealthy_mark = Column(Boolean, default=False, nullable=False)
    models_count = Column(Integer, default=0)
    response_ms = Column(Integer)
    error_msg = Column(Text)


class PPTAuditResult(Base):
    """ppt_audit_results PPT vision audit history table (migration 030)."""

    __tablename__ = 'ppt_audit_results'
    __table_args__ = {'extend_existing': True}

    id = Column(BigInteger, primary_key=True, autoincrement=True)
    audited_at = Column(DateTime(timezone=True), default=datetime.now, nullable=False)
    pptx_filename = Column(String(256), nullable=False)
    pptx_size_kb = Column(Integer)
    pptx_mtime = Column(DateTime(timezone=True))
    vision_enabled = Column(Boolean, nullable=False)
    audit_status = Column(String(32), nullable=False)
    issues_count = Column(Integer, default=0)
    issues_found = Column(_jsonb_type())
    confidence = Column(Numeric(4, 3))
    duration_ms = Column(Integer)
    error_msg = Column(Text)
    reviewer_notes = Column(Text)


__all__ = [
    "AIGenerationHistory", "AIPromptTemplate", "AIUsageTracking", "AIInsight",
    "AICall", "MCPCall", "AICallBudget", "RAGQueryLog", "LearningEpisode",
    "HostHealthProbe", "PPTAuditResult",
]
