"""市場情報 adapter 基礎類別。

Phase 3 只提供 read-only discovery plan，不發 HTTP request。
"""

from dataclasses import asdict, dataclass
from typing import Iterable, Sequence


@dataclass(frozen=True)
class CampaignSource:
    """公開活動入口的描述，不代表已實際爬取。"""

    source_key: str
    name: str
    url: str
    campaign_type: str
    notes: str = ""

    def to_dict(self):
        return asdict(self)


@dataclass(frozen=True)
class AdapterSafetyPolicy:
    """平台爬取安全策略。"""

    request_interval_sec: float
    timeout_sec: int
    max_pages_per_run: int
    allow_login: bool = False
    allow_database_write: bool = False
    allow_scheduler_attach: bool = False

    def to_dict(self):
        return asdict(self)


class MarketIntelAdapter:
    """市場情報平台 adapter base class。"""

    platform_code = ""
    platform_name = ""
    base_url = ""
    campaign_url_keywords = ()
    campaign_text_keywords = ()
    safety_policy = AdapterSafetyPolicy(
        request_interval_sec=2.0,
        timeout_sec=20,
        max_pages_per_run=5,
    )

    def campaign_sources(self) -> Sequence[CampaignSource]:
        return ()

    def summary(self):
        return {
            "platform_code": self.platform_code,
            "platform_name": self.platform_name,
            "base_url": self.base_url,
            "source_count": len(self.campaign_sources()),
            "safety_policy": self.safety_policy.to_dict(),
            "phase": "read_only_adapter_skeleton",
        }

    def build_discovery_plan(self):
        """建立 discovery plan，不發 request、不寫 DB。"""
        return {
            **self.summary(),
            "network_request_allowed": False,
            "database_write_allowed": False,
            "scheduler_attach_allowed": False,
            "sources": [source.to_dict() for source in self.campaign_sources()],
        }

    def discover_campaigns(self, *, dry_run=True) -> Iterable[CampaignSource]:
        """Phase 3 僅允許 dry-run 回傳入口描述。"""
        if not dry_run:
            raise RuntimeError("市場情報 adapter 尚未允許正式 discovery")
        return self.campaign_sources()

    def score_campaign_link(self, href, text):
        """平台別活動連結加權，只用於診斷排序。"""
        url_text = (href or "").lower()
        link_text = (text or "").lower()
        score = 0
        for keyword in self.campaign_url_keywords:
            if str(keyword).lower() in url_text:
                score += 4
        for keyword in self.campaign_text_keywords:
            if str(keyword).lower() in link_text:
                score += 3
        return score
