# #region AssistantToolMaintenance [C:3] [TYPE Module] [SEMANTICS assistant, tool, maintenance, events]
# @BRIEF Handlers for maintenance operations — list events, start maintenance, end maintenance.
# @LAYER API
# @RELATION DEPENDS_ON -> [AssistantToolRegistry]
# @RELATION DEPENDS_ON -> [MaintenanceModels]

from __future__ import annotations

from datetime import UTC, datetime
from typing import Any

from fastapi import HTTPException
from sqlalchemy.orm import Session

from src.core.config_manager import ConfigManager
from src.core.logger import belief_scope, logger
from src.core.task_manager import TaskManager
from src.schemas.auth import User
from src.models.maintenance import (
    MaintenanceEvent,
    MaintenanceEventStatus,
    MaintenanceDashboardState,
    MaintenanceDashboardStateStatus,
)

from ._schemas import AssistantAction
from ._tool_registry import _check_any_permission, assistant_tool


# #region handle_list_maintenance_events [C:2] [TYPE Function]
@assistant_tool(
    operation="list_maintenance_events",
    domain="maintenance",
    description="List active and recent maintenance events (maintenance windows) with affected tables and status",
    risk_level="safe",
    requires_confirmation=False,
    permission_checks=[("maintenance", "READ")],
)
@belief_scope("list_maintenance_events")
async def handle_list_maintenance_events(
    intent: dict[str, Any],
    current_user: User,
    task_manager: TaskManager,
    config_manager: ConfigManager,
    db: Session,
) -> tuple[str, str | None, list[AssistantAction]]:
    """List active and recent maintenance events."""
    _check_any_permission(current_user, [("maintenance", "READ")])

    # Auto-expiry: end events past their end_time
    now = datetime.now(UTC)
    expired = (
        db.query(MaintenanceEvent)
        .filter(
            MaintenanceEvent.status.in_([
                MaintenanceEventStatus.ACTIVE,
                MaintenanceEventStatus.PARTIAL,
                MaintenanceEventStatus.ENDING,
            ]),
            MaintenanceEvent.end_time.isnot(None),
            MaintenanceEvent.end_time < now,
        )
        .all()
    )
    for ev in expired:
        task = await task_manager.create_task(
            plugin_id="maintenance_banner_apply",
            params={
                "operation": "end",
                "event_id": ev.id,
                "environment_id": ev.environment_id,
                "user": "system",
            },
        )

    # Active events
    active_statuses = [
        MaintenanceEventStatus.ACTIVE,
        MaintenanceEventStatus.PARTIAL,
    ]
    active_events = (
        db.query(MaintenanceEvent)
        .filter(MaintenanceEvent.status.in_(active_statuses))
        .order_by(MaintenanceEvent.created_at.desc())
        .all()
    )

    # Completed events (last 20)
    completed_events = (
        db.query(MaintenanceEvent)
        .filter(
            MaintenanceEvent.status.in_([
                MaintenanceEventStatus.COMPLETED,
                MaintenanceEventStatus.FAILED,
            ])
        )
        .order_by(MaintenanceEvent.created_at.desc())
        .limit(20)
        .all()
    )

    lines = []

    if active_events:
        lines.append("**🟡 Активные события обслуживания:**")
        for ev in active_events:
            affected = (
                db.query(MaintenanceDashboardState)
                .filter(
                    MaintenanceDashboardState.event_id == ev.id,
                    MaintenanceDashboardState.status.in_([
                        MaintenanceDashboardStateStatus.ACTIVE,
                        MaintenanceDashboardStateStatus.PENDING_APPLY,
                    ]),
                )
                .count()
            )
            status_icon = "🟢" if ev.status == MaintenanceEventStatus.ACTIVE else "🟡"
            tables = ", ".join(ev.tables[:5]) if ev.tables else "все"
            lines.append(
                f"{status_icon} **{ev.id[:8]}** — {tables}"
                f" (дашбордов: {affected})"
            )
        lines.append("")

    if completed_events:
        lines.append("**✅ Завершённые события:**")
        for ev in completed_events:
            icon = "✅" if ev.status == MaintenanceEventStatus.COMPLETED else "❌"
            tables = ", ".join(ev.tables[:3]) if ev.tables else "все"
            lines.append(f"{icon} {ev.id[:8]} — {tables}")
        lines.append("")

    if not active_events and not completed_events:
        lines.append("Нет событий обслуживания.")

    return (
        "\n".join(lines).strip(),
        None,
        [
            AssistantAction(
                type="open_route",
                label="Открыть Maintenance",
                target="/maintenance",
            )
        ],
    )


# #endregion handle_list_maintenance_events


# #region handle_start_maintenance [C:3] [TYPE Function]
@assistant_tool(
    operation="start_maintenance",
    domain="maintenance",
    description="Start a maintenance window for specified tables with start/end time and optional message",
    required_entities=["tables", "start_time"],
    optional_entities=["end_time", "message"],
    risk_level="guarded",
    requires_confirmation=True,
    permission_checks=[("maintenance", "WRITE")],
)
@belief_scope("start_maintenance")
async def handle_start_maintenance(
    intent: dict[str, Any],
    current_user: User,
    task_manager: TaskManager,
    config_manager: ConfigManager,
    db: Session,
) -> tuple[str, str | None, list[AssistantAction]]:
    """Start a maintenance window."""
    _check_any_permission(current_user, [("maintenance", "WRITE")])
    entities = intent.get("entities", {})
    tables = entities.get("tables", [])
    start_time_str = entities.get("start_time")
    end_time_str = entities.get("end_time")
    message = entities.get("message")

    if not tables or not start_time_str:
        raise HTTPException(
            status_code=422,
            detail="Missing tables or start_time. Укажите таблицы и время начала.",
        )

    if isinstance(tables, str):
        tables = [t.strip() for t in tables.split(",")]

    # Parse times
    try:
        start_time = datetime.fromisoformat(start_time_str)
    except (ValueError, TypeError):
        raise HTTPException(
            status_code=422,
            detail="Invalid start_time format. Используйте ISO формат (YYYY-MM-DDTHH:MM).",
        )

    end_time = None
    if end_time_str:
        try:
            end_time = datetime.fromisoformat(end_time_str)
        except (ValueError, TypeError):
            raise HTTPException(
                status_code=422,
                detail="Invalid end_time format. Используйте ISO формат (YYYY-MM-DDTHH:MM).",
            )

    # Validate tables list
    if len(tables) > 100:
        raise HTTPException(status_code=422, detail="Maximum 100 tables allowed")

    # Schedule maintenance via task manager
    task = await task_manager.create_task(
        plugin_id="maintenance_banner_apply",
        params={
            "operation": "start",
            "tables": tables,
            "start_time": start_time.isoformat(),
            "end_time": end_time.isoformat() if end_time else None,
            "message": message or "",
            "user_id": current_user.id,
        },
    )

    table_list = ", ".join(tables[:5])
    if len(tables) > 5:
        table_list += f" и ещё {len(tables) - 5}"

    text = (
        f"🟡 Обслуживание запущено. task_id={task.id}\n"
        f"Таблицы: {table_list}\n"
        f"Начало: {start_time.isoformat()}"
    )
    if end_time:
        text += f"\nОкончание: {end_time.isoformat()}"
    if message:
        text += f"\nСообщение: {message}"

    return (
        text,
        task.id,
        [
            AssistantAction(type="open_task", label="Open Task", target=task.id),
            AssistantAction(
                type="open_route",
                label="Открыть Maintenance",
                target="/maintenance",
            ),
        ],
    )


# #endregion handle_start_maintenance


# #region handle_end_maintenance [C:2] [TYPE Function]
@assistant_tool(
    operation="end_maintenance",
    domain="maintenance",
    description="End a specific maintenance event by event_id or end all active maintenance events",
    optional_entities=["event_id"],
    risk_level="guarded",
    requires_confirmation=True,
    permission_checks=[("maintenance", "WRITE")],
)
@belief_scope("end_maintenance")
async def handle_end_maintenance(
    intent: dict[str, Any],
    current_user: User,
    task_manager: TaskManager,
    config_manager: ConfigManager,
    db: Session,
) -> tuple[str, str | None, list[AssistantAction]]:
    """End a specific maintenance event or all active events."""
    _check_any_permission(current_user, [("maintenance", "WRITE")])
    entities = intent.get("entities", {})
    event_id = entities.get("event_id")

    if event_id:
        # End specific event
        event = (
            db.query(MaintenanceEvent)
            .filter(MaintenanceEvent.id == event_id)
            .first()
        )
        if not event:
            raise HTTPException(
                status_code=404,
                detail=f"Событие обслуживания {event_id} не найдено.",
            )

        task = await task_manager.create_task(
            plugin_id="maintenance_banner_apply",
            params={
                "operation": "end",
                "event_id": event.id,
                "environment_id": event.environment_id,
                "user": current_user.id,
            },
        )
        return (
            f"✅ Завершение обслуживания {event_id} запущено. task_id={task.id}",
            task.id,
            [
                AssistantAction(type="open_task", label="Open Task", target=task.id),
            ],
        )

    # End all active events
    active_events = (
        db.query(MaintenanceEvent)
        .filter(
            MaintenanceEvent.status.in_([
                MaintenanceEventStatus.ACTIVE,
                MaintenanceEventStatus.PARTIAL,
            ])
        )
        .all()
    )

    if not active_events:
        return ("Нет активных событий обслуживания.", None, [])

    tasks = []
    for event in active_events:
        task = await task_manager.create_task(
            plugin_id="maintenance_banner_apply",
            params={
                "operation": "end",
                "event_id": event.id,
                "environment_id": event.environment_id,
                "user": current_user.id,
            },
        )
        tasks.append(task)

    return (
        f"✅ Завершение {len(tasks)} событий обслуживания запущено.",
        tasks[0].id if tasks else None,
        [
            AssistantAction(
                type="open_route",
                label="Открыть Maintenance",
                target="/maintenance",
            ),
        ],
    )


# #endregion handle_end_maintenance
# #endregion AssistantToolMaintenance
