"""SQLAlchemy model for the tests table."""

# Import uuid
import uuid

# Import  from sqlalchemy
from sqlalchemy import (
    Boolean,
    Column,
    DateTime,
    Enum,
    ForeignKey,
    Index,
    Integer,
    String,
    Text,
    func,
)

# Import UUID from sqlalchemy.dialects.postgresql
from sqlalchemy.dialects.postgresql import UUID

# Import relationship from sqlalchemy.orm
from sqlalchemy.orm import relationship

# Import Base from app.database
from app.database import Base

# Import ContainmentResult, TestResult, TestState from app.models.enums
from app.models.enums import AttackSuccessResult, ContainmentResult, TestResult, TestState


# Define class Test
class Test(Base):
    """Test model representing a security test for a MITRE ATT&CK technique.

    Each test documents an attempt to validate coverage of a specific technique,
    including the procedure, tools used, and outcome.  V2 introduces dual
    validation: Red Lead and Blue Lead must each approve independently.
    """
    # Assign __tablename__ = "tests"
    __tablename__ = "tests"

    # ── Core fields ─────────────────────────────────────────────────
    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    # Assign technique_id = Column(UUID(as_uuid=True), ForeignKey("techniques.id"), nullable=Fa...
    technique_id = Column(UUID(as_uuid=True), ForeignKey("techniques.id"), nullable=False)
    # Assign name = Column(String, nullable=False)
    name = Column(String, nullable=False)
    # Assign description = Column(Text, nullable=True)
    description = Column(Text, nullable=True)
    # Assign platform = Column(String, nullable=True)
    platform = Column(String, nullable=True)
    # Assign procedure_text = Column(Text, nullable=True)
    procedure_text = Column(Text, nullable=True)
    # Assign tool_used = Column(String, nullable=True)
    tool_used = Column(String, nullable=True)
    # Assign execution_date = Column(DateTime, nullable=True)
    execution_date = Column(DateTime, nullable=True)
    # Assign created_by = Column(UUID(as_uuid=True), ForeignKey("users.id"), nullable=True)
    created_by = Column(UUID(as_uuid=True), ForeignKey("users.id"), nullable=True)
    # Assign result = Column(Enum(TestResult, name="testresult"), nullable=True)
    result = Column(Enum(TestResult, name="testresult"), nullable=True)
    # Assign state = Column(Enum(TestState, name="teststate"), default=TestState.draft)
    state = Column(Enum(TestState, name="teststate"), default=TestState.draft)
    # Assign created_at = Column(DateTime(timezone=True), server_default=func.now())
    created_at = Column(DateTime(timezone=True), server_default=func.now())

    # ── Red Team fields ─────────────────────────────────────────────
    red_summary = Column(Text, nullable=True)
    # Assign attack_success = Column(Boolean, nullable=True)
    attack_success = Column(Enum(AttackSuccessResult, name="attacksuccessresult"), nullable=True)
    execution_start_time = Column(DateTime, nullable=True)
    execution_end_time = Column(DateTime, nullable=True)
    # Assign red_validated_by = Column(UUID(as_uuid=True), ForeignKey("users.id"), nullable=True)
    red_validated_by = Column(UUID(as_uuid=True), ForeignKey("users.id"), nullable=True)
    # Assign red_validated_at = Column(DateTime, nullable=True)
    red_validated_at = Column(DateTime, nullable=True)
    # Assign red_validation_status = Column(String, nullable=True)   # pending / approved / rejected
    red_validation_status = Column(String, nullable=True)   # pending / approved / rejected
    # Assign red_validation_notes = Column(Text, nullable=True)
    red_validation_notes = Column(Text, nullable=True)

    # ── Blue Team fields ────────────────────────────────────────────
    blue_summary = Column(Text, nullable=True)
    # Assign detection_result = Column(Enum(TestResult, name="testresult"), nullable=True)
    detection_result = Column(Enum(TestResult, name="testresult"), nullable=True)
    containment_result = Column(Enum(ContainmentResult, name="containmentresult"), nullable=True)
    detection_time = Column(DateTime, nullable=True)
    containment_time = Column(DateTime, nullable=True)
    # Assign blue_validated_by = Column(UUID(as_uuid=True), ForeignKey("users.id"), nullable=True)
    blue_validated_by = Column(UUID(as_uuid=True), ForeignKey("users.id"), nullable=True)
    # Assign blue_validated_at = Column(DateTime, nullable=True)
    blue_validated_at = Column(DateTime, nullable=True)
    # Assign blue_validation_status = Column(String, nullable=True)  # pending / approved / rejected
    blue_validation_status = Column(String, nullable=True)  # pending / approved / rejected
    # Assign blue_validation_notes = Column(Text, nullable=True)
    blue_validation_notes = Column(Text, nullable=True)

    # ── Phase timing fields (for automatic Tempo worklogs) ──────────
    red_started_at = Column(DateTime, nullable=True)
    # Assign blue_started_at = Column(DateTime, nullable=True)
    blue_started_at = Column(DateTime, nullable=True)
    blue_work_started_at = Column(DateTime, nullable=True)  # when blue tech picks up (Tempo start)
    paused_at = Column(DateTime, nullable=True)
    # Assign red_paused_seconds = Column(Integer, default=0)
    red_paused_seconds = Column(Integer, default=0)
    # Assign blue_paused_seconds = Column(Integer, default=0)
    blue_paused_seconds = Column(Integer, default=0)

    # ── Remediation fields ───────────────────────────────────────────
    remediation_steps = Column(Text, nullable=True)
    # Assign remediation_status = Column(String, nullable=True)  # pending / in_progress / completed ...
    remediation_status = Column(String, nullable=True)  # pending / in_progress / completed / not_applicable
    # Assign remediation_assignee = Column(UUID(as_uuid=True), ForeignKey("users.id"), nullable=True)
    remediation_assignee = Column(UUID(as_uuid=True), ForeignKey("users.id"), nullable=True)

    # ── Re-test fields ────────────────────────────────────────────
    retest_of = Column(UUID(as_uuid=True), ForeignKey("tests.id"), nullable=True)
    # Assign retest_count = Column(Integer, default=0)
    retest_count = Column(Integer, default=0)
    # Assign data_classification = Column(String(20), nullable=False, server_default="internal")
    data_classification = Column(String(20), nullable=False, server_default="confidential")

    # ── Relationships ───────────────────────────────────────────────
    technique = relationship("Technique", back_populates="tests")
    # Assign evidences = relationship("Evidence", back_populates="test")
    evidences = relationship("Evidence", back_populates="test")
    # Assign creator = relationship("User", foreign_keys=[created_by])
    creator = relationship("User", foreign_keys=[created_by])
    # Assign red_validator = relationship("User", foreign_keys=[red_validated_by])
    red_validator = relationship("User", foreign_keys=[red_validated_by])
    # Assign blue_validator = relationship("User", foreign_keys=[blue_validated_by])
    blue_validator = relationship("User", foreign_keys=[blue_validated_by])
    # Assign remediation_user = relationship("User", foreign_keys=[remediation_assignee])
    remediation_user = relationship("User", foreign_keys=[remediation_assignee])

    # ── Assignment fields ──────────────────────────────────────────
    red_tech_assignee = Column(UUID(as_uuid=True), ForeignKey("users.id"), nullable=True)
    blue_tech_assignee = Column(UUID(as_uuid=True), ForeignKey("users.id"), nullable=True)

    # ── Review assignment fields ────────────────────────────────────
    red_reviewer_assignee = Column(UUID(as_uuid=True), ForeignKey("users.id"), nullable=True)
    red_review_by = Column(UUID(as_uuid=True), ForeignKey("users.id"), nullable=True)
    red_review_at = Column(DateTime, nullable=True)
    red_review_notes = Column(Text, nullable=True)

    blue_reviewer_assignee = Column(UUID(as_uuid=True), ForeignKey("users.id"), nullable=True)
    blue_review_by = Column(UUID(as_uuid=True), ForeignKey("users.id"), nullable=True)
    blue_review_at = Column(DateTime, nullable=True)
    blue_review_notes = Column(Text, nullable=True)
    system_gaps = Column(Text, nullable=True)

    # ── On-hold fields ─────────────────────────────────────────────
    is_on_hold = Column(Boolean, default=False, nullable=False, server_default="false")
    hold_reason = Column(Text, nullable=True)
    held_at = Column(DateTime, nullable=True)

    red_tech_assigned_user = relationship("User", foreign_keys=[red_tech_assignee])
    blue_tech_assigned_user = relationship("User", foreign_keys=[blue_tech_assignee])

    red_reviewer = relationship("User", foreign_keys=[red_reviewer_assignee])
    red_review_actor = relationship("User", foreign_keys=[red_review_by])
    blue_reviewer = relationship("User", foreign_keys=[blue_reviewer_assignee])
    blue_review_actor = relationship("User", foreign_keys=[blue_review_by])

    # Assign original_test = relationship("Test", remote_side="Test.id", foreign_keys=[retest_of])
    original_test = relationship("Test", remote_side="Test.id", foreign_keys=[retest_of])
    # Assign retests = relationship("Test", foreign_keys=[retest_of], back_populates="orig...
    retests = relationship("Test", foreign_keys=[retest_of], back_populates="original_test")

    # Assign __table_args__ = (
    __table_args__ = (
        Index("ix_tests_technique_id", "technique_id"),
        Index("ix_tests_state", "state"),
        Index("ix_tests_created_at", "created_at"),
        Index("ix_tests_technique_state", "technique_id", "state"),
        Index("ix_tests_state_created_at", "state", "created_at"),
    )
