from __future__ import annotations

from dataclasses import dataclass
from pathlib import Path
from typing import Optional

from playwright.sync_api import Page

from ....core.artifacts import shot
from ....core.log import log_step, pause


@dataclass(frozen=True)
class TargetDate:
    year: int
    month: int
    day: int

    @staticmethod
    def parse(iso_date: str) -> "TargetDate":
        y, m, d = iso_date.strip().split("-")
        return TargetDate(year=int(y), month=int(m), day=int(d))


def _wait_timesheet_ready(page: Page) -> None:
    page.wait_for_function(
        """() => {
            const u = location.href.toLowerCase();
            if (!u.includes('timesheet')) return false;
            const t = document.body && (document.body.innerText || '');
            return t.includes('Daily Timesheet') || t.includes('Timesheet for');
        }""",
        timeout=45_000,
    )


def _get_current_date_from_dom(page: Page) -> Optional[str]:
    try:
        btn = page.locator("button.gpsWindowFullBtn[data-current-date]").first
        if btn.count() == 0:
            return None
        v = btn.get_attribute("data-current-date")
        return v or None
    except Exception:
        return None


def _normalize_dom_date_to_iso(dom_date: str) -> str:
    parts = dom_date.strip().split("/")
    if len(parts) != 3:
        return dom_date
    return f"{parts[0]}-{parts[1]}-{parts[2]}"


def _wait_date_changed(page: Page, target_iso: str) -> None:
    page.wait_for_function(
        """(targetIso) => {
            const btn = document.querySelector("button.gpsWindowFullBtn[data-current-date]");
            if (!btn) return false;
            const v = btn.getAttribute("data-current-date") || "";
            const iso = v.replaceAll("/", "-");
            return iso === targetIso;
        }""",
        arg=target_iso,
        timeout=20_000,
    )


def run(page: Page, cfg, run_dir: Path, *, target_date: str) -> None:
    _wait_timesheet_ready(page)

    tgt = TargetDate.parse(target_date)
    target_iso = f"{tgt.year:04d}-{tgt.month:02d}-{tgt.day:02d}"

    dom_date = _get_current_date_from_dom(page)
    if dom_date:
        cur_iso = _normalize_dom_date_to_iso(dom_date)
        if cur_iso == target_iso:
            log_step(f"ts-date-already-{target_iso}", page)
            return

    shot(page, run_dir, f"ts-date-01-before-{target_iso}")
    log_step(f"ts-date-01-before-{target_iso}", page)
    pause(cfg, f"Before selecting date {target_iso}")

    href_fragment = f"sday={tgt.day}&smonth={tgt.month}&syear={tgt.year}"

    cal_link = page.locator(f".af-datepicker a.calDay[href*='{href_fragment}']").first

    if cal_link.count() == 0:
        shot(page, run_dir, f"ts-date-99-not-found-{target_iso}")
        raise RuntimeError(f"No encontré link del calendario para {target_iso} (href*='{href_fragment}').")

    cal_link.click()

    _wait_date_changed(page, target_iso)
    _wait_timesheet_ready(page)

    shot(page, run_dir, f"ts-date-02-after-{target_iso}")
    log_step(f"ts-date-02-after-{target_iso}", page)
    pause(cfg, f"After selecting date {target_iso}")
