# -*- coding: utf-8 -*-

import os
import traceback

from playwright.sync_api import sync_playwright

from config import STORAGE_DIR
from db import get_conn


SESSION_DIR = os.path.join(STORAGE_DIR, "naver_sessions")
os.makedirs(SESSION_DIR, exist_ok=True)


def get_waiting_queue():
    conn = get_conn()

    try:
        with conn.cursor() as cur:
            cur.execute("""
                SELECT
                    q.*,
                    d.draft_title,
                    d.draft_html,
                    d.clipboard_html,
                    d.plain_text,
                    d.article_no,
                    r.office_name
                FROM blog_publish_queue q
                INNER JOIN blog_article_drafts d
                    ON q.draft_id = d.id
                INNER JOIN blog_realtors r
                    ON q.realtor_id = r.id
                WHERE q.queue_status = 'waiting'
                ORDER BY q.id ASC
                LIMIT 1
            """)
            return cur.fetchone()

    finally:
        conn.close()


def update_queue_status(queue_id, status, error_message=None, result_url=None):

    conn = get_conn()

    try:
        with conn.cursor() as cur:

            sql = """
                UPDATE blog_publish_queue
                SET queue_status = %s,
                    updated_at = NOW()
            """

            params = [status]

            if status == "processing":
                sql += ", started_at = NOW()"

            if status in ["published", "failed", "hold"]:
                sql += ", finished_at = NOW()"

            if error_message is not None:
                sql += ", error_message = %s"
                params.append(error_message)

            if result_url is not None:
                sql += ", publish_result_url = %s"
                params.append(result_url)

            sql += " WHERE id = %s"
            params.append(queue_id)

            cur.execute(sql, params)

        conn.commit()

    finally:
        conn.close()


def update_draft_status(draft_id, status):

    conn = get_conn()

    try:
        with conn.cursor() as cur:

            cur.execute("""
                UPDATE blog_article_drafts
                SET status = %s,
                    updated_at = NOW()
                WHERE id = %s
            """, (status, draft_id))

        conn.commit()

    finally:
        conn.close()


def get_session_file(realtor_id):

    return os.path.join(
        SESSION_DIR,
        f"naver_session_{realtor_id}.json"
    )


def close_guides(page):

    selectors = [
        'button[aria-label="닫기"]',
        'button:has-text("닫기")',
        'button:has-text("확인")',
        'a:has-text("닫기")',
        ".btn_close",
        ".popup_close",
    ]

    for selector in selectors:

        try:
            locator = page.locator(selector)

            if locator.count() > 0:

                print(f"[GUIDE CLOSE] {selector} / count={locator.count()}")

                locator.first.click(
                    force=True,
                    timeout=2000
                )

                page.wait_for_timeout(800)

        except Exception:
            pass


def find_write_frame(page):

    for frame in page.frames:

        if "PostWriteForm.naver" in frame.url:
            return frame

    return None


def remove_right_help_panel(write_frame):

    try:

        print("[RIGHT PANEL REMOVE START]")

        remove_script = """
        (() => {

            const keywords = [
                "What’s New",
                "도움말",
                "간편해진 태그 입력",
                "간결해진 에디터 화면",
                "기본 인터페이스 안내"
            ];

            const all = Array.from(
                document.querySelectorAll("div, section, aside, article")
            );

            all.forEach(el => {

                try {

                    const text = el.innerText || "";
                    const rect = el.getBoundingClientRect();

                    if (
                        rect.width >= 250 &&
                        rect.height >= 200 &&
                        rect.left >= 900 &&
                        keywords.some(k => text.includes(k))
                    ) {
                        el.remove();
                    }

                } catch(e) {}

            });

        })();
        """

        write_frame.evaluate(remove_script)

        print("[RIGHT PANEL REMOVE END]")

    except Exception as e:

        print("[RIGHT PANEL REMOVE ERROR]", str(e))


def click_top_publish_button(page):

    try:

        print("[PUBLISH TOP COORD CLICK START]")

        page.mouse.click(1335, 22)

        page.wait_for_timeout(5000)

        print("[PUBLISH TOP COORD CLICK SUCCESS]")

        return True

    except Exception as e:

        print("[PUBLISH TOP COORD CLICK ERROR]", str(e))

        return False


def click_final_publish_button(page):

    try:

        print("[FINAL PUBLISH CLICK START]")

        page.mouse.click(1294, 556)

        page.wait_for_timeout(10000)

        print("[FINAL PUBLISH CLICK SUCCESS]")

        return True

    except Exception as e:

        print("[FINAL PUBLISH CLICK ERROR]", str(e))

        return False


def wait_publish_result_url(page):

    result_url = page.url

    for i in range(20):

        page.wait_for_timeout(1000)

        current_url = page.url

        print(f"[WAIT PUBLISH RESULT] {i + 1}/20 url={current_url}")

        result_url = current_url

        if (
            "blog.naver.com/" in current_url
            and "Redirect=Write" not in current_url
            and "PostWriteForm" not in current_url
        ):
            break

    return result_url


def validate_publish_result(result_url):

    if not result_url:
        return False

    result_url = result_url.strip()

    if (
        "blog.naver.com/" in result_url
        and "Redirect=Write" not in result_url
        and "PostWriteForm" not in result_url
    ):
        return True

    return False


def run_publish_worker():

    queue = get_waiting_queue()

    if not queue:
        print("[INFO] 대기중 Queue 없음")
        return

    queue_id = queue["id"]
    realtor_id = queue["realtor_id"]
    draft_id = queue["draft_id"]

    print("=" * 80)
    print(f"[QUEUE START] queue_id={queue_id}, realtor_id={realtor_id}, draft_id={draft_id}")
    print("=" * 80)

    session_file = get_session_file(realtor_id)

    print("[SESSION FILE]", session_file)

    if not os.path.exists(session_file):

        update_queue_status(
            queue_id,
            "failed",
            "세션 파일 없음"
        )

        update_draft_status(
            draft_id,
            "publish_failed"
        )

        print("[FAILED] 세션 파일 없음")

        return

    update_queue_status(queue_id, "processing")

    try:

        with sync_playwright() as p:

            browser = p.chromium.launch(
                headless=False,
                args=[
                    "--disable-blink-features=AutomationControlled",
                    "--no-sandbox",
                ]
            )

            context = browser.new_context(
                storage_state=session_file,
                locale="ko-KR",
                viewport={
                    "width": 1400,
                    "height": 1000
                }
            )

            page = context.new_page()

            print("[OPEN BLOG HOME] https://blog.naver.com")

            page.goto(
                "https://blog.naver.com",
                wait_until="domcontentloaded",
                timeout=60000
            )

            page.wait_for_timeout(5000)

            print("[CURRENT URL]", page.url)

            print("[LOGIN OK] 네이버 로그인 상태 확인 완료")

            close_guides(page)

            clicked = False

            write_selectors = [
                "a:has-text('글쓰기')",
                "button:has-text('글쓰기')",
                "a[href*='Write']",
            ]

            for selector in write_selectors:

                try:

                    locator = page.locator(selector)

                    if locator.count() <= 0:
                        continue

                    print("[CLICK WRITE SELECTOR]", selector)

                    try:

                        with page.context.expect_page(timeout=5000) as new_page_info:

                            locator.first.click(timeout=5000)

                        new_page = new_page_info.value

                        new_page.wait_for_load_state(
                            "domcontentloaded",
                            timeout=60000
                        )

                        page = new_page

                    except Exception:

                        locator.first.click(timeout=5000)

                        page.wait_for_timeout(5000)

                    clicked = True
                    break

                except Exception as e:

                    print("[WRITE CLICK FAIL]", selector, str(e))

            if not clicked:

                browser.close()

                update_queue_status(
                    queue_id,
                    "failed",
                    "글쓰기 버튼 클릭 실패"
                )

                update_draft_status(
                    draft_id,
                    "publish_failed"
                )

                print("[FAILED] 글쓰기 버튼 클릭 실패")

                return

            for i in range(30):

                page.wait_for_timeout(1000)

                print(f"[WAIT EDITOR] {i + 1}/30 url={page.url}")

            print("[WRITE FINAL URL]", page.url)

            write_frame = find_write_frame(page)

            if write_frame is None:

                browser.close()

                update_queue_status(
                    queue_id,
                    "failed",
                    "글쓰기 iframe 찾기 실패"
                )

                update_draft_status(
                    draft_id,
                    "publish_failed"
                )

                print("[FAILED] 글쓰기 iframe 찾기 실패")

                return

            print("[WRITE FRAME FOUND]", write_frame.url)

            # -------------------------------------------------
            # 제목 입력
            # -------------------------------------------------

            try:

                title_placeholder = write_frame.locator(
                    ".se-section-documentTitle .se-placeholder"
                ).first

                title_placeholder.click(force=True)

                page.wait_for_timeout(1000)

                box = title_placeholder.bounding_box()

                print("[TITLE PLACEHOLDER BOX]", box)

                if box:

                    page.mouse.click(
                        box["x"] + 30,
                        box["y"] + 20
                    )

                page.wait_for_timeout(1000)

                publish_title = str(
                    queue.get("draft_title")
                    or "부동산 매물 안내"
                ).strip()

                page.keyboard.type(
                    publish_title[:80],
                    delay=80
                )

                page.wait_for_timeout(3000)

                print("[TITLE INPUT SUCCESS]")

            except Exception as e:

                browser.close()

                update_queue_status(
                    queue_id,
                    "failed",
                    f"제목 입력 실패: {str(e)}"
                )

                update_draft_status(
                    draft_id,
                    "publish_failed"
                )

                print("[TITLE INPUT ERROR]", str(e))

                return

            # -------------------------------------------------
            # 본문 입력
            # -------------------------------------------------

            try:

                body_placeholders = write_frame.locator(
                    ".se-component-content .se-placeholder"
                )

                body_count = body_placeholders.count()

                print("[BODY PLACEHOLDER COUNT]", body_count)

                clicked_body = False

                for i in range(body_count):

                    placeholder = body_placeholders.nth(i)

                    try:
                        text = placeholder.inner_text(timeout=3000)
                    except Exception:
                        text = ""

                    if "제목" in text:
                        continue

                    box = placeholder.bounding_box()

                    print(f"[BODY PLACEHOLDER {i}] text={text} box={box}")

                    if not box:
                        continue

                    placeholder.click(force=True)

                    page.wait_for_timeout(800)

                    page.mouse.click(
                        box["x"] + 50,
                        box["y"] + 20
                    )

                    page.wait_for_timeout(800)

                    clicked_body = True

                    break

                if not clicked_body:

                    page.mouse.click(520, 430)

                    page.wait_for_timeout(1000)

                # -------------------------------------------------
                # HTML 우선
                # -------------------------------------------------

                clipboard_html = str(
                    queue.get("clipboard_html") or ""
                ).strip()

                plain_text = str(
                    queue.get("plain_text") or ""
                ).strip()

                if clipboard_html:

                    print("[BODY INPUT MODE] clipboard_html")

                    print("[HTML PASTE START]")

                    write_frame.evaluate("""
                    async (html) => {

                        const blob = new Blob(
                            [html],
                            { type: 'text/html' }
                        );

                        const data = [
                            new ClipboardItem({
                                'text/html': blob
                            })
                        ];

                        await navigator.clipboard.write(data);

                    }
                    """, clipboard_html)

                    page.wait_for_timeout(1500)

                    page.keyboard.press("Control+V")

                    page.wait_for_timeout(5000)

                    print("[HTML PASTE SUCCESS]")

                else:

                    print("[BODY INPUT MODE] plain_text")

                    if not plain_text:
                        plain_text = "매물 상세 내용은 상담을 통해 안내드리겠습니다."

                    page.keyboard.type(
                        plain_text[:2500],
                        delay=20
                    )

                page.wait_for_timeout(5000)

                print("[BODY INPUT SUCCESS]")

            except Exception as e:

                browser.close()

                update_queue_status(
                    queue_id,
                    "failed",
                    f"본문 입력 실패: {str(e)}"
                )

                update_draft_status(
                    draft_id,
                    "publish_failed"
                )

                print("[BODY INPUT ERROR]", str(e))

                return

            # -------------------------------------------------
            # 에디터 포커스 제거
            # -------------------------------------------------

            try:

                print("[EDITOR BLUR START]")

                page.keyboard.press("Escape")

                page.wait_for_timeout(1000)

                page.mouse.click(1200, 200)

                page.wait_for_timeout(1000)

                page.keyboard.press("Escape")

                page.wait_for_timeout(1000)

                print("[EDITOR BLUR END]")

            except Exception as e:

                print("[EDITOR BLUR ERROR]", str(e))

            remove_right_help_panel(write_frame)

            page.wait_for_timeout(1000)

            # -------------------------------------------------
            # 상단 발행
            # -------------------------------------------------

            top_publish_clicked = click_top_publish_button(page)

            if not top_publish_clicked:

                browser.close()

                update_queue_status(
                    queue_id,
                    "failed",
                    "상단 발행 버튼 클릭 실패"
                )

                update_draft_status(
                    draft_id,
                    "publish_failed"
                )

                return

            page.wait_for_timeout(3000)

            # -------------------------------------------------
            # 최종 발행
            # -------------------------------------------------

            final_publish_clicked = click_final_publish_button(page)

            if not final_publish_clicked:

                browser.close()

                update_queue_status(
                    queue_id,
                    "failed",
                    "최종 발행 버튼 클릭 실패"
                )

                update_draft_status(
                    draft_id,
                    "publish_failed"
                )

                return

            # -------------------------------------------------
            # 발행 결과
            # -------------------------------------------------

            result_url = wait_publish_result_url(page)

            print("[RESULT URL CHECK]", result_url)

            is_valid_publish = validate_publish_result(result_url)

            if not is_valid_publish:

                browser.close()

                update_queue_status(
                    queue_id,
                    "failed",
                    "발행 URL 검증 실패",
                    result_url
                )

                update_draft_status(
                    draft_id,
                    "publish_failed"
                )

                return

            browser.close()

            update_queue_status(
                queue_id,
                "published",
                error_message="발행 완료",
                result_url=result_url
            )

            update_draft_status(
                draft_id,
                "published"
            )

            print("[DONE] 네이버 블로그 발행 완료")
            print("[RESULT URL]", result_url)

    except Exception as e:

        traceback.print_exc()

        update_queue_status(
            queue_id,
            "failed",
            str(e)[:1000]
        )

        update_draft_status(
            draft_id,
            "publish_failed"
        )

        print("[FAILED]", str(e))


if __name__ == "__main__":
    run_publish_worker()