"""
Session model for work sessions with time tracking.

Tracks individual work sessions including client, project, machine used,
time tracking, and session documentation.
"""

from datetime import date, datetime
from typing import TYPE_CHECKING, Optional

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

from .base import Base, TimestampMixin, UUIDMixin

if TYPE_CHECKING:
    from .client import Client
    from .database_change import DatabaseChange
    from .deployment import Deployment
    from .infrastructure_change import InfrastructureChange
    from .machine import Machine
    from .operation_failure import OperationFailure
    from .project import Project
    from .work_item import WorkItem


class Session(Base, UUIDMixin, TimestampMixin):
    """
    Session model representing work sessions with time tracking.

    Tracks individual work sessions including which client, project, and machine
    were involved, along with timing information, billability, and session documentation.
    Enhanced with machine tracking to understand which machine was used for the work.

    Attributes:
        client_id: Foreign key to clients table
        project_id: Foreign key to projects table
        machine_id: Foreign key to machines table (which machine was used)
        session_date: Date of the session
        start_time: Session start timestamp
        end_time: Session end timestamp
        duration_minutes: Duration in minutes (auto-calculated or manual)
        status: Session status (completed, in_progress, blocked, pending)
        session_title: Brief title describing the session
        summary: Markdown summary of the session
        is_billable: Whether this session is billable
        billable_hours: Billable hours if applicable
        technician: Name of technician who performed the work
        session_log_file: Path to markdown session log file
        notes: Additional notes about the session
        client: Relationship to Client model
        project: Relationship to Project model
        machine: Relationship to Machine model
    """

    __tablename__ = "sessions"

    # Foreign keys
    client_id: Mapped[Optional[str]] = mapped_column(
        String(36),
        ForeignKey("clients.id", ondelete="SET NULL"),
        doc="Foreign key to clients table"
    )

    project_id: Mapped[Optional[str]] = mapped_column(
        String(36),
        ForeignKey("projects.id", ondelete="SET NULL"),
        doc="Foreign key to projects table"
    )

    machine_id: Mapped[Optional[str]] = mapped_column(
        String(36),
        ForeignKey("machines.id", ondelete="SET NULL"),
        doc="Foreign key to machines table (which machine was used)"
    )

    # Session timing
    session_date: Mapped[date] = mapped_column(
        DATE,
        nullable=False,
        doc="Date of the session"
    )

    start_time: Mapped[Optional[datetime]] = mapped_column(
        TIMESTAMP,
        doc="Session start timestamp"
    )

    end_time: Mapped[Optional[datetime]] = mapped_column(
        TIMESTAMP,
        doc="Session end timestamp"
    )

    duration_minutes: Mapped[Optional[int]] = mapped_column(
        Integer,
        doc="Duration in minutes (auto-calculated or manual)"
    )

    # Status
    status: Mapped[str] = mapped_column(
        String(50),
        default="completed",
        server_default="completed",
        doc="Session status: completed, in_progress, blocked, pending"
    )

    # Session details
    session_title: Mapped[str] = mapped_column(
        String(500),
        nullable=False,
        doc="Brief title describing the session"
    )

    summary: Mapped[Optional[str]] = mapped_column(
        Text,
        doc="Markdown summary of the session"
    )

    # Billability
    is_billable: Mapped[bool] = mapped_column(
        Boolean,
        default=False,
        server_default="0",
        doc="Whether this session is billable"
    )

    billable_hours: Mapped[Optional[float]] = mapped_column(
        Numeric(10, 2),
        doc="Billable hours if applicable"
    )

    # Technician
    technician: Mapped[Optional[str]] = mapped_column(
        String(255),
        doc="Name of technician who performed the work"
    )

    # Documentation
    session_log_file: Mapped[Optional[str]] = mapped_column(
        String(500),
        doc="Path to markdown session log file"
    )

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

    # Relationships
    client: Mapped[Optional["Client"]] = relationship(
        "Client",
        back_populates="sessions",
        doc="Relationship to Client model"
    )

    project: Mapped[Optional["Project"]] = relationship(
        "Project",
        back_populates="sessions",
        doc="Relationship to Project model"
    )

    machine: Mapped[Optional["Machine"]] = relationship(
        "Machine",
        back_populates="sessions",
        doc="Relationship to Machine model"
    )

    work_items: Mapped[list["WorkItem"]] = relationship(
        "WorkItem",
        back_populates="session",
        cascade="all, delete-orphan",
        doc="Relationship to WorkItem model"
    )

    operation_failures: Mapped[list["OperationFailure"]] = relationship(
        "OperationFailure",
        back_populates="session",
        cascade="all, delete-orphan",
        doc="Relationship to OperationFailure model"
    )

    deployments: Mapped[list["Deployment"]] = relationship(
        "Deployment",
        back_populates="session",
        cascade="all, delete-orphan",
        doc="Relationship to Deployment model"
    )

    database_changes: Mapped[list["DatabaseChange"]] = relationship(
        "DatabaseChange",
        back_populates="session",
        cascade="all, delete-orphan",
        doc="Relationship to DatabaseChange model"
    )

    infrastructure_changes: Mapped[list["InfrastructureChange"]] = relationship(
        "InfrastructureChange",
        back_populates="session",
        cascade="all, delete-orphan",
        doc="Relationship to InfrastructureChange model"
    )

    # Indexes
    __table_args__ = (
        Index("idx_sessions_client", "client_id"),
        Index("idx_sessions_project", "project_id"),
        Index("idx_sessions_date", "session_date"),
        Index("idx_sessions_billable", "is_billable"),
        Index("idx_sessions_machine", "machine_id"),
    )

    def __repr__(self) -> str:
        """String representation of the session."""
        return f"<Session(title='{self.session_title}', date='{self.session_date}', status='{self.status}')>"
