"""All Pydantic v2 models mirroring the Appliku OpenAPI schemas."""

from __future__ import annotations

from typing import Generic, TypeVar

from pydantic import BaseModel, Field

T = TypeVar("T")


# ---------------------------------------------------------------------------
# Pagination
# ---------------------------------------------------------------------------


class PaginatedResponse(BaseModel, Generic[T]):
    count: int
    next: str | None = None
    previous: str | None = None
    results: list[T]


# ---------------------------------------------------------------------------
# Auth
# ---------------------------------------------------------------------------


class LoginRequest(BaseModel):
    email: str
    password: str
    name: str | None = None
    opt_in: bool = True


class LoginResponse(BaseModel):
    access: str
    refresh: str


class ApiKeyResponse(BaseModel):
    api_key: str


class UserInfo(BaseModel):
    email: str
    name: str | None = None


# ---------------------------------------------------------------------------
# Teams
# ---------------------------------------------------------------------------


class TeamCreate(BaseModel):
    team_path: str
    name: str


class TeamUpdate(BaseModel):
    name: str | None = None


class Team(BaseModel):
    id: int
    team_path: str
    name: str
    plan: str | None = None
    aws_credentials_set: bool = False
    do_token_set: bool = False


# ---------------------------------------------------------------------------
# Apps
# ---------------------------------------------------------------------------


class AppCreate(BaseModel):
    name: str
    branch: str
    repo_provider: str | None = None
    repo_name: str | None = None
    git_url: str | None = None
    build_pack: str | None = None
    server_id: int | None = None
    cluster_id: int | None = None


class AppUpdate(BaseModel):
    name: str | None = None
    branch: str | None = None
    repo_provider: str | None = None
    repo_name: str | None = None
    git_url: str | None = None
    build_pack: str | None = None
    server_id: int | None = None
    cluster_id: int | None = None


class App(BaseModel):
    id: int
    name: str
    branch: str
    repo_provider: str | None = None
    status: str | None = None
    build_pack: str | None = None
    server_id: int | None = None
    cluster_id: int | None = None


class ConfigVarsResponse(BaseModel):
    vars: dict[str, str]


# ---------------------------------------------------------------------------
# Deployments
# ---------------------------------------------------------------------------


class Deployment(BaseModel):
    id: int
    app_id: int
    app_name: str
    status: str
    stage: str | None = None
    git_commit: str | None = None
    branch: str | None = None
    error_msg: str | None = None
    is_active: bool = False
    is_aborted: bool = False


class LogEntry(BaseModel):
    id: int
    message: str
    timestamp: str | None = None


class AppLogsRequest(BaseModel):
    process: str
    tail: int = 100


class NginxLogsRequest(BaseModel):
    domain: str
    tail: int = 100


class LogsRequestResponse(BaseModel):
    request_id: float
    tail: int | None = None


class AdvancedLogsResponse(BaseModel):
    id: int
    logs: str | None = None
    request_id: float
    status: str | None = None


class NginxLogsResponse(BaseModel):
    id: int
    logs: str | None = None
    request_id: float


class ServiceLogsResponse(BaseModel):
    id: int
    logs: str


class DatastoreLogsResponse(BaseModel):
    id: int
    logs: str


# ---------------------------------------------------------------------------
# Datastores
# ---------------------------------------------------------------------------


class DatastoreCreate(BaseModel):
    name: str
    engine: str
    version: str | None = None
    app_id: int | None = None


class Datastore(BaseModel):
    id: int
    name: str
    engine: str
    version: str | None = None
    is_primary: bool = False
    status: str | None = None


# ---------------------------------------------------------------------------
# Domains
# ---------------------------------------------------------------------------


class DomainCreate(BaseModel):
    domain: str


class Domain(BaseModel):
    id: int
    domain: str
    deployment_status: str | None = None


# ---------------------------------------------------------------------------
# Volumes
# ---------------------------------------------------------------------------


class VolumeCreate(BaseModel):
    name: str
    container_path: str
    environment_variable: str | None = None


class VolumeUpdate(BaseModel):
    name: str | None = None
    container_path: str | None = None
    environment_variable: str | None = None


class Volume(BaseModel):
    id: int
    name: str
    container_path: str
    url: str | None = None
    environment_variable: str | None = None


# ---------------------------------------------------------------------------
# CronJobs
# ---------------------------------------------------------------------------


class CronJobCreate(BaseModel):
    name: str
    schedule: str
    command: str


class CronJobUpdate(BaseModel):
    name: str | None = None
    schedule: str | None = None
    command: str | None = None
    is_disabled: bool | None = None


class CronJob(BaseModel):
    id: int
    name: str
    schedule: str
    command: str
    is_disabled: bool = False


# ---------------------------------------------------------------------------
# Clusters
# ---------------------------------------------------------------------------


class ClusterCreate(BaseModel):
    name: str


class Cluster(BaseModel):
    id: int
    name: str
    apps_count: int | None = None
    domains_count: int | None = None


# ---------------------------------------------------------------------------
# Servers
# ---------------------------------------------------------------------------


class Server(BaseModel):
    id: int
    name: str = Field(alias="server_name")
    provider: str | None = None
    region: str | None = None
    status: str | None = None
    ip_address: str | None = None
    uptime: str | None = None
    cpu_info: float | None = None  # CPU usage %
    requires_restart: bool | None = None
    memory_info: str | None = None  # JSON string with mem/swap info
    disk_info: str | None = None  # JSON string with disk usage info

    model_config = {"populate_by_name": True}


class ServerCreateDO(BaseModel):
    name: str
    region: str
    size: str
    image: str | None = None


class ServerCreateEC2(BaseModel):
    name: str
    region: str
    instance_type: str
    ami: str | None = None


class ServerCreateCustom(BaseModel):
    name: str
    host: str
    ssh_port: int = 22
    ssh_username: str | None = None
    ssh_key_name: str | None = None


# ---------------------------------------------------------------------------
# Invites
# ---------------------------------------------------------------------------


class InviteCreate(BaseModel):
    email: str
    role: str = "member"


class Invite(BaseModel):
    id: int
    email: str
    role: str | None = None
    status: str | None = None
    created_at: str | None = None


# ---------------------------------------------------------------------------
# Database Migrations
# ---------------------------------------------------------------------------


class MigrationRun(BaseModel):
    application_id: int
    command: str


class Migration(BaseModel):
    id: int
    command: str
    status: str | None = None
    created_at: str | None = None
    completed_at: str | None = None
