"""
Machine model for technician's machines used for MSP work.

Tracks laptops, desktops, and workstations with their capabilities,
installed tools, MCP servers, and skills.
"""

from datetime import datetime
from typing import TYPE_CHECKING, Optional

from sqlalchemy import Boolean, Index, Integer, String, Text, TIMESTAMP
from sqlalchemy.orm import Mapped, mapped_column, relationship

from .base import Base, TimestampMixin, UUIDMixin

if TYPE_CHECKING:
    from .session import Session


class Machine(Base, UUIDMixin, TimestampMixin):
    """
    Machine model representing technician's machines used for MSP work.

    Tracks machine identification, capabilities, installed tools, MCP servers,
    skills, and network context. Machines are auto-detected on session start
    using hostname, username, platform, and home directory.

    Attributes:
        hostname: Machine hostname from `hostname` command
        machine_fingerprint: SHA256 hash of hostname + username + platform + home_directory
        friendly_name: Human-readable name like "Main Laptop" or "Home Desktop"
        machine_type: Type of machine (laptop, desktop, workstation, vm)
        platform: Operating system platform (win32, darwin, linux)
        os_version: Operating system version
        username: Username from `whoami` command
        home_directory: User home directory path
        has_vpn_access: Whether machine can connect to client networks
        vpn_profiles: JSON array of available VPN profiles
        has_docker: Whether Docker is installed
        has_powershell: Whether PowerShell is installed
        powershell_version: PowerShell version if installed
        has_ssh: Whether SSH is available
        has_git: Whether Git is installed
        typical_network_location: Typical network location (home, office, mobile)
        static_ip: Static IP address if applicable
        claude_working_directory: Primary working directory for Claude Code
        additional_working_dirs: JSON array of additional working directories
        installed_tools: JSON object with tool versions
        available_mcps: JSON array of available MCP servers
        mcp_capabilities: JSON object with MCP capabilities
        available_skills: JSON array of available skills
        skill_paths: JSON object mapping skill names to paths
        preferred_shell: Preferred shell (powershell, bash, zsh, cmd)
        package_manager_commands: JSON object with package manager commands
        is_primary: Whether this is the primary machine
        is_active: Whether machine is active
        last_seen: Last time machine was seen
        last_session_id: UUID of last session from this machine
        notes: Additional notes about the machine
    """

    __tablename__ = "machines"

    # Machine identification (auto-detected)
    hostname: Mapped[str] = mapped_column(
        String(255),
        nullable=False,
        unique=True,
        doc="Machine hostname from `hostname` command"
    )

    machine_fingerprint: Mapped[Optional[str]] = mapped_column(
        String(500),
        unique=True,
        doc="SHA256 hash: hostname + username + platform + home_directory"
    )

    # Environment details
    friendly_name: Mapped[Optional[str]] = mapped_column(
        String(255),
        doc="Human-readable name like 'Main Laptop' or 'Home Desktop'"
    )

    machine_type: Mapped[Optional[str]] = mapped_column(
        String(50),
        doc="Type of machine: laptop, desktop, workstation, vm"
    )

    platform: Mapped[Optional[str]] = mapped_column(
        String(50),
        doc="Operating system platform: win32, darwin, linux"
    )

    os_version: Mapped[Optional[str]] = mapped_column(
        String(100),
        doc="Operating system version"
    )

    username: Mapped[Optional[str]] = mapped_column(
        String(255),
        doc="Username from `whoami` command"
    )

    home_directory: Mapped[Optional[str]] = mapped_column(
        String(500),
        doc="User home directory path"
    )

    # Capabilities
    has_vpn_access: Mapped[bool] = mapped_column(
        Boolean,
        default=False,
        server_default="0",
        doc="Whether machine can connect to client networks"
    )

    vpn_profiles: Mapped[Optional[str]] = mapped_column(
        Text,
        doc="JSON array of available VPN profiles"
    )

    has_docker: Mapped[bool] = mapped_column(
        Boolean,
        default=False,
        server_default="0",
        doc="Whether Docker is installed"
    )

    has_powershell: Mapped[bool] = mapped_column(
        Boolean,
        default=False,
        server_default="0",
        doc="Whether PowerShell is installed"
    )

    powershell_version: Mapped[Optional[str]] = mapped_column(
        String(20),
        doc="PowerShell version if installed"
    )

    has_ssh: Mapped[bool] = mapped_column(
        Boolean,
        default=True,
        server_default="1",
        doc="Whether SSH is available"
    )

    has_git: Mapped[bool] = mapped_column(
        Boolean,
        default=True,
        server_default="1",
        doc="Whether Git is installed"
    )

    # Network context
    typical_network_location: Mapped[Optional[str]] = mapped_column(
        String(100),
        doc="Typical network location: home, office, mobile"
    )

    static_ip: Mapped[Optional[str]] = mapped_column(
        String(45),
        doc="Static IP address if applicable (supports IPv4/IPv6)"
    )

    # Claude Code context
    claude_working_directory: Mapped[Optional[str]] = mapped_column(
        String(500),
        doc="Primary working directory for Claude Code"
    )

    additional_working_dirs: Mapped[Optional[str]] = mapped_column(
        Text,
        doc="JSON array of additional working directories"
    )

    # Tool versions
    installed_tools: Mapped[Optional[str]] = mapped_column(
        Text,
        doc="JSON object with tool versions like {\"git\": \"2.40\", \"docker\": \"24.0\"}"
    )

    # MCP Servers & Skills
    available_mcps: Mapped[Optional[str]] = mapped_column(
        Text,
        doc="JSON array of available MCP servers"
    )

    mcp_capabilities: Mapped[Optional[str]] = mapped_column(
        Text,
        doc="JSON object with MCP capabilities"
    )

    available_skills: Mapped[Optional[str]] = mapped_column(
        Text,
        doc="JSON array of available skills"
    )

    skill_paths: Mapped[Optional[str]] = mapped_column(
        Text,
        doc="JSON object mapping skill names to paths"
    )

    # OS-Specific Commands
    preferred_shell: Mapped[Optional[str]] = mapped_column(
        String(50),
        doc="Preferred shell: powershell, bash, zsh, cmd"
    )

    package_manager_commands: Mapped[Optional[str]] = mapped_column(
        Text,
        doc="JSON object with package manager commands"
    )

    # Status
    is_primary: Mapped[bool] = mapped_column(
        Boolean,
        default=False,
        server_default="0",
        doc="Whether this is the primary machine"
    )

    is_active: Mapped[bool] = mapped_column(
        Boolean,
        default=True,
        server_default="1",
        doc="Whether machine is currently active"
    )

    last_seen: Mapped[Optional[datetime]] = mapped_column(
        TIMESTAMP,
        doc="Last time machine was seen"
    )

    last_session_id: Mapped[Optional[str]] = mapped_column(
        String(36),
        doc="UUID of last session from this machine"
    )

    # Notes
    notes: Mapped[Optional[str]] = mapped_column(
        Text,
        doc="Additional notes about the machine"
    )

    # Relationships
    sessions: Mapped[list["Session"]] = relationship(
        "Session",
        back_populates="machine",
        doc="Sessions associated with this machine"
    )

    # Indexes
    __table_args__ = (
        Index("idx_machines_hostname", "hostname"),
        Index("idx_machines_fingerprint", "machine_fingerprint"),
        Index("idx_machines_is_active", "is_active"),
        Index("idx_machines_platform", "platform"),
    )

    def __repr__(self) -> str:
        """String representation of the machine."""
        return f"<Machine(hostname='{self.hostname}', friendly_name='{self.friendly_name}', platform='{self.platform}')>"
