"""
Service model for applications running on infrastructure.

Services represent applications, databases, web servers, and other software
running on infrastructure components.
"""

from typing import TYPE_CHECKING, Optional

from sqlalchemy import CHAR, CheckConstraint, ForeignKey, Index, Integer, String, Text
from sqlalchemy.orm import Mapped, mapped_column, relationship

from .base import Base, TimestampMixin, UUIDMixin

if TYPE_CHECKING:
    from .deployment import Deployment


class Service(Base, UUIDMixin, TimestampMixin):
    """
    Service model representing applications running on infrastructure.

    Tracks applications, services, databases, web servers, and other software
    components running on infrastructure with URLs, ports, and status.

    Attributes:
        infrastructure_id: Reference to the infrastructure hosting this service
        service_name: Name of the service (e.g., "Gitea", "PostgreSQL")
        service_type: Type of service (e.g., "git_hosting", "database")
        external_url: External URL for accessing the service
        internal_url: Internal URL for accessing the service
        port: Port number the service runs on
        protocol: Protocol used (https, ssh, smb, etc.)
        status: Current status (running, stopped, error, maintenance)
        version: Version of the service
        notes: Additional notes
    """

    __tablename__ = "services"

    # Foreign keys
    infrastructure_id: Mapped[Optional[str]] = mapped_column(
        CHAR(36),
        ForeignKey("infrastructure.id", ondelete="CASCADE"),
        doc="Reference to the infrastructure hosting this service"
    )

    # Service identification
    service_name: Mapped[str] = mapped_column(
        String(255),
        nullable=False,
        doc="Name of the service (e.g., 'Gitea', 'PostgreSQL', 'Apache')"
    )

    service_type: Mapped[Optional[str]] = mapped_column(
        String(100),
        doc="Type of service (e.g., 'git_hosting', 'database', 'web_server')"
    )

    # URLs and connectivity
    external_url: Mapped[Optional[str]] = mapped_column(
        String(500),
        doc="External URL for accessing the service"
    )

    internal_url: Mapped[Optional[str]] = mapped_column(
        String(500),
        doc="Internal URL for accessing the service"
    )

    port: Mapped[Optional[int]] = mapped_column(
        Integer,
        doc="Port number the service runs on"
    )

    protocol: Mapped[Optional[str]] = mapped_column(
        String(50),
        doc="Protocol used (https, ssh, smb, etc.)"
    )

    # Status
    status: Mapped[str] = mapped_column(
        String(50),
        default="running",
        server_default="running",
        nullable=False,
        doc="Status: running, stopped, error, maintenance"
    )

    # Version
    version: Mapped[Optional[str]] = mapped_column(
        String(100),
        doc="Version of the service"
    )

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

    # Relationships
    deployments: Mapped[list["Deployment"]] = relationship(
        "Deployment",
        back_populates="service",
        doc="Relationship to Deployment model"
    )

    # Constraints and indexes
    __table_args__ = (
        CheckConstraint(
            "status IN ('running', 'stopped', 'error', 'maintenance')",
            name="ck_services_status"
        ),
        Index("idx_services_infrastructure", "infrastructure_id"),
        Index("idx_services_name", "service_name"),
        Index("idx_services_type", "service_type"),
    )

    def __repr__(self) -> str:
        """String representation of the service."""
        return f"<Service(service_name='{self.service_name}', status='{self.status}')>"
