from datetime import datetime
from enum import Enum
from typing import List, Optional

from pydantic import BaseModel, Field


class LinkType(str, Enum):
    http = "http"
    ssh = "ssh"
    rdp = "rdp"
    command = "command"


class LinkEnvironment(str, Enum):
    prod = "prod"
    test = "test"
    dev = "dev"


class LinkScope(str, Enum):
    case = "case"
    customer = "customer"
    hardware = "hardware"
    global_scope = "global"


class LinkCategoryBase(BaseModel):
    name: str = Field(..., min_length=1, max_length=100)
    icon: Optional[str] = Field(default=None, max_length=100)
    sort_order: int = 100


class LinkCategoryCreate(LinkCategoryBase):
    pass


class LinkCategory(LinkCategoryBase):
    id: int
    created_at: datetime
    updated_at: datetime


class LinkBase(BaseModel):
    name: str = Field(..., min_length=1, max_length=255)
    description: Optional[str] = None
    type: LinkType
    url: Optional[str] = None
    host: Optional[str] = None
    port: Optional[int] = Field(default=None, ge=1, le=65535)
    username: Optional[str] = None
    icon: Optional[str] = None
    color: Optional[str] = None
    customer_id: Optional[int] = None
    case_id: Optional[int] = None
    hardware_id: Optional[int] = None
    vault_item_id: Optional[str] = None
    vault_item_ids: List[str] = Field(default_factory=list)
    is_critical: bool = False
    is_favorite: bool = False
    environment: LinkEnvironment = LinkEnvironment.prod


class LinkCreate(LinkBase):
    category_ids: List[int] = Field(default_factory=list)


class LinkUpdate(BaseModel):
    name: Optional[str] = Field(default=None, min_length=1, max_length=255)
    description: Optional[str] = None
    type: Optional[LinkType] = None
    url: Optional[str] = None
    host: Optional[str] = None
    port: Optional[int] = Field(default=None, ge=1, le=65535)
    username: Optional[str] = None
    icon: Optional[str] = None
    color: Optional[str] = None
    customer_id: Optional[int] = None
    case_id: Optional[int] = None
    hardware_id: Optional[int] = None
    vault_item_id: Optional[str] = None
    vault_item_ids: Optional[List[str]] = None
    is_critical: Optional[bool] = None
    is_favorite: Optional[bool] = None
    environment: Optional[LinkEnvironment] = None
    category_ids: Optional[List[int]] = None


class Link(LinkBase):
    id: int
    category_ids: List[int] = Field(default_factory=list)
    created_at: datetime
    updated_at: datetime
    deleted_at: Optional[datetime] = None


class RelevantLink(Link):
    scope: LinkScope
    scope_priority: int
    score: int
    match_count: int
    matched_tag_ids: List[int] = Field(default_factory=list)
    category_ids: List[int] = Field(default_factory=list)


class LinkActionLogCreate(BaseModel):
    action_type: str = Field(..., min_length=1, max_length=50)
    case_id: Optional[int] = None
    customer_id: Optional[int] = None
    metadata: Optional[dict] = None


class LinkActionResult(BaseModel):
    link_id: int
    action_type: str
    type: LinkType
    open_url: Optional[str] = None
    ssh_command: Optional[str] = None
    rdp_content: Optional[str] = None
    command_text: Optional[str] = None
    username: Optional[str] = None
    vault_item_id: Optional[str] = None
    vault_search_hint: Optional[str] = None


class LinkLatestStatus(BaseModel):
    link_id: int
    status: str
    checked_at: datetime
    details: dict = Field(default_factory=dict)


class VaultCredential(BaseModel):
    item_id: Optional[str] = None
    item_name: Optional[str] = None
    username: Optional[str] = None
    password: Optional[str] = None
    totp: Optional[str] = None
    notes: Optional[str] = None
    url: Optional[str] = None


class LinkVaultResolveRequest(BaseModel):
    item_id: Optional[str] = None
    search_hint: Optional[str] = None


class LinkVaultResolveResponse(BaseModel):
    status: str
    configured: bool
    message: Optional[str] = None
    checked_item_ids: List[str] = Field(default_factory=list)
    credential: Optional[VaultCredential] = None
