# -*- coding: utf-8 -*-
"""
STEP103-19 PipelineManager with Resume Skip

역할:
- V2 Stage들을 순서대로 실행한다.
- TimelineLogger로 Pipeline/Stage start/finish/skipped를 기록한다.
- context.resume_from 값이 있으면 해당 stage 이전 Stage는 skip 처리한다.

예:
  context.put("resume_from", "publish")

  session -> skipped
  collect -> skipped
  draft   -> skipped
  publish -> run
"""

from services.v2.pipeline_result import PipelineResult


class PipelineManager:
    def __init__(self):
        self.stages = []

    def register(self, stage):
        self.stages.append(stage)

    def run(self, context):
        print("[V2] Pipeline Start")

        timeline = self._make_timeline_logger(context)

        self._safe_timeline(
            timeline,
            "pipeline_start",
            context,
            message="V2 pipeline start",
            meta={
                "stage_count": len(self.stages),
                "version": context.version,
                "resume_from": context.get("resume_from"),
            },
        )

        try:
            if not self.stages:
                print("[V2] No Stage Registered")
                self._safe_timeline(
                    timeline,
                    "pipeline_finish",
                    context,
                    success=True,
                    message="V2 pipeline finish: no stage registered",
                )
                print("[V2] Pipeline Finish")
                return PipelineResult(
                    success=True,
                    stage="pipeline",
                    message="no stage registered",
                    elapsed=0,
                )

            last_result = None
            resume_from = context.get("resume_from")
            should_run = False if resume_from else True

            for stage in self.stages:
                stage_name = getattr(stage, "name", stage.__class__.__name__)

                if resume_from and not should_run:
                    if stage_name == resume_from:
                        should_run = True
                    else:
                        context.log(f"[{stage_name.upper()}] skipped by resume_from={resume_from}")
                        self._safe_timeline(
                            timeline,
                            "log_event",
                            context,
                            stage=stage_name,
                            event_type="skipped",
                            status="skipped",
                            success=True,
                            message=f"{stage_name} skipped by resume_from={resume_from}",
                            meta={
                                "resume_from": resume_from,
                            },
                        )
                        continue

                self._safe_timeline(
                    timeline,
                    "stage_start",
                    context,
                    stage_name,
                    message=f"{stage_name} start",
                )

                try:
                    result = stage.run(context)
                    last_result = result

                    self._safe_timeline(
                        timeline,
                        "stage_finish",
                        context,
                        stage_name,
                        success=bool(result.success),
                        message=result.message,
                        elapsed=getattr(result, "elapsed", None),
                        meta={
                            "result_stage": getattr(result, "stage", stage_name),
                            "resume_from": resume_from,
                        },
                    )

                    if not result.success:
                        print(result.message)

                        self._safe_timeline(
                            timeline,
                            "pipeline_finish",
                            context,
                            success=False,
                            message=f"V2 pipeline stopped at {stage_name}",
                            error_message=result.message,
                        )

                        print("[V2] Pipeline Finish")
                        return result

                except Exception as e:
                    self._safe_timeline(
                        timeline,
                        "stage_finish",
                        context,
                        stage_name,
                        success=False,
                        message=f"{stage_name} failed",
                        error_message=str(e),
                    )

                    self._safe_timeline(
                        timeline,
                        "pipeline_finish",
                        context,
                        success=False,
                        message=f"V2 pipeline failed at {stage_name}",
                        error_message=str(e),
                    )

                    print("[V2] Pipeline Finish")
                    raise

            self._safe_timeline(
                timeline,
                "pipeline_finish",
                context,
                success=True,
                message="V2 pipeline finish",
            )

            print("[V2] Pipeline Finish")

            return last_result or PipelineResult(
                success=True,
                stage="pipeline",
                message="pipeline finish",
                elapsed=0,
            )

        except Exception:
            raise

    def _make_timeline_logger(self, context):
        try:
            from db import get_conn
            from services.v2.timeline_logger import TimelineLogger

            conn = get_conn()

            class TimelineWrapper:
                def __init__(self, conn, logger):
                    self.conn = conn
                    self.logger = logger

                def close(self):
                    try:
                        self.conn.close()
                    except Exception:
                        pass

            logger = TimelineLogger(
                conn,
                scheduler_key=context.get("scheduler_key", "manual_v2"),
            )

            return TimelineWrapper(conn, logger)

        except Exception as e:
            print("[V2 TIMELINE INIT ERROR]", str(e))
            return None

    def _safe_timeline(self, timeline, method_name, *args, **kwargs):
        if not timeline:
            return None

        try:
            method = getattr(timeline.logger, method_name)
            return method(*args, **kwargs)

        except Exception as e:
            print("[V2 TIMELINE ERROR]", method_name, str(e))
            return None
