# -*- coding: utf-8 -*-
"""
STEP103-10 V2 ResumeInspector

역할:
- blog_v2_pipeline_timeline과 blog_v2_scheduler_state를 읽어
  마지막 실행이 정상 종료됐는지, 어느 단계에서 멈췄는지 판단한다.
- Scheduler가 다음 실행 시 어디서 이어갈지 판단하는 기초 모듈이다.

주의:
- 이 파일은 아직 자동 재개 실행을 수행하지 않는다.
- 먼저 "진단"을 정확히 하는 것이 목표다.
"""

from dataclasses import dataclass
from typing import Any


@dataclass
class ResumeInspectionResult:
    should_resume: bool
    reason: str
    scheduler_key: str
    pipeline_id: str | None = None
    realtor_id: int | None = None
    stage: str | None = None
    article_no: str | None = None
    draft_id: int | None = None
    publish_queue_id: int | None = None
    last_event: dict[str, Any] | None = None
    scheduler_state: dict[str, Any] | None = None


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

    def inspect(self) -> ResumeInspectionResult:
        state = self.fetch_scheduler_state()
        last_event = self.fetch_last_timeline_event()

        if not state and not last_event:
            return ResumeInspectionResult(
                should_resume=False,
                reason="no_scheduler_state_no_timeline",
                scheduler_key=self.scheduler_key,
            )

        if not last_event:
            return ResumeInspectionResult(
                should_resume=False,
                reason="no_timeline_event",
                scheduler_key=self.scheduler_key,
                scheduler_state=state,
            )

        pipeline_id = last_event.get("pipeline_id")
        realtor_id = self._to_int(last_event.get("realtor_id"))
        stage = last_event.get("stage")
        event_type = last_event.get("event_type")
        success = last_event.get("success")
        status = last_event.get("status")

        # 정상 pipeline finish success면 재개 불필요
        if stage == "pipeline" and event_type == "finish" and str(status) == "success":
            return ResumeInspectionResult(
                should_resume=False,
                reason="last_pipeline_finished_success",
                scheduler_key=self.scheduler_key,
                pipeline_id=pipeline_id,
                realtor_id=realtor_id,
                stage=stage,
                article_no=last_event.get("article_no"),
                draft_id=self._to_int(last_event.get("draft_id")),
                publish_queue_id=self._to_int(last_event.get("publish_queue_id")),
                last_event=last_event,
                scheduler_state=state,
            )

        # pipeline finish failed 또는 stage finish failed면 재개 필요
        if str(success) == "0" or str(status) == "failed":
            return ResumeInspectionResult(
                should_resume=True,
                reason="last_event_failed",
                scheduler_key=self.scheduler_key,
                pipeline_id=pipeline_id,
                realtor_id=realtor_id,
                stage=stage,
                article_no=last_event.get("article_no"),
                draft_id=self._to_int(last_event.get("draft_id")),
                publish_queue_id=self._to_int(last_event.get("publish_queue_id")),
                last_event=last_event,
                scheduler_state=state,
            )

        # start 이벤트로 끝났으면 해당 stage 진행 중 중단으로 판단
        if event_type == "start":
            return ResumeInspectionResult(
                should_resume=True,
                reason="last_event_was_start_without_finish",
                scheduler_key=self.scheduler_key,
                pipeline_id=pipeline_id,
                realtor_id=realtor_id,
                stage=stage,
                article_no=last_event.get("article_no"),
                draft_id=self._to_int(last_event.get("draft_id")),
                publish_queue_id=self._to_int(last_event.get("publish_queue_id")),
                last_event=last_event,
                scheduler_state=state,
            )

        # Scheduler 상태가 running/paused인데 pipeline finish가 아니면 재개 후보
        state_status = str((state or {}).get("status") or "")
        if state_status in {"running", "paused"} and not (
            stage == "pipeline" and event_type == "finish"
        ):
            return ResumeInspectionResult(
                should_resume=True,
                reason=f"scheduler_state_{state_status}_not_pipeline_finished",
                scheduler_key=self.scheduler_key,
                pipeline_id=pipeline_id,
                realtor_id=realtor_id,
                stage=stage,
                article_no=last_event.get("article_no"),
                draft_id=self._to_int(last_event.get("draft_id")),
                publish_queue_id=self._to_int(last_event.get("publish_queue_id")),
                last_event=last_event,
                scheduler_state=state,
            )

        return ResumeInspectionResult(
            should_resume=False,
            reason="resume_not_required",
            scheduler_key=self.scheduler_key,
            pipeline_id=pipeline_id,
            realtor_id=realtor_id,
            stage=stage,
            article_no=last_event.get("article_no"),
            draft_id=self._to_int(last_event.get("draft_id")),
            publish_queue_id=self._to_int(last_event.get("publish_queue_id")),
            last_event=last_event,
            scheduler_state=state,
        )

    def fetch_scheduler_state(self):
        try:
            with self.conn.cursor() as cur:
                cur.execute(
                    """
                    SELECT *
                    FROM blog_v2_scheduler_state
                    WHERE scheduler_key=%s
                    LIMIT 1
                    """,
                    (self.scheduler_key,),
                )
                row = cur.fetchone()
            return dict(row) if row else None
        except Exception:
            return None

    def fetch_last_timeline_event(self):
        with self.conn.cursor() as cur:
            cur.execute(
                """
                SELECT *
                FROM blog_v2_pipeline_timeline
                WHERE scheduler_key=%s
                ORDER BY id DESC
                LIMIT 1
                """,
                (self.scheduler_key,),
            )
            row = cur.fetchone()

        return dict(row) if row else None

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