"""Background loop for daily calendar planning."""
from __future__ import annotations

import asyncio
import logging
from datetime import datetime

from dobby.models import Priority, Schedule, ScheduleType, Task

logger = logging.getLogger(__name__)


async def planner_loop(stop_event: asyncio.Event, store) -> None:
    """Background loop that generates daily plans and dispatches calendar creation.

    Checks every 5 minutes.  When the user has set ``pref:planner-enabled``
    to true and the local time passes ``pref:planner-time`` (default 07:30),
    a one-shot planning agent task is queued for the ``dobby`` project.
    """
    last_plan_date: str | None = None
    while not stop_event.is_set():
        try:
            await asyncio.sleep(300)  # 5 minutes
            if store is None:
                continue

            # Load planner preferences
            prefs_data = await store.search_memories(type="preference")
            planner_time = "07:30"
            planner_tz = "America/Los_Angeles"
            planner_enabled = False
            calendar_ids = ["primary"]

            for p in (prefs_data or []):
                key = p.get("key", "")
                val = p.get("value", "")
                if key == "pref:planner-time":
                    planner_time = val
                elif key == "pref:planner-timezone":
                    planner_tz = val
                elif key == "pref:planner-enabled":
                    planner_enabled = val.lower() in ("true", "1", "yes")
                elif key == "pref:planner-calendar-ids":
                    calendar_ids = [s.strip() for s in val.split(",")]

            if not planner_enabled:
                continue

            from zoneinfo import ZoneInfo
            tz = ZoneInfo(planner_tz)
            now_local = datetime.now(tz)
            today_str = now_local.strftime("%Y-%m-%d")

            if last_plan_date == today_str:
                continue

            plan_h, plan_m = map(int, planner_time.split(":"))
            if now_local.hour < plan_h or (now_local.hour == plan_h and now_local.minute < plan_m):
                continue

            last_plan_date = today_str
            logger.info("Planner: generating daily plan for %s", today_str)

            planner_task = Task(
                project="dobby",
                description=build_planner_prompt(today_str, planner_tz, calendar_ids),
                exit_criteria="Calendar events created and Slack briefing posted",
                priority=Priority.HIGH,
                schedule=Schedule(type=ScheduleType.ONCE),
            )
            await store.store_task(planner_task)
            logger.info("Planner: queued planning task %s", planner_task.id)

        except asyncio.CancelledError:
            return
        except Exception as exc:
            logger.warning("Planner loop error: %s", exc)


def build_planner_prompt(date: str, tz_name: str, calendar_ids: list[str]) -> str:
    """Build the prompt for the daily planning agent."""
    cal_ids_str = ", ".join(f'"{cid}"' for cid in calendar_ids)
    return f"""You are Dobby's daily planner agent. Generate today's schedule.

## Steps

1. **Read calendar**: Use the google-calendar MCP tool to list today's events.
   Query EACH of these calendar IDs: {cal_ids_str}
   Use timeMin="{date}T00:00:00" timeMax="{date}T23:59:59" timeZone="{tz_name}"
   Merge all events from all calendars into one list.

2. **Generate plan**: Call the dobby_plan_day tool with:
   - timezone="{tz_name}"
   - date="{date}"
   - calendar_events= (paste the merged JSON events from step 1)
   - The tool will return time blocks with instructions

3. **Create calendar events**: For EACH focus/break/lunch block returned:
   - Call gcal_create_event with the exact parameters shown
   - Use sendUpdates="none" to avoid notifications
   - Add description "[Dobby Planner] Auto-generated focus block"

4. **Post Slack briefing**: Use the slack MCP tool to post the plan summary
   to the user's preferred channel.

5. **Report results**: Include the plan summary and created event count in your result.
"""
