import re
import time
from typing import Dict, Iterator, List, Optional
from urllib.parse import urljoin

import requests
from bs4 import BeautifulSoup

BASE = "https://www.motie.go.kr"

def _req(url: str, ua: str, params: Optional[dict] = None) -> requests.Response:
    headers = {
        "User-Agent": ua or "govbot/1.0",
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    }
    r = requests.get(url, headers=headers, params=params, timeout=20)
    r.raise_for_status()
    return r

def _clean(s: str) -> str:
    return " ".join((s or "").split())

def get_last_page(ua: str) -> int:
    """
    /kor/25/empSearch 첫 페이지에서 a.direction.last 의 onclick 속성
    'empSearch.list(숫자)'에서 숫자를 추출해 마지막 페이지로 사용.
    """
    url = f"{BASE}/kor/25/empSearch"
    res = _req(url, ua)
    soup = BeautifulSoup(res.text, "html.parser")
    a_last = soup.select_one("a.direction.last")
    if not a_last:
        # 페이징이 없을 수도 있으니 기본 1
        return 1
    onclick = a_last.get("onclick", "")
    m = re.search(r"empSearch\.list\((\d+)\)", onclick)
    return int(m.group(1)) if m else 1

def iter_emp_rows_from_page_html(html: str) -> List[Dict]:
    """
    목록 테이블의 각 tr을 파싱하여 name/position/department/task/phone을 추출.
    1) 우선 td 셀 기반 파싱
    2) 실패 시 n8n에서 하던 '행 텍스트를 공백 분리' 백업 파싱
    """
    soup = BeautifulSoup(html, "html.parser")
    out: List[Dict] = []
    rows = soup.select("table tbody tr")
    for tr in rows:
        tds = tr.find_all("td")
        name = position = department = task = phone = ""
        parsed = False

        # 1) td 셀 기반 (권장)
        if len(tds) >= 5:
            name = _clean(tds[0].get_text(" ", strip=True))
            position = _clean(tds[1].get_text(" ", strip=True))
            department = _clean(tds[2].get_text(" ", strip=True))
            # 담당업무/연락처가 나뉘어 있거나 섞여 있을 수 있음
            # 우선 끝쪽 td들에서 전화/업무를 추정
            # tel: 링크 우선
            tel_a = tr.select_one('a[href^="tel:"]')
            if tel_a and tel_a.has_attr("href"):
                phone = tel_a["href"].removeprefix("tel:").strip()
            else:
                # 숫자 형태로 탐지
                tail_txt = " ".join(_clean(td.get_text(" ", strip=True)) for td in tds[-2:])
                m = re.search(r"\b\d{2,4}-\d{3,4}-\d{4}\b", tail_txt)
                phone = m.group(0) if m else ""

            # 업무 텍스트 후보
            # (전화가 섞여 있으면 제거)
            body_txt = _clean(tds[3].get_text(" ", strip=True)) if len(tds) >= 4 else ""
            if not body_txt:
                # 한 칸 밀려 있을 수 있음
                body_txt = _clean(tds[-2].get_text(" ", strip=True))
            task = body_txt.replace(phone, "").strip()
            parsed = True

        # 2) 백업: tr 전체 텍스트를 공백 분리해 n8n과 유사 처리
        if not parsed:
            row_text = _clean(tr.get_text(" ", strip=True))
            if not row_text:
                continue
            columns = row_text.split()
            if len(columns) < 5:
                continue
            name = columns[0]
            position = columns[1]
            department = columns[2]
            # 마지막 토큰에서 전화 추출 시도
            last_token = columns[-1]
            m = re.search(r"\b\d{2,4}-\d{3,4}-\d{4}\b", last_token)
            phone = m.group(0) if m else last_token
            task = " ".join(columns[3:-1]).replace(phone, "").strip()

        out.append({
            "name": name,
            "position": position,
            "department": department,
            "task": task,
            "phone": phone,
        })
    return out

def fetch_emp_page(ua: str, page: int) -> List[Dict]:
    """
    /kor/25/empSearch?pageIndex={page} 한 페이지를 가져와 행 파싱
    """
    url = f"{BASE}/kor/25/empSearch"
    res = _req(url, ua, params={"pageIndex": page})
    return iter_emp_rows_from_page_html(res.text)

def fetch_departments(ua: str) -> List[str]:
    """
    /kor/26/headquarters 페이지에서
    a[onclick*="headquarters.jsSearchOrgan"] 의 텍스트(부서명)를 모두 수집.
    n8n 로직처럼 첫 번째 항목은 스킵(헤더 가능성)하고 나머지 사용.
    """
    url = f"{BASE}/kor/26/headquarters"
    res = _req(url, ua)
    soup = BeautifulSoup(res.text, "html.parser")
    arr = [ _clean(a.get_text(" ", strip=True))
            for a in soup.select('a[onclick*="headquarters.jsSearchOrgan"]') ]
    # 첫 항목 스킵 + 중복 제거
    arr = [x for x in arr[1:] if x]
    seen = set()
    uniq = []
    for x in arr:
        if x not in seen:
            uniq.append(x); seen.add(x)
    return uniq
