#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""跨平台市場活動情報 ORM models。"""

from datetime import datetime, timedelta, timezone

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

from database.models import Base


TAIPEI_TZ = timezone(timedelta(hours=8))


def taipei_now():
    """取得台北時間 naive datetime，符合專案 DB 時間規範。"""
    return datetime.now(TAIPEI_TZ).replace(tzinfo=None)


class MarketPlatform(Base):
    """市場平台設定，例如 MOMO / PChome / Coupang / Shopee。"""

    __tablename__ = "market_platforms"

    id = Column(Integer, primary_key=True, autoincrement=True)
    code = Column(String(50), unique=True, nullable=False, index=True)
    name = Column(String(120), nullable=False)
    base_url = Column(String(500))
    enabled = Column(Boolean, default=False, nullable=False)
    crawl_policy_json = Column(Text)
    created_at = Column(DateTime, default=taipei_now, nullable=False)
    updated_at = Column(DateTime, default=taipei_now, onupdate=taipei_now, nullable=False)

    campaigns = relationship("MarketCampaign", back_populates="platform")


class MarketCampaign(Base):
    """跨平台活動檔期。"""

    __tablename__ = "market_campaigns"

    id = Column(Integer, primary_key=True, autoincrement=True)
    platform_code = Column(String(50), ForeignKey("market_platforms.code"), nullable=False, index=True)
    campaign_key = Column(String(200), nullable=False)
    campaign_name = Column(String(500), nullable=False)
    campaign_type = Column(String(80), index=True)
    campaign_url = Column(Text)
    start_at = Column(DateTime)
    end_at = Column(DateTime)
    status = Column(String(30), default="unknown", nullable=False, index=True)
    discovered_at = Column(DateTime, default=taipei_now, nullable=False)
    last_seen_at = Column(DateTime, default=taipei_now, nullable=False)
    metadata_json = Column(Text)

    platform = relationship("MarketPlatform", back_populates="campaigns")
    snapshots = relationship("MarketCampaignSnapshot", back_populates="campaign")
    products = relationship("MarketCampaignProduct", back_populates="campaign")

    __table_args__ = (
        UniqueConstraint("platform_code", "campaign_key", name="uq_market_campaign_platform_key"),
        Index("idx_market_campaign_status_time", "status", "start_at", "end_at"),
    )


class MarketCampaignSnapshot(Base):
    """活動頁每次爬取快照。"""

    __tablename__ = "market_campaign_snapshots"

    id = Column(Integer, primary_key=True, autoincrement=True)
    campaign_id = Column(Integer, ForeignKey("market_campaigns.id"), nullable=False, index=True)
    batch_id = Column(String(80), nullable=False, index=True)
    crawled_at = Column(DateTime, default=taipei_now, nullable=False, index=True)
    title = Column(String(500))
    hero_text = Column(Text)
    coupon_text = Column(Text)
    raw_discount_text = Column(Text)
    page_hash = Column(String(128), index=True)
    raw_snapshot_path = Column(Text)
    status = Column(String(30), default="success", nullable=False, index=True)
    error_message = Column(Text)
    metadata_json = Column(Text)

    campaign = relationship("MarketCampaign", back_populates="snapshots")

    __table_args__ = (
        Index("idx_market_campaign_snapshot_campaign_time", "campaign_id", "crawled_at"),
    )


class MarketCampaignProduct(Base):
    """活動頁中的平台商品快照主檔。"""

    __tablename__ = "market_campaign_products"

    id = Column(Integer, primary_key=True, autoincrement=True)
    campaign_id = Column(Integer, ForeignKey("market_campaigns.id"), nullable=False, index=True)
    platform_code = Column(String(50), nullable=False, index=True)
    platform_product_id = Column(String(200), nullable=False, index=True)
    product_url = Column(Text)
    name = Column(String(500), nullable=False)
    brand = Column(String(200), index=True)
    image_url = Column(Text)
    category_text = Column(String(300), index=True)
    price = Column(Float)
    original_price = Column(Float)
    discount_text = Column(String(200))
    discount_rate = Column(Float)
    coupon_text = Column(Text)
    stock_text = Column(String(200))
    sold_count = Column(Integer)
    rating = Column(Float)
    review_count = Column(Integer)
    rank_position = Column(Integer)
    is_active = Column(Boolean, default=True, nullable=False, index=True)
    first_seen_at = Column(DateTime, default=taipei_now, nullable=False)
    last_seen_at = Column(DateTime, default=taipei_now, nullable=False, index=True)
    metadata_json = Column(Text)

    campaign = relationship("MarketCampaign", back_populates="products")
    price_history = relationship("MarketProductPriceHistory", back_populates="market_product")
    matches = relationship("MarketProductMatch", back_populates="market_product")

    __table_args__ = (
        UniqueConstraint(
            "campaign_id",
            "platform_code",
            "platform_product_id",
            name="uq_market_campaign_product",
        ),
        Index("idx_market_product_platform_seen", "platform_code", "last_seen_at"),
        Index("idx_market_product_discount", "discount_rate", "price"),
    )


class MarketProductPriceHistory(Base):
    """市場商品價格歷史快照。"""

    __tablename__ = "market_product_price_history"

    id = Column(Integer, primary_key=True, autoincrement=True)
    market_product_id = Column(Integer, ForeignKey("market_campaign_products.id"), nullable=False, index=True)
    campaign_id = Column(Integer, ForeignKey("market_campaigns.id"), nullable=False, index=True)
    platform_code = Column(String(50), nullable=False, index=True)
    platform_product_id = Column(String(200), nullable=False, index=True)
    price = Column(Float)
    original_price = Column(Float)
    discount_rate = Column(Float)
    stock_text = Column(String(200))
    sold_count = Column(Integer)
    rank_position = Column(Integer)
    crawled_at = Column(DateTime, default=taipei_now, nullable=False, index=True)
    batch_id = Column(String(80), nullable=False, index=True)
    metadata_json = Column(Text)

    market_product = relationship("MarketCampaignProduct", back_populates="price_history")

    __table_args__ = (
        Index("idx_market_price_platform_time", "platform_code", "platform_product_id", "crawled_at"),
        Index("idx_market_price_campaign_time", "campaign_id", "crawled_at"),
    )


class MarketProductMatch(Base):
    """市場商品與我方 MOMO 商品的比對審核結果。"""

    __tablename__ = "market_product_matches"

    id = Column(Integer, primary_key=True, autoincrement=True)
    market_product_id = Column(Integer, ForeignKey("market_campaign_products.id"), nullable=False, index=True)
    momo_product_id = Column(Integer, ForeignKey("products.id"), index=True)
    momo_i_code = Column(String(50), index=True)
    match_score = Column(Float, default=0.0, nullable=False)
    match_status = Column(String(30), default="needs_review", nullable=False, index=True)
    match_reason_json = Column(Text)
    created_at = Column(DateTime, default=taipei_now, nullable=False)
    reviewed_at = Column(DateTime)
    reviewed_by = Column(String(120))

    market_product = relationship("MarketCampaignProduct", back_populates="matches")

    __table_args__ = (
        UniqueConstraint("market_product_id", "momo_i_code", name="uq_market_product_momo_match"),
        Index("idx_market_match_status_score", "match_status", "match_score"),
    )


class MarketCrawlerRun(Base):
    """市場情報爬蟲執行紀錄。"""

    __tablename__ = "market_crawler_runs"

    id = Column(Integer, primary_key=True, autoincrement=True)
    platform_code = Column(String(50), index=True)
    crawler_name = Column(String(120), nullable=False, index=True)
    campaign_id = Column(Integer, ForeignKey("market_campaigns.id"), index=True)
    batch_id = Column(String(80), nullable=False, index=True)
    started_at = Column(DateTime, default=taipei_now, nullable=False, index=True)
    finished_at = Column(DateTime)
    status = Column(String(30), default="started", nullable=False, index=True)
    dry_run = Column(Boolean, default=True, nullable=False)
    pages_found = Column(Integer, default=0, nullable=False)
    products_found = Column(Integer, default=0, nullable=False)
    products_changed = Column(Integer, default=0, nullable=False)
    error_count = Column(Integer, default=0, nullable=False)
    error_message = Column(Text)
    metadata_json = Column(Text)

    __table_args__ = (
        Index("idx_market_crawler_run_platform_time", "platform_code", "started_at"),
        Index("idx_market_crawler_run_status_time", "status", "started_at"),
    )


class MarketAlertReviewQueue(Base):
    """市場機會與威脅告警的人工審核佇列。"""

    __tablename__ = "market_alert_review_queue"

    id = Column(Integer, primary_key=True, autoincrement=True)
    alert_candidate_id = Column(String(120), nullable=False, unique=True, index=True)
    review_state = Column(String(40), default="draft", nullable=False, index=True)
    priority_lane = Column(String(40), default="watch", nullable=False, index=True)
    threshold_level = Column(String(40), nullable=False, index=True)
    total_score = Column(Float, default=0.0, nullable=False)
    evidence_bundle_id = Column(String(120), nullable=False, index=True)
    dedupe_key = Column(String(240), nullable=False)
    source_batch_id = Column(String(80), nullable=False, index=True)
    campaign_id = Column(Integer, ForeignKey("market_campaigns.id"), index=True)
    market_product_id = Column(Integer, ForeignKey("market_campaign_products.id"), index=True)
    momo_i_code = Column(String(50), index=True)
    reviewer_identity = Column(String(120))
    review_action = Column(String(60))
    review_reason = Column(Text)
    reviewed_at = Column(DateTime)
    previous_state = Column(String(40))
    next_state = Column(String(40))
    created_at = Column(DateTime, default=taipei_now, nullable=False)
    updated_at = Column(DateTime, default=taipei_now, onupdate=taipei_now, nullable=False)
    metadata_json = Column(Text)

    __table_args__ = (
        Index(
            "idx_market_alert_review_queue_state_priority",
            "review_state",
            "priority_lane",
            "created_at",
        ),
        Index("ux_market_alert_review_queue_dedupe", "dedupe_key", unique=True),
        Index(
            "idx_market_alert_review_queue_bundle",
            "evidence_bundle_id",
            "source_batch_id",
        ),
    )
