from dataclasses import dataclass
from typing import Callable

from backend.copilot_briefing import (
    build_followup_brief_steps,
    build_morning_brief_steps,
    is_copilot_followup_goal,
    is_copilot_morning_brief_goal,
)


RoutineStepBuilder = Callable[..., list[dict]]
RoutineGoalMatcher = Callable[[str], bool]


@dataclass(frozen=True, slots=True)
class CopilotRoutineSpec:
    routine_id: str
    title: str
    planner_summary: str
    planner_examples: tuple[str, ...]
    matches_goal: RoutineGoalMatcher
    build_steps: RoutineStepBuilder


_COPILOT_ROUTINES: tuple[CopilotRoutineSpec, ...] = (
    CopilotRoutineSpec(
        routine_id="morning_brief",
        title="Co-Pilot Morning Brief",
        planner_summary=(
            "Use for a start-of-day work briefing that combines important recent email with upcoming calendar items."
        ),
        planner_examples=(
            "give me a work briefing for today from my email and calendar",
            "maak een ochtendoverzicht van mijn Outlook mail en agenda",
        ),
        matches_goal=is_copilot_morning_brief_goal,
        build_steps=build_morning_brief_steps,
    ),
    CopilotRoutineSpec(
        routine_id="follow_up",
        title="Co-Pilot Follow-up Brief",
        planner_summary=(
            "Use for a follow-up briefing focused on unresolved commitments, pending replies, and near-term obligations."
        ),
        planner_examples=(
            "which follow-ups do I still owe today from my mail and calendar",
            "geef een follow-up briefing op basis van mijn mail en agenda",
        ),
        matches_goal=is_copilot_followup_goal,
        build_steps=build_followup_brief_steps,
    ),
)


def list_copilot_routines() -> tuple[CopilotRoutineSpec, ...]:
    return _COPILOT_ROUTINES


def build_copilot_routine_planner_guide() -> str:
    lines: list[str] = []
    for routine in _COPILOT_ROUTINES:
        examples = "; ".join(f'"{example}"' for example in routine.planner_examples)
        lines.append(
            f"- {routine.routine_id}: {routine.title}. Use when: {routine.planner_summary} Example requests: {examples}."
        )
    return "\n".join(lines)


def get_matching_copilot_routine_id(goal_text: str) -> str:
    goal = str(goal_text or "").strip()
    if not goal:
        return ""
    for routine in _COPILOT_ROUTINES:
        if routine.matches_goal(goal):
            return routine.routine_id
    return ""


def is_known_copilot_routine_goal(goal_text: str) -> bool:
    return bool(get_matching_copilot_routine_id(goal_text))


def get_copilot_routine(routine_id: str) -> CopilotRoutineSpec | None:
    normalized = str(routine_id or "").strip().lower()
    if not normalized:
        return None
    for routine in _COPILOT_ROUTINES:
        if routine.routine_id == normalized:
            return routine
    return None


def resolve_copilot_routine_by_id(
    routine_id: str,
    *,
    outlook_enabled: bool,
    gmail_enabled: bool,
    outlook_folder_profiles: dict | None = None,
    google_folder_profiles: dict | None = None,
) -> dict | None:
    routine = get_copilot_routine(routine_id)
    if routine is None:
        return None
    return {
        "id": routine.routine_id,
        "title": routine.title,
        "steps": routine.build_steps(
            outlook_enabled=outlook_enabled,
            gmail_enabled=gmail_enabled,
            outlook_folder_profiles=outlook_folder_profiles,
            google_folder_profiles=google_folder_profiles,
        ),
    }


def resolve_known_copilot_routine(
    goal_text: str,
    *,
    outlook_enabled: bool,
    gmail_enabled: bool,
    outlook_folder_profiles: dict | None = None,
    google_folder_profiles: dict | None = None,
) -> dict | None:
    routine_id = get_matching_copilot_routine_id(goal_text)
    if not routine_id:
        return None
    return resolve_copilot_routine_by_id(
        routine_id,
        outlook_enabled=outlook_enabled,
        gmail_enabled=gmail_enabled,
        outlook_folder_profiles=outlook_folder_profiles,
        google_folder_profiles=google_folder_profiles,
    )