# -*- coding: utf-8 -*-
"""
STEP105-12 V2 Publish Action - Safe Close

역할:
- 발행 버튼 클릭 후 실제 최종 발행 전 화면/팝업 구조를 분석한다.
- 최종 발행은 하지 않는다.
- 발행 설정창 닫기는 정확히 publish_fold_btn만 사용한다.

중요:
- button:has-text('취소') 사용 금지
  네이버 에디터 툴바의 '취소선' 버튼을 잘못 누를 수 있다.

V1 publish_worker.py는 수정하지 않는다.
"""


class V2PublishClickProbe:
    def __init__(self, verbose=True):
        self.verbose = verbose

    def probe(self, page, write_frame, discovery_result=None, logger=None, session=None):
        def _run():
            return self._probe_impl(
                page=page,
                write_frame=write_frame,
                discovery_result=discovery_result,
            )

        if session and logger:
            with session.step("publish.click.probe", logger=logger):
                return _run()

        return _run()

    def _probe_impl(self, page, write_frame, discovery_result=None):
        best = (discovery_result or {}).get("best") or {}

        selector = best.get("selector") or "button:has-text('발행')"
        index = int(best.get("index") or 0)
        target_name = best.get("target") or "write_frame"

        target = write_frame if target_name == "write_frame" else page

        print("[V2 PUBLISH CLICK PROBE TARGET]", {
            "target": target_name,
            "selector": selector,
            "index": index,
        })

        locator = target.locator(selector)

        count = locator.count()
        if count <= index:
            raise RuntimeError(f"발행 버튼 locator 부족: selector={selector}, count={count}, index={index}")

        button = locator.nth(index)

        if not button.is_visible(timeout=3000):
            raise RuntimeError("발행 버튼이 visible 상태가 아닙니다.")

        if not button.is_enabled(timeout=3000):
            raise RuntimeError("발행 버튼이 enabled 상태가 아닙니다.")

        button.click(force=True, timeout=5000)
        page.wait_for_timeout(2500)

        probe_result = self.inspect_after_click(page=page, write_frame=write_frame)

        # 안전 닫기: 발행 설정 닫기 전용 버튼만 사용
        close_result = self.try_close_publish_layer(page=page, write_frame=write_frame)

        probe_result["clicked"] = True
        probe_result["click_target"] = {
            "target": target_name,
            "selector": selector,
            "index": index,
        }
        probe_result["close_result"] = close_result

        print("[V2 PUBLISH CLICK PROBE RESULT]", probe_result)

        return probe_result

    def inspect_after_click(self, page, write_frame):
        targets = [("page", page), ("write_frame", write_frame)]

        selectors = [
            "button",
            "a",
            "[role='button']",
            ".se-popup",
            "[class*='publish']",
            "[class*='layer']",
            "[class*='popup']",
        ]

        result = {
            "url": page.url,
            "candidates": [],
            "texts": {},
        }

        for target_name, target in targets:
            for key, text in [
                ("publish", "발행"),
                ("confirm", "확인"),
                ("cancel", "취소"),
                ("close", "닫기"),
                ("public", "공개"),
                ("private", "비공개"),
                ("neighbor", "이웃"),
                ("tag", "태그"),
                ("category", "카테고리"),
                ("reserve", "예약"),
            ]:
                try:
                    count = target.locator(f"text={text}").count()
                    result["texts"][f"{target_name}:{key}:{text}"] = count
                except Exception:
                    pass

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

                    if count <= 0:
                        continue

                    for idx in range(min(count, 20)):
                        item = locator.nth(idx)

                        info = {
                            "target": target_name,
                            "selector": selector,
                            "index": idx,
                            "count": count,
                            "visible": None,
                            "enabled": None,
                            "text": "",
                            "class": "",
                            "id": "",
                            "aria_label": "",
                            "title": "",
                        }

                        try:
                            info["visible"] = item.is_visible(timeout=500)
                        except Exception:
                            pass

                        try:
                            info["enabled"] = item.is_enabled(timeout=500)
                        except Exception:
                            pass

                        try:
                            info["text"] = str(item.inner_text(timeout=500) or "").strip()[:200]
                        except Exception:
                            pass

                        try:
                            info["class"] = str(item.get_attribute("class") or "").strip()
                        except Exception:
                            pass

                        try:
                            info["id"] = str(item.get_attribute("id") or "").strip()
                        except Exception:
                            pass

                        try:
                            info["aria_label"] = str(item.get_attribute("aria-label") or "").strip()
                        except Exception:
                            pass

                        try:
                            info["title"] = str(item.get_attribute("title") or "").strip()
                        except Exception:
                            pass

                        text_blob = " ".join([
                            info.get("text") or "",
                            info.get("class") or "",
                            info.get("aria_label") or "",
                            info.get("title") or "",
                        ])

                        if info.get("visible") or any(k in text_blob for k in ["발행", "확인", "취소", "공개", "비공개", "예약", "publish", "popup", "layer"]):
                            result["candidates"].append(info)

                except Exception as e:
                    if self.verbose:
                        print("[V2 PUBLISH PROBE INSPECT ERROR]", target_name, selector, str(e))

        return result

    def try_close_publish_layer(self, page, write_frame):
        """
        탐색 후 발행 설정창만 안전하게 닫는다.

        절대 사용하지 말 것:
        - button:has-text('취소')
        - text=취소

        이유:
        - 에디터 툴바의 '취소선' 버튼이 같이 잡힐 수 있다.
        """
        close_selectors = [
            "button[class*='publish_fold_btn']",
            "[class*='publish_fold_btn']",
            "button:has-text('발행 설정 닫기')",
        ]

        for selector in close_selectors:
            try:
                locator = write_frame.locator(selector)
                count = locator.count()

                if self.verbose:
                    print("[V2 PUBLISH SAFE CLOSE CHECK]", selector, count)

                if count <= 0:
                    continue

                for idx in range(min(count, 5)):
                    item = locator.nth(idx)

                    try:
                        if not item.is_visible(timeout=500):
                            continue
                    except Exception:
                        pass

                    text = ""
                    cls = ""

                    try:
                        text = str(item.inner_text(timeout=500) or "").strip()
                    except Exception:
                        pass

                    try:
                        cls = str(item.get_attribute("class") or "").strip()
                    except Exception:
                        pass

                    item.click(force=True, timeout=3000)
                    page.wait_for_timeout(1000)

                    return {
                        "closed": True,
                        "target": "write_frame",
                        "selector": selector,
                        "index": idx,
                        "text": text,
                        "class": cls,
                    }

            except Exception as e:
                if self.verbose:
                    print("[V2 PUBLISH SAFE CLOSE FAIL]", selector, str(e))

        return {
            "closed": False,
        }


def probe_publish_click(page, write_frame, discovery_result=None, logger=None, session=None, verbose=True):
    worker = V2PublishClickProbe(verbose=verbose)
    return worker.probe(
        page=page,
        write_frame=write_frame,
        discovery_result=discovery_result,
        logger=logger,
        session=session,
    )
