"""
Trust Repository - PostgreSQL 持久化層
======================================
ADR-088: TrustScoreManager 持久化升級

職責: trust_records 表的 upsert / load_all
設計: 實作 ITrustRepository Protocol

Pod 重啟後信任分數不歸零，AI 能真正累積到 L4 自動放行門檻。

2026-04-17 ogt + Claude Sonnet 4.6（亞太）: Phase 4 信任持久化
"""

from datetime import datetime

import structlog
from sqlalchemy import select
from sqlalchemy.dialects.postgresql import insert as pg_insert

from src.db.base import get_db_context
from src.db.models import TrustRecordDB
from src.repositories.interfaces import ITrustRepository

logger = structlog.get_logger(__name__)


class TrustRepository:
    """
    Trust Repository 實作（PostgreSQL）

    使用 PostgreSQL ON CONFLICT DO UPDATE (upsert)，
    保證並行安全且無競爭條件。
    """

    async def upsert(
        self,
        action_pattern: str,
        score: int,
        total_approvals: int,
        total_rejections: int,
        last_approval_by: str | None = None,
        last_approval_at: datetime | None = None,
        last_rejection_by: str | None = None,
        last_rejection_at: datetime | None = None,
    ) -> bool:
        """
        INSERT or UPDATE trust record。

        使用 PostgreSQL upsert 保證並行安全。
        action_pattern 是主鍵，衝突時更新除 created_at 外的所有欄位。
        """
        from src.utils.timezone import now_taipei

        try:
            async with get_db_context() as db:
                stmt = pg_insert(TrustRecordDB).values(
                    action_pattern=action_pattern,
                    score=score,
                    total_approvals=total_approvals,
                    total_rejections=total_rejections,
                    last_approval_by=last_approval_by,
                    last_approval_at=last_approval_at,
                    last_rejection_by=last_rejection_by,
                    last_rejection_at=last_rejection_at,
                    created_at=now_taipei(),
                    updated_at=now_taipei(),
                ).on_conflict_do_update(
                    index_elements=["action_pattern"],
                    set_={
                        "score": score,
                        "total_approvals": total_approvals,
                        "total_rejections": total_rejections,
                        "last_approval_by": last_approval_by,
                        "last_approval_at": last_approval_at,
                        "last_rejection_by": last_rejection_by,
                        "last_rejection_at": last_rejection_at,
                        "updated_at": now_taipei(),
                    },
                )
                await db.execute(stmt)

            logger.debug(
                "trust_record_upserted",
                action_pattern=action_pattern,
                score=score,
            )
            return True

        except Exception as e:
            logger.error(
                "trust_record_upsert_failed",
                action_pattern=action_pattern,
                error=str(e),
            )
            return False

    async def load_all(self) -> list[dict]:
        """
        載入所有 trust records，供啟動 warm-up。

        Returns:
            list[dict] — 每筆含 action_pattern, score, total_approvals,
            total_rejections, last_approval_by, last_approval_at,
            last_rejection_by, last_rejection_at
        """
        try:
            async with get_db_context() as db:
                result = await db.execute(select(TrustRecordDB))
                rows = result.scalars().all()

            records = [
                {
                    "action_pattern": r.action_pattern,
                    "score": r.score,
                    "total_approvals": r.total_approvals,
                    "total_rejections": r.total_rejections,
                    "last_approval_by": r.last_approval_by,
                    "last_approval_at": r.last_approval_at,
                    "last_rejection_by": r.last_rejection_by,
                    "last_rejection_at": r.last_rejection_at,
                }
                for r in rows
            ]

            logger.info("trust_records_loaded", count=len(records))
            return records

        except Exception as e:
            logger.error("trust_records_load_failed", error=str(e))
            return []


# =============================================================================
# Singleton
# =============================================================================

_repository: TrustRepository | None = None


def get_trust_repository() -> ITrustRepository:
    """取得 TrustRepository 單例"""
    global _repository
    if _repository is None:
        _repository = TrustRepository()
    return _repository
