# scraper2_hj3415/app/nfs/adapters/out/playwright/capabilities/table.py
from __future__ import annotations

import re
from io import StringIO
from typing import Any, Hashable

import pandas as pd

from ._base import _PlaywrightBase  # pyright: ignore[reportPrivateUsage]

_PERIOD_MM_RE = re.compile(r"\b(19|20)\d{2}/(03|06|09|12)\b")


class PlaywrightTable(_PlaywrightBase):
    async def table_records(
        self,
        table_selector: str,
        *,
        header: int | list[int] | None = 0,
    ) -> list[dict[Hashable, Any]]:  # pyright: ignore[reportExplicitAny]
        await self.wait_attached(table_selector)

        table = self._page.locator(table_selector).first
        html: str = await table.evaluate(  # pyright: ignore[reportAny]
            "el => el.outerHTML"
        )

        try:
            df = pd.read_html(StringIO(html), header=header)[0]
        except Exception as e:
            raise RuntimeError(f"pd.read_html failed: {type(e).__name__}: {e}") from e

        # 문자열 컬럼일 때만 정규화
        if all(
            isinstance(c, str)  # pyright: ignore[reportUnnecessaryIsInstance]
            for c in df.columns
        ):
            if "항목" in df.columns:
                df["항목"] = (
                    df["항목"].astype(str).str.replace("펼치기", "").str.strip()
                )

            df.columns = (
                df.columns.astype(str)
                .str.replace("연간컨센서스보기", "", regex=False)
                .str.replace("연간컨센서스닫기", "", regex=False)
                .str.replace("(IFRS연결)", "", regex=False)
                .str.replace("(IFRS별도)", "", regex=False)
                .str.replace("(GAAP개별)", "", regex=False)
                .str.replace("(YoY)", "", regex=False)
                .str.replace("(QoQ)", "", regex=False)
                .str.replace("(E)", "", regex=False)
                .str.replace(".", "", regex=False)
                .str.strip()
            )

        return df.where(
            pd.notnull(df), None
        ).to_dict(  # pyright: ignore[reportArgumentType]
            orient="records"
        )

    async def table_header_texts_nth(
        self, table_selector: str, *, index: int
    ) -> list[str]:
        table = self._page.locator(table_selector).nth(index)
        thead = table.locator("thead")
        if await thead.count() == 0:
            return []

        ths = thead.locator("th")
        try:
            texts = await ths.all_inner_texts()
        except Exception:
            texts = []

        out: list[str] = []
        for t in texts:
            t = " ".join((t or "").split())
            if t:
                out.append(t)
        return out

    async def table_header_periods_mm_nth(
        self, table_selector: str, *, index: int
    ) -> list[str]:
        texts = await self.table_header_texts_nth(table_selector, index=index)
        periods: list[str] = []
        for t in texts:
            for m in _PERIOD_MM_RE.finditer(t):
                periods.append(m.group(0))

        seen: set[str] = set()
        uniq: list[str] = []
        for p in periods:
            if p in seen:
                continue
            seen.add(p)
            uniq.append(p)
        return uniq
