# @File: backend/schemas/uptimerobot.py
# @Desc: Pydantic schemas for the UptimeRobot Reseller Manager module.
from __future__ import annotations

from datetime import datetime
from typing import List, Literal, Optional

from pydantic import BaseModel, Field


# ---------- Packages ----------
class UptimePackageBase(BaseModel):
    slug: str = Field(..., min_length=1, max_length=64)
    name: str = Field(..., min_length=1, max_length=128)
    description: Optional[str] = None

    max_monitors: int = 0
    monitors_unlimited: bool = False
    max_alert_contacts: int = 0
    alert_contacts_unlimited: bool = False
    max_maintenance_windows: int = 0
    maintenance_windows_unlimited: bool = False
    max_status_pages: int = 0
    status_pages_unlimited: bool = False

    min_check_interval: int = 300
    allowed_monitor_types: str = "http"

    public_status_page_allowed: bool = False
    api_monitoring_allowed: bool = False
    advanced_notifications_allowed: bool = False

    whmcs_product_id: Optional[int] = None
    terminate_action: Literal["archive", "delete"] = "archive"
    is_active: bool = True
    price_per_month: Optional[str] = None


class UptimePackageCreate(UptimePackageBase):
    pass


class UptimePackageUpdate(BaseModel):
    name: Optional[str] = None
    description: Optional[str] = None
    max_monitors: Optional[int] = None
    monitors_unlimited: Optional[bool] = None
    max_alert_contacts: Optional[int] = None
    alert_contacts_unlimited: Optional[bool] = None
    max_maintenance_windows: Optional[int] = None
    maintenance_windows_unlimited: Optional[bool] = None
    max_status_pages: Optional[int] = None
    status_pages_unlimited: Optional[bool] = None
    min_check_interval: Optional[int] = None
    allowed_monitor_types: Optional[str] = None
    public_status_page_allowed: Optional[bool] = None
    api_monitoring_allowed: Optional[bool] = None
    advanced_notifications_allowed: Optional[bool] = None
    whmcs_product_id: Optional[int] = None
    terminate_action: Optional[Literal["archive", "delete"]] = None
    is_active: Optional[bool] = None
    price_per_month: Optional[str] = None


class UptimePackageOut(UptimePackageBase):
    id: int
    created_at: datetime
    updated_at: datetime

    class Config:
        from_attributes = True


# ---------- Subscriptions ----------
class UptimeSubscriptionCreate(BaseModel):
    user_id: str
    user_email: Optional[str] = None
    package_id: int
    whmcs_service_id: Optional[int] = None
    whmcs_product_id: Optional[int] = None
    notes: Optional[str] = None


class UptimeSubscriptionUpdate(BaseModel):
    package_id: Optional[int] = None
    status: Optional[Literal["active", "suspended", "terminated"]] = None
    notes: Optional[str] = None


class UptimeSubscriptionOut(BaseModel):
    id: int
    user_id: str
    user_email: Optional[str] = None
    package_id: int
    package_name: Optional[str] = None
    whmcs_service_id: Optional[int] = None
    whmcs_product_id: Optional[int] = None
    status: str
    monitors_used: int
    alert_contacts_used: int
    maintenance_windows_used: int
    status_pages_used: int
    notes: Optional[str] = None
    activated_at: Optional[datetime] = None
    suspended_at: Optional[datetime] = None
    terminated_at: Optional[datetime] = None
    email_notifications_enabled: bool = False
    created_at: datetime
    updated_at: datetime

    class Config:
        from_attributes = True


# ---------- Notification preferences ----------
class UptimeNotificationPrefOut(BaseModel):
    """Email-on-status-change toggle for the current user's subscription."""

    email_notifications_enabled: bool
    notify_email: Optional[str] = None


class UptimeNotificationPrefUpdate(BaseModel):
    email_notifications_enabled: bool


# ---------- Monitors ----------
class UptimeMonitorCreate(BaseModel):
    friendly_name: str = Field(..., min_length=1, max_length=255)
    monitor_type: Literal["http", "ping", "port", "keyword", "heartbeat"]
    url: Optional[str] = None
    keyword: Optional[str] = None
    port: Optional[int] = None
    interval_seconds: int = 300


class UptimeMonitorUpdate(BaseModel):
    friendly_name: Optional[str] = None
    url: Optional[str] = None
    keyword: Optional[str] = None
    port: Optional[int] = None
    interval_seconds: Optional[int] = None


class UptimeMonitorOut(BaseModel):
    id: int
    subscription_id: int
    user_id: str
    ur_monitor_id: str
    friendly_name: str
    monitor_type: str
    url: Optional[str] = None
    keyword: Optional[str] = None
    port: Optional[int] = None
    interval_seconds: int
    status: str
    uptime_ratio_24h: Optional[str] = None
    uptime_ratio_7d: Optional[str] = None
    uptime_ratio_30d: Optional[str] = None
    response_time_ms: Optional[int] = None
    last_error: Optional[str] = None
    last_synced_at: Optional[datetime] = None
    paused: bool
    archived: bool
    created_at: datetime
    updated_at: datetime

    class Config:
        from_attributes = True


class UptimeMonitorLogEntry(BaseModel):
    event: str
    timestamp: Optional[str] = None
    duration: Optional[int] = None
    reason: Optional[str] = None


# ---------- Alert contacts ----------
class UptimeAlertContactCreate(BaseModel):
    contact_type: Literal["email", "sms", "webhook", "slack", "telegram"]
    value: str = Field(..., min_length=1, max_length=512)
    friendly_name: Optional[str] = None


class UptimeAlertContactOut(BaseModel):
    id: int
    subscription_id: int
    user_id: str
    ur_contact_id: str
    contact_type: str
    friendly_name: Optional[str] = None
    value: str
    verified: bool
    created_at: datetime
    updated_at: datetime

    class Config:
        from_attributes = True


# ---------- Maintenance windows ----------
class UptimeMaintenanceWindowCreate(BaseModel):
    friendly_name: str = Field(..., min_length=1, max_length=128)
    window_type: Literal["once", "daily", "weekly", "monthly"] = "once"
    start_time: Optional[str] = None
    duration_minutes: int = 60


class UptimeMaintenanceWindowOut(BaseModel):
    id: int
    subscription_id: int
    user_id: str
    ur_window_id: str
    friendly_name: str
    window_type: str
    start_time: Optional[str] = None
    duration_minutes: int
    status: str
    created_at: datetime
    updated_at: datetime

    class Config:
        from_attributes = True


# ---------- Status pages ----------
class UptimeStatusPageCreate(BaseModel):
    friendly_name: str = Field(..., min_length=1, max_length=128)
    custom_url: Optional[str] = None
    monitor_ids: List[str] = Field(default_factory=list)


class UptimeStatusPageOut(BaseModel):
    id: int
    subscription_id: int
    user_id: str
    ur_page_id: str
    friendly_name: str
    standard_url: Optional[str] = None
    custom_url: Optional[str] = None
    monitor_ids: List[str] = Field(default_factory=list)
    created_at: datetime
    updated_at: datetime

    class Config:
        from_attributes = True


# ---------- API settings / team usage ----------
class UptimeApiSettingsOut(BaseModel):
    api_key_present: bool
    api_key_masked: Optional[str] = None
    api_key_source: Literal["db", "env", "none"]
    last_sync_at: Optional[datetime] = None
    last_error_at: Optional[datetime] = None
    last_error_class: Optional[str] = None
    last_error_message: Optional[str] = None


class UptimeApiTestResult(BaseModel):
    ok: bool
    http_status: Optional[int] = None
    error_class: Optional[str] = None
    error_message: Optional[str] = None
    plan_name: Optional[str] = None


class UptimeUsageMeter(BaseModel):
    used: int
    total: Optional[int] = None
    percent: Optional[int] = None
    unlimited: bool = False


class UptimeTeamUsageOut(BaseModel):
    monitors: UptimeUsageMeter
    alert_contacts: UptimeUsageMeter
    status_pages: UptimeUsageMeter
    maintenance_windows: UptimeUsageMeter
    plan_name: Optional[str] = None
    warning_state: Literal["ok", "warn_70", "warn_85", "critical_95", "upgrade_required"]
    warning_label: str
    snapshot_at: Optional[datetime] = None


class UptimeSyncResult(BaseModel):
    ok: bool
    monitors_synced: int = 0
    contacts_synced: int = 0
    windows_synced: int = 0
    pages_synced: int = 0
    snapshot_id: Optional[int] = None
    error: Optional[str] = None


# ---------- API logs ----------
class UptimeApiLogItem(BaseModel):
    id: int
    endpoint: str
    method: str
    status: str
    error_class: Optional[str] = None
    http_status: Optional[int] = None
    duration_ms: Optional[int] = None
    user_email: Optional[str] = None
    error_message: Optional[str] = None
    created_at: datetime

    class Config:
        from_attributes = True


class UptimeApiLogListResponse(BaseModel):
    items: List[UptimeApiLogItem]
    total: int


# ---------- Client dashboard ----------
class UptimeClientDashboardOut(BaseModel):
    subscription: Optional[UptimeSubscriptionOut] = None
    package: Optional[UptimePackageOut] = None
    quota_monitors: UptimeUsageMeter
    quota_alert_contacts: UptimeUsageMeter
    quota_maintenance_windows: UptimeUsageMeter
    quota_status_pages: UptimeUsageMeter