# -*- coding: utf-8 -*-
"""
STEP103-04 PublishAdapter with DecisionLogger

역할:
- V2 PublishStage에서 기존 workers/publish_worker.py의 run_publish_worker()를 호출한다.
- TargetSelector가 고른 대상을 blog_v2_decision_logs에 기록한다.
- 기본값은 dry_run=True 이다.
- context.get("execute_publish") == True 일 때만 실제 발행한다.
"""

from services.v2.base_adapter import BaseAdapter
from services.v2.target_selector import TargetSelector
from services.v2.decision_logger import DecisionLogger


class PublishAdapter(BaseAdapter):
    name = "publish_adapter"

    def run(self, context) -> dict:
        return self.publish(context)

    def publish(self, context) -> dict:
        try:
            from db import get_conn

            conn = get_conn()
            target = None
            decision_log_id = None

            try:
                selector = TargetSelector(conn)
                target = selector.select(context.realtor_id)

                logger = DecisionLogger(
                    conn,
                    scheduler_key=context.get("scheduler_key", "manual_v2"),
                )
                decision_log_id = logger.log_target_selection(
                    pipeline_id=context.pipeline_id,
                    realtor_id=context.realtor_id,
                    selection_result=target,
                    stage="publish_target_selector",
                    message="PublishAdapter selected target before publish_worker",
                    meta={
                        "execute_publish": bool(context.get("execute_publish", False)),
                        "version": context.version,
                    },
                )

                data = {
                    "realtor_id": context.realtor_id,
                    "decision_log_id": decision_log_id,
                    "target": {
                        "found": target.found,
                        "action": target.action,
                        "reason": target.reason,
                        "article_no": target.article_no,
                        "draft_id": target.draft_id,
                        "publish_queue_id": target.publish_queue_id,
                        "basis_date": str(target.basis_date) if target.basis_date else None,
                        "compare": target.compare,
                    },
                }

                if not target.found:
                    return self.ok(
                        message="publish skipped: no target",
                        data=data,
                        published=[],
                        skipped=True,
                    )

                if target.action not in {"publish_existing_queue", "publish_existing_draft"}:
                    return self.ok(
                        message=f"publish skipped: target action is {target.action}",
                        data=data,
                        published=[],
                        skipped=True,
                    )

                execute_publish = bool(context.get("execute_publish", False))

                if not execute_publish:
                    return self.ok(
                        message=(
                            "publish dry-run: target selected but actual publish not executed. "
                            "Set context execute_publish=True to run publish_worker."
                        ),
                        data=data,
                        published=[],
                        skipped=True,
                        dry_run=True,
                    )

            finally:
                conn.close()

            from workers.publish_worker import run_publish_worker

            worker_result = run_publish_worker(
                limit=1,
                realtor_id=context.realtor_id,
                sleep_seconds=0,
                until_hour=None,
                until_time=None,
                stale_minutes=90,
                retry_session_hold=True,
                only_night_window=False,
                window_start_hour=7,
                window_end_hour=23,
                max_retry=2,
                auto_reset_retry_failed=True,
                smart_sleep=False,
                min_sleep=0,
                max_sleep=0,
                sleep_jitter=0,
                estimated_publish_seconds=90,
                per_realtor_daily_limit=1,
            )

            publish_result = self.fetch_latest_publish_result(context.realtor_id)

            actual_success = bool(
                publish_result
                and str(publish_result.get("queue_status") or "") == "published"
                and publish_result.get("publish_result_url")
            )

            published = []
            if actual_success:
                published.append({
                    "queue_id": publish_result.get("id"),
                    "article_no": publish_result.get("article_no"),
                    "draft_id": publish_result.get("draft_id"),
                    "blog_url": publish_result.get("publish_result_url"),
                    "blog_id": publish_result.get("blog_id"),
                    "blog_post_no": publish_result.get("blog_post_no"),
                    "status": "published",
                })

            return self.ok(
                message="publish worker completed",
                data={
                    "realtor_id": context.realtor_id,
                    "decision_log_id": decision_log_id,
                    "worker_result": worker_result,
                    "latest_publish_result": publish_result,
                    "actual_success": actual_success,
                },
                published=published,
                skipped=False,
                dry_run=False,
            )

        except Exception as e:
            return self.fail(
                message=f"publish adapter failed: {e}",
                data={
                    "realtor_id": context.realtor_id,
                    "error": str(e),
                },
                published=[],
                skipped=False,
            )

    def fetch_latest_publish_result(self, realtor_id: int):
        try:
            from db import get_conn

            conn = get_conn()
            try:
                with conn.cursor() as cur:
                    cur.execute(
                        """
                        SELECT
                            id,
                            realtor_id,
                            draft_id,
                            article_no,
                            queue_status,
                            worker_status,
                            publish_result_url,
                            blog_id,
                            blog_post_no,
                            finished_at,
                            updated_at
                        FROM blog_publish_queue
                        WHERE realtor_id=%s
                        ORDER BY updated_at DESC, id DESC
                        LIMIT 1
                        """,
                        (int(realtor_id),),
                    )
                    row = cur.fetchone()
                return dict(row) if row else None
            finally:
                conn.close()
        except Exception as e:
            return {
                "error": str(e),
                "realtor_id": realtor_id,
            }
