# -*- coding: utf-8 -*-
"""
STEP103-03 V2 DecisionLogger

역할:
- blog_v2_decision_logs 테이블에 V2 의사결정 로그를 저장한다.
- TargetSelector, Scheduler, PublishAdapter 등에서 공통 사용한다.
- "왜 이 매물을 선택했는가"를 운영자가 추적할 수 있게 한다.
"""

import json


class DecisionLogger:
    table_name = "blog_v2_decision_logs"

    def __init__(self, conn, scheduler_key="server_default"):
        self.conn = conn
        self.scheduler_key = scheduler_key

    def log_target_selection(
        self,
        pipeline_id,
        realtor_id,
        selection_result,
        stage="target_selector",
        message=None,
        meta=None,
    ):
        """
        TargetSelector.select() 결과를 그대로 decision log에 저장한다.
        """
        row = selection_result.row or {}
        compare = selection_result.compare or {}

        article_no = (
            selection_result.article_no
            or row.get("article_no")
            or row.get("queue_article_no")
            or ""
        )

        return self.log(
            pipeline_id=pipeline_id,
            realtor_id=realtor_id,
            article_no=article_no,
            draft_id=selection_result.draft_id,
            publish_queue_id=selection_result.publish_queue_id,
            stage=stage,
            action=selection_result.action,
            reason=selection_result.reason,
            basis_date=selection_result.basis_date,
            selected_article_no=selection_result.article_no,
            selected_draft_id=selection_result.draft_id,
            selected_publish_queue_id=selection_result.publish_queue_id,
            compare=compare,
            message=message,
            meta=meta,
        )

    def log(
        self,
        pipeline_id,
        realtor_id,
        stage,
        action,
        reason=None,
        article_no=None,
        draft_id=None,
        publish_queue_id=None,
        basis_date=None,
        selected_article_no=None,
        selected_draft_id=None,
        selected_publish_queue_id=None,
        compare=None,
        message=None,
        meta=None,
    ):
        compare_text = json.dumps(compare or {}, ensure_ascii=False, default=str)
        meta_text = json.dumps(meta or {}, ensure_ascii=False, default=str)

        sql = f"""
            INSERT INTO {self.table_name}
            (
                pipeline_id,
                scheduler_key,
                realtor_id,
                article_no,
                draft_id,
                publish_queue_id,
                stage,
                action,
                reason,
                basis_date,
                selected_article_no,
                selected_draft_id,
                selected_publish_queue_id,
                compare_text,
                message,
                meta_text,
                created_at
            )
            VALUES
            (
                %s,
                %s,
                %s,
                %s,
                %s,
                %s,
                %s,
                %s,
                %s,
                %s,
                %s,
                %s,
                %s,
                %s,
                %s,
                %s,
                NOW()
            )
        """

        params = (
            pipeline_id,
            self.scheduler_key,
            int(realtor_id),
            str(article_no) if article_no else None,
            self._to_int_or_none(draft_id),
            self._to_int_or_none(publish_queue_id),
            str(stage),
            str(action),
            str(reason) if reason else None,
            basis_date,
            str(selected_article_no) if selected_article_no else None,
            self._to_int_or_none(selected_draft_id),
            self._to_int_or_none(selected_publish_queue_id),
            compare_text,
            message,
            meta_text,
        )

        with self.conn.cursor() as cur:
            cur.execute(sql, params)
            log_id = cur.lastrowid

        self.conn.commit()
        return log_id

    def _to_int_or_none(self, value):
        try:
            if value is None or value == "":
                return None
            return int(value)
        except Exception:
            return None
