# -*- coding: utf-8 -*-
"""
STEP105-05 V2 Publish Button Discovery

역할:
- V2 전용 발행 버튼 탐색 모듈.
- 실제 발행 버튼은 클릭하지 않는다.
- page와 write_frame 양쪽에서 발행/등록/다음 버튼 후보를 찾는다.
- 이후 실제 발행 단계에서 사용할 안정적인 selector 후보를 수집한다.

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


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

    def discover(self, page, write_frame=None, logger=None, session=None):
        def _run():
            return self._discover_impl(page=page, write_frame=write_frame)

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

        return _run()

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

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

        selectors = [
            "button:has-text('발행')",
            "a:has-text('발행')",
            "button:has-text('등록')",
            "a:has-text('등록')",
            "button:has-text('다음')",
            "a:has-text('다음')",
            "button[aria-label*='발행']",
            "button[title*='발행']",
            "button[class*='publish']",
            "a[class*='publish']",
            ".se-publish-button",
            ".publish_btn",
            ".btn_publish",
            ".se-toolbar-button-publish",
            "button[data-name*='publish']",
            "button[data-log*='publish']",
        ]

        found = []
        summary = {
            "found": False,
            "best": None,
            "candidates": found,
        }

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

                    if self.verbose:
                        print(
                            "[V2 PUBLISH BUTTON CHECK]",
                            f"target={target_name}",
                            f"selector={selector}",
                            f"count={count}",
                        )

                    if count <= 0:
                        continue

                    for idx in range(min(count, 5)):
                        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=1000)
                        except Exception:
                            pass

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

                        try:
                            info["text"] = str(item.inner_text(timeout=1000) or "").strip()
                        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

                        found.append(info)

                        if self.verbose:
                            print("[V2 PUBLISH BUTTON FOUND]", info)

                except Exception as e:
                    if self.verbose:
                        print(
                            "[V2 PUBLISH BUTTON CHECK ERROR]",
                            f"target={target_name}",
                            f"selector={selector}",
                            str(e),
                        )

        best = self._pick_best(found)

        summary["found"] = best is not None
        summary["best"] = best

        print("[V2 PUBLISH BUTTON DISCOVERY RESULT]", summary)

        return summary

    def _pick_best(self, candidates):
        """
        우선순위:
        1. visible=True, enabled=True
        2. text에 발행 포함
        3. write_frame보다 page 우선/혹은 실제 위치는 결과로 확인
        """
        if not candidates:
            return None

        def score(item):
            s = 0
            text = str(item.get("text") or "")
            selector = str(item.get("selector") or "")
            cls = str(item.get("class") or "")
            aria = str(item.get("aria_label") or "")
            title = str(item.get("title") or "")

            if item.get("visible") is True:
                s += 100
            if item.get("enabled") is True:
                s += 100
            if "발행" in text:
                s += 80
            if "발행" in selector:
                s += 50
            if "발행" in aria or "발행" in title:
                s += 50
            if "publish" in selector.lower() or "publish" in cls.lower():
                s += 40
            if "등록" in text:
                s += 20
            if "다음" in text:
                s += 10

            return s

        return sorted(candidates, key=score, reverse=True)[0]


def discover_publish_button(page, write_frame=None, logger=None, session=None, verbose=True):
    worker = V2PublishButtonDiscovery(verbose=verbose)
    return worker.discover(
        page=page,
        write_frame=write_frame,
        logger=logger,
        session=session,
    )
