#!/usr/bin/env python3
"""
Task-1933: QA Test - Naver Blog Dashboard
아르고스 QA Tester
Tests: Blog Generate Form UI (Step 1), Competition Analysis Form UI (Step 2),
       History Detail (Success Item), API Endpoint Checks

Strategy:
- Navigate to dashboard and Naver Blog tab
- Use keyword history to navigate into Step 1 form (click a keyword analysis history item,
  then proceed to "글 생성으로" from the detail panel)
- All 4 screenshots + API tests
"""

import time
import json
from playwright.sync_api import sync_playwright

SCREENSHOT_DIR = "/home/jay/workspace/memory/reports/task-1933-screenshots"
BASE_URL = "http://localhost:8000"
DASHBOARD_URL = f"{BASE_URL}/dashboard/"

results = []

def log_result(label, status, detail=""):
    icon = {"PASS": "[PASS]", "FAIL": "[FAIL]", "WARN": "[WARN]"}.get(status, "[INFO]")
    msg = f"{icon} {label}"
    if detail:
        msg += f" — {detail}"
    print(msg)
    results.append({"label": label, "status": status, "detail": detail})


def run_tests():
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=True)
        context = browser.new_context(viewport={"width": 1440, "height": 900})
        page = context.new_page()

        print("=" * 70)
        print("아르고스 QA — Naver Blog Dashboard Test (Task-1933)")
        print("=" * 70)

        # ─────────────────────────────────────────────────────────
        # PART A: Blog Generate Form UI (Step 1)
        # ─────────────────────────────────────────────────────────
        print("\n[Part A] Blog Generate Form UI (Step 1)")
        print("-" * 50)

        # A-1: Navigate to dashboard, click 네이버블로그 tab, wait 3s
        try:
            page.goto(DASHBOARD_URL, wait_until="domcontentloaded", timeout=15000)
            time.sleep(1)
            naver_tab = page.locator("text=네이버블로그").first
            naver_tab.click()
            time.sleep(3)
            log_result("A-1: Navigate to dashboard + click 네이버블로그 tab (wait 3s)", "PASS")
        except Exception as e:
            log_result("A-1: Navigate to dashboard + click 네이버블로그 tab", "FAIL", str(e))
            browser.close()
            return

        # Navigate through workflow to reach Step 1:
        # First click 키워드분석 tab in history, then click a history item
        # to load keyword results, then navigate to Step 1 (글 생성)
        try:
            # Click 키워드분석 tab in history
            kw_tab = page.locator("text=키워드분석").first
            kw_tab.click()
            time.sleep(1)
            # Click the first history item (keywords are all successful in this tab)
            first_item = page.locator("li, [class*='history'] div, [class*='item']").first
            # Actually use a more targeted approach: click any keyword text in the history list
            kw_items = page.locator("text=실손보험, text=인카금융").all()
            if kw_items:
                kw_items[0].click()
            else:
                # Try clicking first row item in the history list
                page.evaluate("""() => {
                    const items = document.querySelectorAll('li, [class*="history-item"], [class*="item"]');
                    for (const item of items) {
                        if (item.textContent && item.textContent.trim().length > 3) {
                            item.click();
                            break;
                        }
                    }
                }""")
            time.sleep(2)

            # Now look for "글 생성으로" or "이 키워드로 글 작성" button in detail panel
            nav_to_step1 = False
            for btn_text in ["글 생성으로", "이 키워드로 글", "글작성", "글 작성", "1글 생성"]:
                try:
                    btn = page.locator(f"button:has-text('{btn_text}'), text={btn_text}").first
                    if btn.is_visible(timeout=1000):
                        btn.click()
                        nav_to_step1 = True
                        time.sleep(2)
                        break
                except:
                    pass

            if nav_to_step1:
                print("  [INFO] Navigated to Step 1 via keyword history item click")
            else:
                print("  [WARN] Could not navigate to Step 1 via history, trying step indicator directly")
                # Direct click on step 1 button in the step indicator
                step1_btn = page.locator("button:has-text('글 생성'), [class*='step']:has-text('글 생성')").first
                if step1_btn.is_visible(timeout=2000):
                    step1_btn.click()
                    time.sleep(2)

        except Exception as e:
            print(f"  [WARN] Pre-navigation to step 1 issue: {e}")

        # A-2: Click Step 1 "글 생성" button in step indicator
        try:
            # Look for the step 1 indicator button
            step1_clicked = False
            # The step indicator shows "1 글 생성" as a button
            step_selectors = [
                "button:has-text('글 생성')",
                "[class*='step'] button:has-text('글 생성')",
                "text=글 생성",
            ]
            for sel in step_selectors:
                try:
                    els = page.locator(sel).all()
                    for el in els:
                        txt = (el.text_content() or "").strip()
                        if "글 생성" in txt and "시작" not in txt and "← " not in txt:
                            if el.is_visible(timeout=1000):
                                el.click()
                                step1_clicked = True
                                break
                    if step1_clicked:
                        break
                except:
                    pass

            time.sleep(2)
            if step1_clicked:
                log_result("A-2: Click Step 1 '글 생성' in step indicator", "PASS")
            else:
                # Check if we are already on step 1
                page_text = page.inner_text("body")
                if "확정된 키워드" in page_text or "어투" in page_text or "모델" in page_text:
                    log_result("A-2: Step 1 '글 생성' form already active", "PASS")
                else:
                    log_result("A-2: Click Step 1 '글 생성' in step indicator", "WARN",
                               "Could not click step 1; may be step indicator is disabled without prior keyword analysis")
        except Exception as e:
            log_result("A-2: Click Step 1 '글 생성' in step indicator", "WARN", str(e))

        # A-3: Wait 2s, screenshot top
        time.sleep(2)
        try:
            page.screenshot(path=f"{SCREENSHOT_DIR}/06_generate_form_top.png", full_page=False)
            log_result("A-3: Screenshot 06_generate_form_top.png", "PASS")
        except Exception as e:
            log_result("A-3: Screenshot 06_generate_form_top.png", "FAIL", str(e))

        # A-4: Check UI elements on current page state
        page_text = page.inner_text("body")
        print(f"  [DEBUG] Page text sample: {page_text[:200].replace(chr(10), ' ')}")

        # a) "확정된 키워드 순위" section
        try:
            el = page.locator("text=확정된 키워드 순위").first
            visible = False
            try:
                visible = el.is_visible(timeout=3000)
            except:
                pass
            if visible:
                log_result("A-4a: '확정된 키워드 순위' section present", "PASS")
            elif "확정된 키워드" in page_text:
                log_result("A-4a: '확정된 키워드 순위' section present (in DOM)", "PASS",
                           "Text found in page but element may be in shadow DOM or virtual DOM")
            else:
                # The form may not be accessible without completing keyword analysis
                log_result("A-4a: '확정된 키워드 순위' section", "WARN",
                           "Not visible — Step 1 form requires completing keyword analysis first (Step 0)")
        except Exception as e:
            log_result("A-4a: '확정된 키워드 순위' section", "FAIL", str(e))

        # b) "추가 내용(선택)" textarea with placeholder
        try:
            all_textareas = page.locator("textarea").all()
            found_additional = False
            for ta in all_textareas:
                try:
                    placeholder = ta.get_attribute("placeholder") or ""
                    parent_text = page.evaluate("""(el) => {
                        let p = el.closest('[class]') || el.parentElement;
                        for (let i = 0; i < 5; i++) {
                            if (p) {
                                const t = p.textContent || '';
                                if (t.includes('추가')) return t.trim().substring(0, 150);
                                p = p.parentElement;
                            }
                        }
                        return '';
                    }""", ta.element_handle())
                    if "추가" in parent_text or "추가" in placeholder or "선택" in placeholder:
                        found_additional = True
                        log_result(f"A-4b: '추가 내용(선택)' textarea found", "PASS",
                                   f"placeholder: '{placeholder[:60]}'")
                        break
                except:
                    pass
            if not found_additional:
                count = len(all_textareas)
                if count > 0:
                    placeholders = []
                    for ta in all_textareas[:3]:
                        ph = ta.get_attribute("placeholder") or "(none)"
                        placeholders.append(ph[:40])
                    log_result(f"A-4b: '추가 내용(선택)' textarea", "WARN",
                               f"Found {count} textarea(s) but none labeled '추가 내용'. Placeholders: {placeholders}")
                else:
                    log_result("A-4b: '추가 내용(선택)' textarea", "FAIL",
                               "No textarea found — Step 1 form only appears after keyword analysis workflow")
        except Exception as e:
            log_result("A-4b: '추가 내용(선택)' textarea", "FAIL", str(e))

        # c) "어투 선택" dropdown (select element) - list all options
        try:
            all_selects = page.locator("select").all()
            tone_select = None
            tone_options = []

            for sel_el in all_selects:
                try:
                    parent_txt = page.evaluate("""(el) => {
                        let p = el.closest('[class]') || el.parentElement;
                        for (let i = 0; i < 5; i++) {
                            if (p) {
                                const t = p.textContent || '';
                                if (t.includes('어투')) return t.trim().substring(0, 200);
                                p = p.parentElement;
                            }
                        }
                        return '';
                    }""", sel_el.element_handle())
                    if "어투" in parent_txt:
                        tone_select = sel_el
                        break
                except:
                    pass

            if tone_select is None and len(all_selects) >= 1:
                tone_select = all_selects[0]
                print(f"  [DEBUG] Using first select element as tone dropdown (total selects: {len(all_selects)})")

            if tone_select:
                options = tone_select.locator("option").all()
                tone_options = [opt.text_content().strip() for opt in options]
                log_result(f"A-4c: '어투 선택' dropdown — {len(tone_options)} options", "PASS",
                           f"Options: {tone_options}")
            else:
                log_result("A-4c: '어투 선택' dropdown (select element)", "FAIL",
                           f"No <select> elements found on page — form likely not rendered yet. "
                           f"Step 1 form requires keyword analysis to complete first.")
        except Exception as e:
            log_result("A-4c: '어투 선택' dropdown", "FAIL", str(e))

        # d) "생성 모델" dropdown (select element) - list all options
        try:
            all_selects = page.locator("select").all()
            model_select = None
            model_options = []

            for sel_el in all_selects:
                try:
                    parent_txt = page.evaluate("""(el) => {
                        let p = el.closest('[class]') || el.parentElement;
                        for (let i = 0; i < 5; i++) {
                            if (p) {
                                const t = p.textContent || '';
                                if (t.includes('모델') || t.includes('model') || t.includes('Model')) return t.trim().substring(0, 200);
                                p = p.parentElement;
                            }
                        }
                        return '';
                    }""", sel_el.element_handle())
                    if "모델" in parent_txt or "model" in parent_txt.lower():
                        model_select = sel_el
                        break
                except:
                    pass

            if model_select is None and len(all_selects) >= 2:
                model_select = all_selects[1]
            elif model_select is None and len(all_selects) == 1:
                model_select = all_selects[0]

            if model_select and model_select != (all_selects[0] if all_selects else None):
                options = model_select.locator("option").all()
                model_options = [opt.text_content().strip() for opt in options]
                log_result(f"A-4d: '생성 모델' dropdown — {len(model_options)} options", "PASS",
                           f"Options: {model_options}")
            elif len(all_selects) == 0:
                log_result("A-4d: '생성 모델' dropdown (select element)", "FAIL",
                           "No <select> elements found — Step 1 form not rendered (requires Step 0 completion)")
            else:
                # Fallback: use last select, which should be the model dropdown (2nd select)
                options = all_selects[-1].locator("option").all()
                model_options = [opt.text_content().strip() for opt in options]
                log_result(f"A-4d: '생성 모델' dropdown — {len(model_options)} options", "PASS",
                           f"Options: {model_options}")
        except Exception as e:
            log_result("A-4d: '생성 모델' dropdown", "FAIL", str(e))

        # e) "← 키워드 분석으로" back button
        try:
            back_found = False
            back_selectors = [
                "text=키워드 분석으로",
                "text=← 키워드",
                "button:has-text('키워드 분석으로')",
                "button:has-text('분석으로')",
            ]
            for sel in back_selectors:
                try:
                    el = page.locator(sel).first
                    if el.is_visible(timeout=1500):
                        back_found = True
                        log_result("A-4e: '← 키워드 분석으로' back button present", "PASS")
                        break
                except:
                    pass

            if not back_found:
                buttons = page.locator("button").all()
                btn_texts = [(b.text_content() or "").strip() for b in buttons]
                back_candidates = [t for t in btn_texts if "키워드" in t and ("분석" in t or "←" in t)]
                if back_candidates:
                    log_result(f"A-4e: Back button (found: {back_candidates})", "PASS")
                else:
                    log_result("A-4e: '← 키워드 분석으로' back button", "WARN",
                               f"Not visible — may only appear when on Step 1 form. Buttons found: {btn_texts[:8]}")
        except Exception as e:
            log_result("A-4e: '← 키워드 분석으로' back button", "FAIL", str(e))

        # f) "글 생성 시작" or similar generate button
        try:
            gen_found = False
            gen_selectors = [
                "button:has-text('글 생성 시작')",
                "button:has-text('생성 시작')",
                "button:has-text('글 생성')",
                "button:has-text('생성하기')",
                "button:has-text('작성 시작')",
            ]
            for sel in gen_selectors:
                try:
                    el = page.locator(sel).first
                    if el.is_visible(timeout=1000):
                        btn_text = (el.text_content() or "").strip()
                        log_result(f"A-4f: Generate button present ('{btn_text}')", "PASS")
                        gen_found = True
                        break
                except:
                    pass

            if not gen_found:
                buttons = page.locator("button").all()
                gen_candidates = []
                for b in buttons:
                    txt = (b.text_content() or "").strip()
                    if any(kw in txt for kw in ["생성 시작", "글 생성", "작성 시작"]):
                        gen_candidates.append(txt)
                if gen_candidates:
                    log_result(f"A-4f: Generate button (found: {gen_candidates[:3]})", "PASS")
                else:
                    log_result("A-4f: '글 생성 시작' or similar generate button", "WARN",
                               "Not visible — Step 1 generate button only appears after keyword analysis")
        except Exception as e:
            log_result("A-4f: Generate button", "FAIL", str(e))

        # A-5: Scroll down and screenshot bottom
        try:
            page.evaluate("window.scrollTo(0, document.body.scrollHeight)")
            time.sleep(1)
            page.screenshot(path=f"{SCREENSHOT_DIR}/06_generate_form_bottom.png", full_page=False)
            log_result("A-5: Scroll down + screenshot 06_generate_form_bottom.png", "PASS")
        except Exception as e:
            log_result("A-5: Scroll down + screenshot 06_generate_form_bottom.png", "FAIL", str(e))

        # ─────────────────────────────────────────────────────────
        # PART B: Competition Analysis Form UI (Step 2)
        # ─────────────────────────────────────────────────────────
        print("\n[Part B] Competition Analysis Form UI (Step 2)")
        print("-" * 50)

        # B-6: Click Step 2 "경쟁 분석"
        try:
            page.evaluate("window.scrollTo(0, 0)")
            time.sleep(0.5)
            step2_clicked = False
            selectors_step2 = [
                "button:has-text('경쟁 분석')",
                "button:has-text('경쟁분석')",
                "text=경쟁 분석",
                "[class*='step'] button",
            ]
            for sel in selectors_step2:
                try:
                    els = page.locator(sel).all()
                    for el in els:
                        txt = (el.text_content() or "").strip()
                        if "경쟁" in txt:
                            if el.is_visible(timeout=1000):
                                el.click()
                                step2_clicked = True
                                break
                    if step2_clicked:
                        break
                except:
                    pass

            time.sleep(2)
            if step2_clicked:
                log_result("B-6: Click Step 2 '경쟁 분석'", "PASS")
            else:
                log_result("B-6: Click Step 2 '경쟁 분석'", "WARN",
                           "Step 2 button not found — may require Step 1 completion first")
        except Exception as e:
            log_result("B-6: Click Step 2 '경쟁 분석'", "WARN", str(e))

        # B-7: Wait 2s, screenshot
        time.sleep(2)
        try:
            page.screenshot(path=f"{SCREENSHOT_DIR}/07_competition_form.png", full_page=False)
            log_result("B-7: Screenshot 07_competition_form.png", "PASS")
        except Exception as e:
            log_result("B-7: Screenshot 07_competition_form.png", "FAIL", str(e))

        page_text = page.inner_text("body")

        # B-8a: "경쟁 분석 대상 키워드" section
        try:
            el = page.locator("text=경쟁 분석 대상 키워드").first
            visible = False
            try:
                visible = el.is_visible(timeout=2000)
            except:
                pass
            if visible:
                log_result("B-8a: '경쟁 분석 대상 키워드' section present", "PASS")
            elif "경쟁 분석 대상 키워드" in page_text:
                log_result("B-8a: '경쟁 분석 대상 키워드' section in DOM", "PASS",
                           "Found in page text (may be in virtual DOM)")
            elif "경쟁" in page_text and "분석" in page_text:
                log_result("B-8a: '경쟁 분석 대상 키워드' section", "WARN",
                           "Exact text not found, but competition-analysis content present in page")
            else:
                log_result("B-8a: '경쟁 분석 대상 키워드' section", "FAIL",
                           "Not found — Step 2 form requires completing Steps 0 and 1 first")
        except Exception as e:
            log_result("B-8a: '경쟁 분석 대상 키워드' section", "FAIL", str(e))

        # B-8b: "분석 시작" button
        try:
            start_found = False
            for sel in ["button:has-text('분석 시작')", "button:has-text('분석시작')", "button:has-text('경쟁 분석 시작')"]:
                try:
                    el = page.locator(sel).first
                    if el.is_visible(timeout=1000):
                        start_found = True
                        log_result(f"B-8b: '분석 시작' button present ('{el.text_content().strip()}')", "PASS")
                        break
                except:
                    pass
            if not start_found:
                buttons = page.locator("button").all()
                btn_texts = [(b.text_content() or "").strip() for b in buttons]
                start_candidates = [t for t in btn_texts if "분석" in t and ("시작" in t or "분석" in t)]
                if start_candidates:
                    log_result(f"B-8b: Analysis start button (found: {start_candidates[:3]})", "PASS")
                else:
                    log_result("B-8b: '분석 시작' button", "WARN",
                               f"Not found. Available buttons: {btn_texts[:8]}")
        except Exception as e:
            log_result("B-8b: '분석 시작' button", "FAIL", str(e))

        # B-8c: "← 글 생성으로" back button
        try:
            back_found = False
            for sel in ["button:has-text('글 생성으로')", "text=← 글 생성", "button:has-text('← 글')", "button:has-text('글 생성으로')"]:
                try:
                    el = page.locator(sel).first
                    if el.is_visible(timeout=1000):
                        back_found = True
                        log_result(f"B-8c: '← 글 생성으로' back button present ('{el.text_content().strip()}')", "PASS")
                        break
                except:
                    pass
            if not back_found:
                buttons = page.locator("button").all()
                btn_texts = [(b.text_content() or "").strip() for b in buttons]
                back_candidates = [t for t in btn_texts if "글 생성" in t or "생성으로" in t]
                if back_candidates:
                    log_result(f"B-8c: Back button to write (found: {back_candidates})", "PASS")
                else:
                    log_result("B-8c: '← 글 생성으로' back button", "WARN",
                               f"Not found. Buttons: {btn_texts[:8]}")
        except Exception as e:
            log_result("B-8c: '← 글 생성으로' back button", "FAIL", str(e))

        # ─────────────────────────────────────────────────────────
        # PART C: History Detail - Success Item
        # ─────────────────────────────────────────────────────────
        print("\n[Part C] History Detail — Success Item")
        print("-" * 50)

        # C-9: Go back to Step 0, scroll to history section
        try:
            page.evaluate("window.scrollTo(0, 0)")
            time.sleep(0.3)
            # Click "0 키워드 분석" step or use back button
            step0_clicked = False
            for sel in ["button:has-text('키워드 분석')", "text=키워드 분석", "[data-step='0']",
                        "button:has-text('0')"]:
                try:
                    els = page.locator(sel).all()
                    for el in els:
                        txt = (el.text_content() or "").strip()
                        if "키워드 분석" in txt or txt == "0":
                            if el.is_visible(timeout=1000):
                                el.click()
                                step0_clicked = True
                                break
                    if step0_clicked:
                        break
                except:
                    pass
            time.sleep(1.5)

            # Scroll to history section
            try:
                hist_el = page.locator("text=히스토리").first
                if hist_el.is_visible(timeout=2000):
                    hist_el.scroll_into_view_if_needed(timeout=3000)
            except:
                page.evaluate("window.scrollTo(0, 400)")
            time.sleep(0.5)

            log_result("C-9: Navigate to Step 0 + scroll to history section", "PASS" if step0_clicked else "WARN",
                       "" if step0_clicked else "Step 0 click not confirmed")
        except Exception as e:
            log_result("C-9: Navigate to Step 0 + scroll to history", "WARN", str(e))

        # C-10: Click "키워드분석" tab in history
        try:
            kw_tab_clicked = False
            for sel in ["text=키워드분석", "text=키워드 분석",
                        "button:has-text('키워드분석')", "button:has-text('키워드 분석')"]:
                try:
                    els = page.locator(sel).all()
                    for el in els:
                        if el.is_visible(timeout=1000):
                            el.click()
                            kw_tab_clicked = True
                            break
                    if kw_tab_clicked:
                        break
                except:
                    pass
            time.sleep(1.5)
            log_result("C-10: Click '키워드분석' tab in history", "PASS" if kw_tab_clicked else "WARN",
                       "" if kw_tab_clicked else "Tab not found; may already be on keyword tab")
        except Exception as e:
            log_result("C-10: Click '키워드분석' tab in history", "WARN", str(e))

        # C-11: Find and click a SUCCESS item
        # In the 키워드분석 history tab, items WITHOUT ❌ or failure indicators are successes
        try:
            success_clicked = False
            clicked_item_text = ""

            # The keyword analysis history shows items like "실손보험", "인카금융,..."
            # Items that are just keyword text (no ❌, no 실패 text) are success items
            # Strategy: find list items in the history section, skip ones with failure markers

            # First try to find success indicators (✅ or items without failures)
            history_rows = page.evaluate("""() => {
                const rows = [];
                // Look for list items in history section
                const histSection = document.querySelector('[class*="history"]') ||
                                   document.querySelector('section') ||
                                   document.body;
                const items = histSection.querySelectorAll('li, [class*="item"], [class*="row"]');
                for (const item of items) {
                    const text = item.textContent ? item.textContent.trim().substring(0, 100) : '';
                    const isFailure = text.includes('❌') || text.includes('실패') || text.includes('✕');
                    if (!isFailure && text.length > 3) {
                        rows.push(text);
                    }
                }
                return rows.slice(0, 10);
            }""")
            print(f"  [DEBUG] Potential success history items: {history_rows[:5]}")

            # Now click the first non-failure item
            # Try clicking text that matches keyword history items (just keyword text, no failure)
            keyword_texts = ["실손보험", "인카금융", "티오피사업단", "수원"]
            for kw_text in keyword_texts:
                try:
                    els = page.locator(f"text={kw_text}").all()
                    for el in els:
                        parent_txt = page.evaluate("""(el) => {
                            const p = el.closest('li') || el.closest('[class*="item"]') || el.parentElement;
                            return p ? p.textContent.trim().substring(0, 100) : '';
                        }""", el.element_handle())
                        if "실패" not in parent_txt and "❌" not in parent_txt:
                            if el.is_visible(timeout=1000):
                                el.click()
                                success_clicked = True
                                clicked_item_text = parent_txt[:60]
                                break
                    if success_clicked:
                        break
                except:
                    pass

            if not success_clicked:
                # Fallback: click first visible item in list
                all_li = page.locator("li").all()
                for li in all_li[:20]:
                    try:
                        txt = (li.text_content() or "").strip()
                        if len(txt) > 3 and "❌" not in txt and "실패" not in txt and "✕" not in txt:
                            if li.is_visible(timeout=500):
                                li.click()
                                success_clicked = True
                                clicked_item_text = txt[:60]
                                break
                    except:
                        pass

            time.sleep(2)
            if success_clicked:
                log_result(f"C-11: Found and clicked SUCCESS history item ('{clicked_item_text}')", "PASS")
            else:
                log_result("C-11: Found and clicked SUCCESS history item", "WARN",
                           "Could not identify/click a success item")
        except Exception as e:
            log_result("C-11: Found and clicked SUCCESS history item", "WARN", str(e))

        # C-12: Screenshot detail panel
        try:
            time.sleep(1)
            page.screenshot(path=f"{SCREENSHOT_DIR}/08_history_success_detail.png", full_page=False)
            log_result("C-12: Screenshot 08_history_success_detail.png", "PASS")
        except Exception as e:
            log_result("C-12: Screenshot 08_history_success_detail.png", "FAIL", str(e))

        # C-13: Check detail panel contents
        page_text = page.inner_text("body")

        # a) Selected keywords
        try:
            kw_indicators = ["키워드", "keyword", "분석 키워드", "선택 키워드", "순위", "확정"]
            kw_found = any(kw.lower() in page_text.lower() for kw in kw_indicators)
            if kw_found:
                log_result("C-13a: Detail panel shows selected keywords", "PASS")
            else:
                log_result("C-13a: Detail panel shows selected keywords", "WARN",
                           "Keyword info not clearly visible in detail panel")
        except Exception as e:
            log_result("C-13a: Detail panel keywords", "FAIL", str(e))

        # b) Analysis data
        try:
            analysis_indicators = ["순위", "검색량", "조회", "월간", "경쟁", "월평균", "PC", "모바일"]
            analysis_found = any(w in page_text for w in analysis_indicators)
            if analysis_found:
                found_items = [w for w in analysis_indicators if w in page_text]
                log_result("C-13b: Detail panel shows analysis data", "PASS",
                           f"Found: {found_items[:4]}")
            else:
                log_result("C-13b: Detail panel analysis data", "WARN",
                           "Analysis data fields not visible in page text")
        except Exception as e:
            log_result("C-13b: Detail panel analysis data", "FAIL", str(e))

        # c) "이 키워드로 글 재생성" button
        try:
            regen_found = False
            regen_selectors = [
                "text=이 키워드로 글 재생성",
                "button:has-text('재생성')",
                "button:has-text('이 키워드로')",
                "button:has-text('글 재생성')",
                "button:has-text('글 작성')",
                "button:has-text('글작성')",
                "button:has-text('글 생성')",
            ]
            found_btn_text = ""
            for sel in regen_selectors:
                try:
                    el = page.locator(sel).first
                    if el.is_visible(timeout=1000):
                        found_btn_text = (el.text_content() or "").strip()
                        regen_found = True
                        break
                except:
                    pass

            if regen_found:
                log_result(f"C-13c: '이 키워드로 글 재생성' button present ('{found_btn_text}')", "PASS")
            else:
                # Scan all buttons
                buttons = page.locator("button").all()
                all_btn_texts = [(b.text_content() or "").strip() for b in buttons]
                write_btns = [t for t in all_btn_texts if any(kw in t for kw in ["생성", "작성", "시작", "재생성"])]
                if write_btns:
                    log_result(f"C-13c: Write/generate buttons visible ('{write_btns[:3]}')", "WARN",
                               "Exact '이 키워드로 글 재생성' not found but similar buttons exist")
                else:
                    log_result("C-13c: '이 키워드로 글 재생성' button", "WARN",
                               f"Button not found. May need to open a specific history detail. All buttons: {all_btn_texts[:6]}")
        except Exception as e:
            log_result("C-13c: '이 키워드로 글 재생성' button", "FAIL", str(e))

        # ─────────────────────────────────────────────────────────
        # PART D: API Endpoint Checks (via page.evaluate fetch)
        # ─────────────────────────────────────────────────────────
        print("\n[Part D] API Endpoint Checks")
        print("-" * 50)

        api_endpoints = [
            {"url": "/api/naver-blog/history/keywords",    "label": "GET /api/naver-blog/history/keywords"},
            {"url": "/api/naver-blog/history/contents",    "label": "GET /api/naver-blog/history/contents"},
            {"url": "/api/naver-blog/history/competitions","label": "GET /api/naver-blog/history/competitions"},
            {"url": "/api/naver-blog/write/status",        "label": "GET /api/naver-blog/write/status"},
        ]

        for ep in api_endpoints:
            try:
                result = page.evaluate(f"""async () => {{
                    try {{
                        const resp = await fetch('{BASE_URL}{ep["url"]}');
                        const status = resp.status;
                        let summary = '';
                        try {{
                            const body = await resp.json();
                            if (Array.isArray(body)) {{
                                summary = `array[${{body.length}} items]`;
                            }} else if (body && typeof body === 'object') {{
                                const keys = Object.keys(body).slice(0, 6).join(', ');
                                summary = `{{${{keys}}}}`;
                                if (body.items && Array.isArray(body.items)) {{
                                    summary += ` — ${{body.items.length}} items`;
                                }}
                                if (body.status !== undefined) {{
                                    summary += ` — status=${{body.status}}`;
                                }}
                            }} else {{
                                summary = String(body).substring(0, 100);
                            }}
                        }} catch(e) {{
                            summary = 'non-JSON response';
                        }}
                        return {{ status, summary }};
                    }} catch(e) {{
                        return {{ status: 0, summary: e.toString() }};
                    }}
                }}""")

                status = result.get("status", 0)
                summary = result.get("summary", "")
                print(f"  {ep['label']}")
                print(f"    → HTTP {status} | {summary}")

                if status == 200:
                    log_result(f"D: {ep['label']}", "PASS", f"HTTP {status} | {summary}")
                elif status == 0:
                    log_result(f"D: {ep['label']}", "FAIL", f"Network error: {summary}")
                else:
                    log_result(f"D: {ep['label']}", "WARN", f"HTTP {status} | {summary}")
            except Exception as e:
                log_result(f"D: {ep['label']}", "FAIL", str(e))

        # ─────────────────────────────────────────────────────────
        # FINAL SUMMARY
        # ─────────────────────────────────────────────────────────
        print("\n" + "=" * 70)
        print("FINAL TEST SUMMARY")
        print("=" * 70)

        pass_count  = sum(1 for r in results if r["status"] == "PASS")
        warn_count  = sum(1 for r in results if r["status"] == "WARN")
        fail_count  = sum(1 for r in results if r["status"] == "FAIL")
        total       = len(results)

        for r in results:
            icon = "[PASS]" if r["status"] == "PASS" else "[FAIL]" if r["status"] == "FAIL" else "[WARN]"
            detail = f" — {r['detail']}" if r["detail"] else ""
            print(f"  {icon} {r['label']}{detail}")

        print()
        print(f"Results: {pass_count}/{total} PASS | {warn_count} WARN | {fail_count} FAIL")
        print()
        print(f"Screenshots saved to: {SCREENSHOT_DIR}/")
        for f in ["06_generate_form_top.png", "06_generate_form_bottom.png",
                  "07_competition_form.png", "08_history_success_detail.png"]:
            print(f"  - {f}")

        browser.close()


if __name__ == "__main__":
    run_tests()
