#!/usr/bin/env python3
"""实习生日报统计 — 按 PDT 分组输出提交/请假/未提交统计。"""

from __future__ import annotations

import argparse
import glob
import os
import re
import sys
from collections import OrderedDict
from datetime import date, datetime, timedelta
from pathlib import Path
from typing import Any, Dict, List, Optional, Tuple


def find_roster_file(roster_dir: str) -> Path:
    pattern = os.path.join(roster_dir, "实习生信息表-*.md")
    matches = sorted(glob.glob(pattern))
    if not matches:
        sys.exit("未找到名册文件: {}".format(pattern))
    return Path(matches[0])


def parse_roster_table(filepath: Path) -> List[Dict[str, Any]]:
    """解析「实习生维度」表格，返回在职+已入职人员列表。"""
    content = filepath.read_text(encoding="utf-8")

    m = re.search(r"###\s+1\.\s*实习生维度(.*?)(?=###|\Z)", content, re.DOTALL)
    if not m:
        sys.exit("名册中未找到「1. 实习生维度」章节")

    section = m.group(1)
    lines = section.strip().split("\n")

    interns: List[Dict[str, Any]] = []
    in_table = False

    for line in lines:
        line = line.strip()
        if line.startswith("|") and "姓名" in line and "入职日期" in line:
            in_table = True
            continue
        if in_table and line.startswith("|---"):
            continue
        if in_table and line.startswith("|"):
            cells = [c.strip() for c in line.strip("|").split("|")]
            if len(cells) < 11:
                continue
            name = cells[1].strip()
            if not name:
                continue

            start_date_str = cells[2].strip()
            mentor = cells[5].strip()
            pdt = cells[9].strip()
            note = cells[10].strip() if len(cells) > 10 else ""

            # 排除已离职/放弃入职
            if "已离职" in note or "放弃入职" in note:
                continue

            # 解析入职日期
            start_date: Optional[date] = None
            try:
                start_date = datetime.strptime(start_date_str, "%Y/%m/%d").date()
            except ValueError:
                pass  # "待定"/"已入职" → None，后续按未入职排除

            interns.append({
                "name": name,
                "mentor": mentor,
                "pdt": pdt or "未分配PDT",
                "start_date": start_date,
                "note": note,
            })
        elif in_table and not line.startswith("|") and line.strip() != "":
            break

    return interns


def parse_daily_entries(filepath: Path) -> Dict[str, Dict[str, str]]:
    """解析 YYYY-MM-DD.md，返回 {姓名: {summary, blocker, next_step, ts}}。"""
    if not filepath.exists():
        return {}

    content = filepath.read_text(encoding="utf-8")
    entries = re.split(r"\n---\n", content)

    result: Dict[str, Dict[str, str]] = {}
    for entry in entries:
        name_m = re.search(r"姓名[：:]\s*(.+?)(?:\n|$)", entry)
        if not name_m:
            continue
        name = name_m.group(1).strip().rstrip("。，,.")

        ts_m = re.search(r"收到时间：(.+?)(?:（|$)", entry)
        ts = ts_m.group(1).strip() if ts_m else ""

        work_m = re.search(r"今[日天]主要工作[：:]\s*(.+?)(?:\n|$)", entry)
        work = work_m.group(1).strip() if work_m else ""

        blocker_m = re.search(r"(?:是否存在卡点|是否卡点)[：:]\s*(.+?)(?:\n|$)", entry)
        blocker = blocker_m.group(1).strip() if blocker_m else ""

        next_m = re.search(r"下一步计划[：:]\s*(.+?)(?:\n|$)", entry)
        next_step = next_m.group(1).strip() if next_m else ""

        # 同名取第一条（日报文件中条目已按时间倒序排列）
        if name not in result:
            result[name] = {
                "summary": work,
                "blocker": blocker,
                "next_step": next_step,
                "ts": ts,
            }

    return result


def parse_leave_table(filepath: Path) -> List[Dict[str, str]]:
    """解析 leave.md 表格，返回 [{name, leave_time, reason, report_date}]。"""
    if not filepath.exists():
        return []

    content = filepath.read_text(encoding="utf-8")
    lines = content.split("\n")

    leaves: List[Dict[str, str]] = []
    for line in lines:
        line = line.strip()
        if not line.startswith("|") or "报备日期" in line or line.startswith("|---"):
            continue

        cells = [c.strip() for c in line.strip("|").split("|")]
        if len(cells) < 5:
            continue

        leaves.append({
            "name": cells[1].strip(),
            "leave_time": cells[3].strip(),
            "reason": cells[4].strip(),
            "report_date": cells[0].strip(),
        })

    return leaves


def is_date_in_leave_range(query_date: date, leave_time_str: str) -> bool:
    """判断查询日期是否在请假时间范围内。"""
    if not leave_time_str:
        return False

    # 提取所有 YYYY-MM-DD
    date_matches = re.findall(r"(\d{4})-(\d{2})-(\d{2})", leave_time_str)
    if not date_matches:
        return False

    date_list: List[date] = []
    for y, m, d in date_matches:
        try:
            date_list.append(date(int(y), int(m), int(d)))
        except ValueError:
            pass

    if not date_list:
        return False

    dates: set = set()
    if "～" in leave_time_str and len(date_list) >= 2:
        date_list.sort()
        d = date_list[0]
        end = date_list[-1]
        while d <= end:
            dates.add(d)
            d += timedelta(days=1)
    else:
        dates.update(date_list)

    return query_date in dates


def judge_status(
    roster_entry: Dict[str, Any],
    daily_data: Dict[str, Dict[str, str]],
    leave_data: List[Dict[str, str]],
    query_date: date,
) -> Tuple[str, Dict[str, Any]]:
    """判定单个实习生状态。返回 (status, detail)。

    status: 'not_onboarded' | 'submitted' | 'on_leave' | 'missing'
    """
    name = roster_entry["name"]
    start_date = roster_entry.get("start_date")

    # 未入职（入职日期 > 查询日期 或 无日期）
    if start_date is None or start_date > query_date:
        return ("not_onboarded", {})

    is_today_onboard = (start_date == query_date)

    # 提交了日报
    if name in daily_data:
        detail = dict(daily_data[name])
        detail["is_today_onboard"] = is_today_onboard
        return ("submitted", detail)

    # 未提交 → 查请假
    for lv in leave_data:
        if lv["name"] == name:
            if is_date_in_leave_range(query_date, lv["leave_time"]):
                return ("on_leave", {
                    "leave_time": lv["leave_time"],
                    "reason": lv["reason"],
                    "is_today_onboard": is_today_onboard,
                })

    return ("missing", {"is_today_onboard": is_today_onboard})


def format_report(
    roster: List[Dict[str, Any]],
    daily_data: Dict[str, Dict[str, str]],
    leave_data: List[Dict[str, str]],
    query_date: date,
) -> str:
    """按 PDT 分组格式化统计报告。"""
    pdt_groups: Dict[str, List[Dict[str, Any]]] = OrderedDict()

    for intern in roster:
        status, detail = judge_status(intern, daily_data, leave_data, query_date)

        if status == "not_onboarded":
            continue

        intern["_status"] = status
        intern["_detail"] = detail

        pdt = intern.get("pdt", "未分配PDT")
        if pdt not in pdt_groups:
            pdt_groups[pdt] = []
        pdt_groups[pdt].append(intern)

    # Title
    title = "Sophclaw {}月{}日实习生日报".format(query_date.month, query_date.day)
    lines: List[str] = ["# {}".format(title), ""]

    # Build output
    status_order = {"submitted": 0, "on_leave": 1, "missing": 2}

    for pdt, members in pdt_groups.items():
        submitted_count = sum(1 for m in members if m["_status"] == "submitted")
        leave_count = sum(1 for m in members if m["_status"] == "on_leave")
        missing_count = sum(1 for m in members if m["_status"] == "missing")

        lines.append("## {}（{}/{}人）".format(pdt, submitted_count, len(members)))
        lines.append("")

        members.sort(key=lambda m: (status_order.get(m["_status"], 9), m["name"]))

        for m in members:
            name = m["name"]
            detail = m.get("_detail", {})
            tag = "🆕 " if detail.get("is_today_onboard") else ""

            if m["_status"] == "submitted":
                lines.append(
                    "- **{}：** {}✅ {}【卡点：{}】【下一步：{}】".format(
                        name, tag,
                        detail.get("summary", ""),
                        detail.get("blocker", "否"),
                        detail.get("next_step", ""),
                    )
                )
            elif m["_status"] == "on_leave":
                leave_time = detail.get("leave_time", "")
                reason = detail.get("reason", "")
                lines.append(
                    "- **{}：** {}🏖️ {}— {}".format(name, tag, leave_time, reason)
                )
            else:
                lines.append("- **{}：** {}❌ 未提交".format(name, tag))

        lines.append("")
        lines.append(
            "> 提交：{} | 未提交：{} | 请假：{}（不计入未提交）".format(
                submitted_count, missing_count, leave_count
            )
        )
        lines.append("")
        lines.append("---")
        lines.append("")

    # Missing-reminder: group by mentor
    missing_by_mentor: Dict[str, List[str]] = OrderedDict()
    for m in roster:
        if m.get("_status") == "missing":
            mentor = m.get("mentor", "")
            if mentor:
                missing_by_mentor.setdefault(mentor, []).append(m["name"])

    # Missing reminder
    if missing_by_mentor:
        lines.append("")
        lines.append("---")
        lines.append("")
        lines.append("⚠️ **未提交提醒：**")
        lines.append("")
        for mentor, names in missing_by_mentor.items():
            lines.append(
                "- @{}：{} 未提交日报".format(mentor, "、".join(names))
            )

    return "\n".join(lines)


DEFAULT_DAILY_DIR = "/home/node/.openclaw/workspace-intern/workspace-intern-qa/records"


def main() -> int:
    p = argparse.ArgumentParser(description="实习生日报统计")
    p.add_argument("--date", "-d", required=True, help="查询日期 (YYYY-MM-DD)")
    p.add_argument(
        "--roster-dir", "-r", default="memory", help="名册目录（默认: memory/）"
    )
    p.add_argument(
        "--daily-dir",
        default=DEFAULT_DAILY_DIR,
        help="日报/请假文件目录（默认: {}）".format(DEFAULT_DAILY_DIR),
    )
    args = p.parse_args()

    # 解析日期
    try:
        query_date = datetime.strptime(args.date, "%Y-%m-%d").date()
    except ValueError:
        sys.exit("日期格式错误: {}（需要 YYYY-MM-DD）".format(args.date))

    # 解析名册
    roster_file = find_roster_file(args.roster_dir)
    roster = parse_roster_table(roster_file)

    if not roster:
        print("⚠️ 名册中无在职实习生记录")
        return 0

    # 解析日报
    daily_dir = Path(args.daily_dir)
    daily_file = daily_dir / "{}.md".format(query_date.isoformat())
    daily_data = parse_daily_entries(daily_file)

    # 解析请假
    leave_file = daily_dir / "leave.md"
    leave_data = parse_leave_table(leave_file)

    # 格式化输出
    report = format_report(roster, daily_data, leave_data, query_date)
    print(report)

    return 0


if __name__ == "__main__":
    try:
        raise SystemExit(main())
    except Exception as exc:
        print("⚠️ {}".format(exc), file=sys.stderr)
        raise SystemExit(1)
