# -*- coding: utf-8 -*-
"""
STEP104-14 V2 Editor Recovery

목적:
- V1 publish_worker.py는 수정하지 않는다.
- 예전 백업파일에서 성공했던 "작성 중인 글이 있습니다" 팝업 취소 원리를 V2에 반영한다.
- 네이버 에디터 지연 로딩을 고려하여 1초 간격으로 최대 10회 반복 검사한다.
- page와 write_frame 둘 다 검사할 수 있다.

정책:
- "확인" 클릭 금지
- "취소" 클릭만 허용
"""

import time


class EditorRecovery:
    def __init__(self, verbose=True):
        self.verbose = verbose
        self.recovery_events = []

    def recover(self, page, write_frame=None, max_wait_seconds=10):
        """
        작성중 글 팝업 복구 진입점.

        반환:
        {
            "handled": bool,
            "events": [...]
        }
        """
        handled = self.cancel_existing_draft_popup(
            page=page,
            write_frame=write_frame,
            max_wait_seconds=max_wait_seconds,
        )

        return {
            "handled": handled,
            "events": self.recovery_events,
        }

    def cancel_existing_draft_popup(self, page, write_frame=None, max_wait_seconds=10):
        """
        "작성 중인 글이 있습니다." 팝업이 있으면 취소 버튼을 누른다.

        예전 성공 코드의 핵심:
        - 1초마다 최대 10회 검사
        - page와 write_frame 모두 검사
        - .se-popup-button-cancel 중심으로 클릭
        """
        self._log("draft_popup_wait_start", f"max_wait_seconds={max_wait_seconds}")

        popup_selectors = [
            ".se-popup-alert-confirm .se-popup-button-cancel",
            ".se-popup-button-cancel",
            "button.se-popup-button-cancel",
            "button:has-text('취소')",
        ]

        title_selectors = [
            ".se-popup-alert-confirm .se-popup-title",
            ".se-popup-title",
            "text=작성 중인 글이 있습니다.",
        ]

        targets = [("page", page)]

        if write_frame is not None:
            targets.append(("write_frame", write_frame))

        for sec in range(int(max_wait_seconds)):
            try:
                page.wait_for_timeout(1000)
            except Exception:
                time.sleep(1)

            self._log("draft_popup_wait_tick", f"{sec + 1}/{max_wait_seconds}")

            for target_name, target in targets:
                if self._has_existing_draft_title(target, title_selectors):
                    self._log("draft_popup_detected", f"target={target_name}")

                for selector in popup_selectors:
                    try:
                        locator = target.locator(selector)
                        count = locator.count()

                        self._log(
                            "draft_popup_selector_check",
                            f"target={target_name} selector={selector} count={count}",
                        )

                        if count <= 0:
                            continue

                        locator.first.click(
                            force=True,
                            timeout=3000,
                        )

                        try:
                            page.wait_for_timeout(2000)
                        except Exception:
                            pass

                        self._log(
                            "draft_popup_cancel_success",
                            f"target={target_name} selector={selector}",
                        )

                        return True

                    except Exception as e:
                        self._log(
                            "draft_popup_click_error",
                            f"target={target_name} selector={selector} error={e}",
                        )

        self._log("draft_popup_not_found", "작성 중인 글 팝업 없음 또는 감지 실패")
        return False

    def _has_existing_draft_title(self, target, title_selectors):
        for selector in title_selectors:
            try:
                locator = target.locator(selector)
                count = locator.count()

                if count <= 0:
                    continue

                if selector.startswith("text="):
                    return True

                text = ""
                try:
                    text = locator.first.inner_text(timeout=1000)
                except Exception:
                    text = ""

                if "작성 중인 글" in text:
                    return True

            except Exception:
                pass

        try:
            body_text = target.locator("body").inner_text(timeout=1000)
            if "작성 중인 글이 있습니다" in body_text and "이어서 작성하시겠습니까" in body_text:
                return True
        except Exception:
            pass

        return False

    def _log(self, event_name, message):
        event = {
            "event": event_name,
            "message": str(message),
            "ts": time.time(),
        }

        self.recovery_events.append(event)

        if self.verbose:
            print("[EDITOR RECOVERY]", event_name, message)

        return event


def recover_editor(page, write_frame=None, max_wait_seconds=10, timeout_ms=None, verbose=True):
    """
    V2 Recovery 함수형 진입점.

    timeout_ms는 기존 호출 호환용이다.
    timeout_ms가 있으면 초 단위로 환산하되 최소 1초로 처리한다.
    """
    if timeout_ms is not None:
        try:
            max_wait_seconds = max(1, int(int(timeout_ms) / 1000))
        except Exception:
            max_wait_seconds = 10

    recovery = EditorRecovery(verbose=verbose)
    return recovery.recover(
        page=page,
        write_frame=write_frame,
        max_wait_seconds=max_wait_seconds,
    )
