# scraper2_hj3415/app/nfs/services/fetch/fetch_c104.py
from __future__ import annotations

import asyncio
import random
from collections.abc import Iterable

from logging_hj3415 import logger
from scraper2_hj3415.app.nfs.adapters.site.wisereport_playwright import (
    WiseReportPlaywright,
)
from scraper2_hj3415.app.nfs.domain.constants import BLOCK_KEYS_BY_ENDPOINT
from scraper2_hj3415.app.nfs.domain.doc import NfsDoc
from scraper2_hj3415.app.nfs.domain.endpoint import EndpointKind
from scraper2_hj3415.app.nfs.domain.types import Records
from scraper2_hj3415.app.nfs.parsing.c104_parser import (
    TABLE_XPATH,
    parse_c104_current_table,
)
from scraper2_hj3415.app.nfs.ports.browser.browser_factory_port import (
    BrowserFactoryPort,
)
from scraper2_hj3415.app.nfs.ports.site.wisereport_port import WiseReportPort
from scraper2_hj3415.app.nfs.services.fetch.common import gather_docs
from scraper2_hj3415.app.nfs.services.nfs_doc_builders import (
    build_metrics_doc_from_parsed,
)

BTN_SETS: dict[str, list[tuple[str, str]]] = {
    "수익성y": [
        ("수익성", 'xpath=//*[ @id="val_tab1"]'),
        ("연간", 'xpath=//*[@id="frqTyp0"]'),
        ("검색", 'xpath=//*[@id="hfinGubun"]'),
    ],
    "성장성y": [
        ("성장성", 'xpath=//*[ @id="val_tab2"]'),
        ("연간", 'xpath=//*[@id="frqTyp0"]'),
        ("검색", 'xpath=//*[@id="hfinGubun"]'),
    ],
    "안정성y": [
        ("안정성", 'xpath=//*[ @id="val_tab3"]'),
        ("연간", 'xpath=//*[@id="frqTyp0"]'),
        ("검색", 'xpath=//*[@id="hfinGubun"]'),
    ],
    "활동성y": [
        ("활동성", 'xpath=//*[ @id="val_tab4"]'),
        ("연간", 'xpath=//*[@id="frqTyp0"]'),
        ("검색", 'xpath=//*[@id="hfinGubun"]'),
    ],
    "가치분석y": [
        ("가치분석연간", 'xpath=//*[@id="frqTyp0_2"]'),
        ("가치분석검색", 'xpath=//*[@id="hfinGubun2"]'),
    ],
    "수익성q": [
        ("수익성", 'xpath=//*[ @id="val_tab1"]'),
        ("분기", 'xpath=//*[@id="frqTyp1"]'),
        ("검색", 'xpath=//*[@id="hfinGubun"]'),
    ],
    "성장성q": [
        ("성장성", 'xpath=//*[ @id="val_tab2"]'),
        ("분기", 'xpath=//*[@id="frqTyp1"]'),
        ("검색", 'xpath=//*[@id="hfinGubun"]'),
    ],
    "안정성q": [
        ("안정성", 'xpath=//*[ @id="val_tab3"]'),
        ("분기", 'xpath=//*[@id="frqTyp1"]'),
        ("검색", 'xpath=//*[@id="hfinGubun"]'),
    ],
    "활동성q": [
        ("활동성", 'xpath=//*[ @id="val_tab4"]'),
        ("분기", 'xpath=//*[@id="frqTyp1"]'),
        ("검색", 'xpath=//*[@id="hfinGubun"]'),
    ],
    "가치분석q": [
        ("가치분석분기", 'xpath=//*[@id="frqTyp1_2"]'),
        ("가치분석검색", 'xpath=//*[@id="hfinGubun2"]'),
    ],
}


def _table_index_for_key(key: str) -> int:
    # 가치분석은 별도 테이블(보통 index=1)
    return 1 if key.startswith("가치분석") else 0


class FetchC104:
    factory: BrowserFactoryPort

    def __init__(self, factory: BrowserFactoryPort):
        self.factory = factory

    async def _fetch_one(self, code: str, *, sleep_sec: float) -> NfsDoc | None:
        async with self.factory.lease() as browser:
            wr: WiseReportPort = WiseReportPlaywright(browser)

            url = (
                "https://navercomp.wisereport.co.kr/v2/company/c1040001.aspx"
                f"?cn=&cmp_cd={code}"
            )
            await browser.goto_and_wait_for_stable(url, timeout_ms=10_000)

            if sleep_sec > 0:
                await asyncio.sleep(sleep_sec + random.uniform(0, 1.0))

            parsed: dict[str, Records] = {}

            # idx별 안정화 상태 추적
            prev_text_by_idx: dict[int, str | None] = {0: None, 1: None}

            for key, steps in BTN_SETS.items():
                idx = _table_index_for_key(key)

                try:
                    # 1) 상태 확정 (분기/연간이 맞는지 헤더로 검증)
                    await wr.set_view_c104(
                        key=key,
                        steps=steps,
                        table_selector=TABLE_XPATH,
                        table_index=idx,
                        prev_text_by_idx=prev_text_by_idx,
                        max_attempts=5,
                        stabilize_timeout_sec=10.0,
                        min_rows=4,
                        min_lines=30,
                        open_consensus=True,
                        code=code,
                    )

                    # 2) 파싱은 “현재 화면의 idx 테이블 1개”만
                    parsed[key] = await parse_c104_current_table(
                        browser,
                        table_index=idx,
                    )

                except Exception as e:
                    logger.warning(
                        f"c104 view/parse failed: code={code} key={key} idx={idx} err={type(e).__name__}: {e}"
                    )
                    parsed[key] = []

            block_keys = BLOCK_KEYS_BY_ENDPOINT[EndpointKind.C104]
            if not parsed or all(not (parsed.get(str(bk)) or []) for bk in block_keys):
                logger.warning(
                    f"c104 fetch: parsed result empty; return None | code={code}"
                )
                return None

            doc = build_metrics_doc_from_parsed(
                code=code,
                endpoint_kind=EndpointKind.C104,
                parsed=parsed,
                block_keys=block_keys,
                item_key="항목",
                raw_label_key="항목_raw",
                keep_empty_blocks=True,
            )
            return doc

    async def execute(self, code: str, *, sleep_sec: float = 2.0) -> NfsDoc | None:
        return await self._fetch_one(code, sleep_sec=sleep_sec)

    async def execute_many(
        self,
        codes: Iterable[str],
        *,
        sleep_sec: float = 2.0,
    ) -> list[NfsDoc]:
        code_list = list(codes)
        return await gather_docs(
            {c: self._fetch_one(c, sleep_sec=sleep_sec) for c in code_list},
            endpoint="c104",
        )
