TOOL_NAME = "parse_date"
TOOL_DESCRIPTION = (
    "Convert a natural-language date/time expression (Dutch or English) into "
    "exact ISO dates. Handles relative expressions like 'vandaag', 'gisteren', "
    "'vorige week', '3 dagen geleden', 'dinsdag', 'in maart', '14 februari 2026', etc. "
    "Returns {since, until, time_label} for use in calendar/email lookups. "
    "Always call this instead of guessing dates yourself."
)
TOOL_ARGS = '{"expression": {"type": "string", "description": "The date/time expression to parse, e.g. gisteren, vorige week, 3 dagen geleden, dinsdag, 14 maart 2026"}}'

import re
from datetime import datetime, timedelta
from tools._std import tool_ok, tool_error

_MONTH_NAME_TO_NUMBER = {
    "januari": 1, "january": 1, "februari": 2, "february": 2,
    "maart": 3, "march": 3, "april": 4, "mei": 5, "may": 5,
    "juni": 6, "june": 6, "juli": 7, "july": 7, "augustus": 8,
    "august": 8, "september": 9, "oktober": 10, "october": 10,
    "november": 11, "december": 12,
    "jan": 1, "feb": 2, "mrt": 3, "apr": 4, "jun": 6, "jul": 7,
    "aug": 8, "sep": 9, "okt": 10, "nov": 11, "dec": 12,
    "mar": 3, "oct": 10,
}

_WEEKDAY_NAMES_TO_INDEX = {
    "maandag": 0, "monday": 0, "dinsdag": 1, "tuesday": 1,
    "woensdag": 2, "wednesday": 2, "donderdag": 3, "thursday": 3,
    "vrijdag": 4, "friday": 4, "zaterdag": 5, "saturday": 5,
    "zondag": 6, "sunday": 6,
}

_MONTH_NAME_PATTERN = "|".join(_MONTH_NAME_TO_NUMBER.keys())
_WEEKDAY_NAME_PATTERN = "|".join(_WEEKDAY_NAMES_TO_INDEX.keys())


def _month_bounds(year: int, month: int) -> tuple[str, str]:
    first = datetime(year, month, 1)
    if month == 12:
        last = datetime(year + 1, 1, 1) - timedelta(days=1)
    else:
        last = datetime(year, month + 1, 1) - timedelta(days=1)
    return first.strftime("%Y-%m-%d"), last.strftime("%Y-%m-%d")


def _infer_month_year(month: int, explicit_year: int | None) -> int:
    if explicit_year:
        return explicit_year
    now = datetime.now()
    if month > now.month:
        return now.year - 1
    return now.year


def _week_bounds(dt: datetime) -> tuple[str, str]:
    start = dt - timedelta(days=dt.weekday())
    end = start + timedelta(days=6)
    return start.strftime("%Y-%m-%d"), end.strftime("%Y-%m-%d")


def run(args: dict) -> str:
    expr = str(args.get("expression") or "").strip().lower()
    if not expr:
        return tool_error("No expression provided")

    now = datetime.now()
    today = now.strftime("%Y-%m-%d")

    # --- Simple keywords ---
    if re.search(r"\b(vandaag|today)\b", expr):
        return tool_ok({"since": today, "until": today, "time_label": "today"})

    if re.search(r"\b(gisteren|yesterday)\b", expr):
        d = (now - timedelta(days=1)).strftime("%Y-%m-%d")
        return tool_ok({"since": d, "until": d, "time_label": "yesterday"})

    if re.search(r"\b(morgen|tomorrow)\b", expr):
        d = (now + timedelta(days=1)).strftime("%Y-%m-%d")
        return tool_ok({"since": d, "until": d, "time_label": "tomorrow"})

    if re.search(r"\b(deze week|this week)\b", expr):
        s, u = _week_bounds(now)
        return tool_ok({"since": s, "until": u, "time_label": "this_week"})

    if re.search(r"\b(vorige week|last week)\b", expr):
        last = now - timedelta(weeks=1)
        s, u = _week_bounds(last)
        return tool_ok({"since": s, "until": u, "time_label": "last_week"})

    if re.search(r"\b(deze maand|this month)\b", expr):
        s, u = _month_bounds(now.year, now.month)
        return tool_ok({"since": s, "until": u, "time_label": "this_month"})

    if re.search(r"\b(vorige maand|last month)\b", expr):
        y, m = now.year, now.month - 1
        if m == 0:
            m, y = 12, y - 1
        s, u = _month_bounds(y, m)
        return tool_ok({"since": s, "until": u, "time_label": "last_month"})

    # --- N days ago ---
    m = re.search(r"\b(\d{1,3})\s+(?:dagen|days?)\s+(?:geleden|ago)\b", expr)
    if m:
        days_back = int(m.group(1))
        d = (now - timedelta(days=days_back)).strftime("%Y-%m-%d")
        return tool_ok({"since": d, "until": d, "time_label": f"{days_back} days ago"})

    # --- N weeks ago ---
    m = re.search(r"\b(\d{1,2})\s+(?:weken|weeks?)\s+(?:geleden|ago)\b", expr)
    if m:
        weeks_back = int(m.group(1))
        target = now - timedelta(weeks=weeks_back)
        s, u = _week_bounds(target)
        return tool_ok({"since": s, "until": u, "time_label": f"{weeks_back} weeks ago"})

    # --- Weekday name (next occurrence) ---
    m = re.search(rf"\b({_WEEKDAY_NAME_PATTERN})\b", expr, re.IGNORECASE)
    if m:
        day_name = m.group(1).lower()
        target_idx = _WEEKDAY_NAMES_TO_INDEX.get(day_name)
        if target_idx is not None:
            # Past: "afgelopen dinsdag" / "last tuesday"
            is_past = bool(re.search(r"\b(afgelopen|vorige|laatste|last|past)\b", expr))
            if is_past:
                delta = (now.weekday() - target_idx) % 7
                if delta == 0:
                    delta = 7
                d = (now - timedelta(days=delta)).strftime("%Y-%m-%d")
            else:
                delta = (target_idx - now.weekday()) % 7
                if delta == 0:
                    delta = 7
                d = (now + timedelta(days=delta)).strftime("%Y-%m-%d")
            return tool_ok({"since": d, "until": d, "time_label": day_name})

    # --- Specific date: "14 maart 2026" or "14 maart" ---
    m = re.search(
        rf"\b(\d{{1,2}})\s+({_MONTH_NAME_PATTERN})(?:\s+(\d{{4}}))?\b",
        expr, re.IGNORECASE,
    )
    if m:
        day = int(m.group(1))
        month = _MONTH_NAME_TO_NUMBER.get(m.group(2).lower())
        year = int(m.group(3)) if m.group(3) else _infer_month_year(month, None)
        if month:
            try:
                d = datetime(year, month, day).strftime("%Y-%m-%d")
                return tool_ok({"since": d, "until": d, "time_label": f"{day} {m.group(2).lower()} {year}"})
            except ValueError:
                return tool_error(f"Invalid date: {day}-{month}-{year}")

    # --- Month only: "in maart", "maart 2025" ---
    m = re.search(rf"\b({_MONTH_NAME_PATTERN})(?:\s+(\d{{4}}))?\b", expr, re.IGNORECASE)
    if m:
        month = _MONTH_NAME_TO_NUMBER.get(m.group(1).lower())
        year = int(m.group(2)) if m.group(2) else _infer_month_year(month, None)
        if month:
            s, u = _month_bounds(year, month)
            return tool_ok({"since": s, "until": u, "time_label": f"{m.group(1).lower()} {year}"})

    # --- ISO date: "2026-03-14" ---
    m = re.search(r"\b(\d{4})-(\d{2})-(\d{2})\b", expr)
    if m:
        d = f"{m.group(1)}-{m.group(2)}-{m.group(3)}"
        return tool_ok({"since": d, "until": d, "time_label": d})

    return tool_error(f"Could not parse date expression: '{args.get('expression', '')}'")
