from sqlalchemy import Column, Integer, String, DateTime, Date, ForeignKey, Enum, Text
from sqlalchemy.orm import relationship, Query
from sqlalchemy.sql import func
from database import Base
import enum


class TaskType(str, enum.Enum):
    # Shot tasks
    LAYOUT = "layout"
    ANIMATION = "animation"
    SIMULATION = "simulation"
    LIGHTING = "lighting"
    COMPOSITING = "compositing"
    # Asset tasks
    MODELING = "modeling"
    SURFACING = "surfacing"
    RIGGING = "rigging"


class TaskStatus(str, enum.Enum):
    NOT_STARTED = "not_started"
    IN_PROGRESS = "in_progress"
    SUBMITTED = "submitted"
    APPROVED = "approved"
    RETAKE = "retake"


class ReviewDecision(str, enum.Enum):
    APPROVED = "approved"
    RETAKE = "retake"


class AttachmentType(str, enum.Enum):
    REFERENCE = "reference"
    WORK_FILE = "work_file"
    PREVIEW = "preview"
    DOCUMENTATION = "documentation"


class Task(Base):
    __tablename__ = "tasks"

    id = Column(Integer, primary_key=True, index=True)
    project_id = Column(Integer, ForeignKey("projects.id"), nullable=False)
    episode_id = Column(Integer, ForeignKey("episodes.id"), nullable=True)
    shot_id = Column(Integer, ForeignKey("shots.id"), nullable=True, index=True)
    asset_id = Column(Integer, ForeignKey("assets.id"), nullable=True)
    assigned_user_id = Column(Integer, ForeignKey("users.id"), nullable=True, index=True)
    task_type = Column(String, nullable=False)  # Changed from Enum to String to support custom task types
    name = Column(String, nullable=False, index=True)
    description = Column(Text)
    status = Column(String, nullable=False, default="not_started")  # Changed from Enum to String to support custom statuses
    deadline = Column(Date)
    created_at = Column(DateTime(timezone=True), server_default=func.now())
    updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
    
    # Soft deletion columns
    deleted_at = Column(DateTime(timezone=True), nullable=True, index=True)
    deleted_by = Column(Integer, ForeignKey("users.id"), nullable=True)

    # Relationships
    project = relationship("Project", back_populates="tasks")
    episode = relationship("Episode", back_populates="tasks")
    shot = relationship("Shot", back_populates="tasks")
    asset = relationship("Asset", back_populates="tasks")
    assigned_user = relationship("User", foreign_keys=[assigned_user_id], back_populates="assigned_tasks")
    submissions = relationship("Submission", back_populates="task", cascade="all, delete-orphan")
    production_notes = relationship("ProductionNote", back_populates="task", cascade="all, delete-orphan")
    attachments = relationship("TaskAttachment", back_populates="task", cascade="all, delete-orphan")
    deleted_by_user = relationship("User", foreign_keys=[deleted_by])

    @property
    def is_deleted(self) -> bool:
        """Check if the task is soft deleted."""
        return self.deleted_at is not None

    @classmethod
    def query_active(cls, query: Query) -> Query:
        """Filter query to exclude soft deleted tasks."""
        return query.filter(cls.deleted_at.is_(None))

    @classmethod
    def query_deleted(cls, query: Query) -> Query:
        """Filter query to include only soft deleted tasks."""
        return query.filter(cls.deleted_at.isnot(None))

    @classmethod
    def query_all_including_deleted(cls, query: Query) -> Query:
        """Return query without soft deletion filtering (for admin use)."""
        return query

    def __repr__(self):
        return f"<Task(id={self.id}, name='{self.name}', type='{self.task_type}', status='{self.status}')>"


class Submission(Base):
    __tablename__ = "submissions"

    id = Column(Integer, primary_key=True, index=True)
    task_id = Column(Integer, ForeignKey("tasks.id"), nullable=False)
    user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
    file_path = Column(String, nullable=False)
    file_name = Column(String, nullable=False)
    version_number = Column(Integer, nullable=False, default=1)
    notes = Column(Text)
    submitted_at = Column(DateTime(timezone=True), server_default=func.now())
    
    # Soft deletion columns
    deleted_at = Column(DateTime(timezone=True), nullable=True)
    deleted_by = Column(Integer, ForeignKey("users.id"), nullable=True)

    # Relationships
    task = relationship("Task", back_populates="submissions")
    user = relationship("User", foreign_keys=[user_id], back_populates="submissions")
    reviews = relationship("Review", back_populates="submission", cascade="all, delete-orphan")
    deleted_by_user = relationship("User", foreign_keys=[deleted_by])

    @property
    def is_deleted(self) -> bool:
        """Check if the submission is soft deleted."""
        return self.deleted_at is not None

    @classmethod
    def query_active(cls, query: Query) -> Query:
        """Filter query to exclude soft deleted submissions."""
        return query.filter(cls.deleted_at.is_(None))

    @classmethod
    def query_deleted(cls, query: Query) -> Query:
        """Filter query to include only soft deleted submissions."""
        return query.filter(cls.deleted_at.isnot(None))

    @classmethod
    def query_all_including_deleted(cls, query: Query) -> Query:
        """Return query without soft deletion filtering (for admin use)."""
        return query

    def __repr__(self):
        return f"<Submission(id={self.id}, task_id={self.task_id}, version={self.version_number})>"


class Review(Base):
    __tablename__ = "reviews"

    id = Column(Integer, primary_key=True, index=True)
    submission_id = Column(Integer, ForeignKey("submissions.id"), nullable=False)
    reviewer_id = Column(Integer, ForeignKey("users.id"), nullable=False)
    decision = Column(Enum(ReviewDecision), nullable=False)
    feedback = Column(Text)
    reviewed_at = Column(DateTime(timezone=True), server_default=func.now())
    
    # Soft deletion columns
    deleted_at = Column(DateTime(timezone=True), nullable=True)
    deleted_by = Column(Integer, ForeignKey("users.id"), nullable=True)

    # Relationships
    submission = relationship("Submission", back_populates="reviews")
    reviewer = relationship("User", foreign_keys=[reviewer_id], back_populates="reviews")
    deleted_by_user = relationship("User", foreign_keys=[deleted_by])

    @property
    def is_deleted(self) -> bool:
        """Check if the review is soft deleted."""
        return self.deleted_at is not None

    @classmethod
    def query_active(cls, query: Query) -> Query:
        """Filter query to exclude soft deleted reviews."""
        return query.filter(cls.deleted_at.is_(None))

    @classmethod
    def query_deleted(cls, query: Query) -> Query:
        """Filter query to include only soft deleted reviews."""
        return query.filter(cls.deleted_at.isnot(None))

    @classmethod
    def query_all_including_deleted(cls, query: Query) -> Query:
        """Return query without soft deletion filtering (for admin use)."""
        return query

    def __repr__(self):
        return f"<Review(id={self.id}, decision='{self.decision}', submission_id={self.submission_id})>"


class ProductionNote(Base):
    __tablename__ = "production_notes"

    id = Column(Integer, primary_key=True, index=True)
    task_id = Column(Integer, ForeignKey("tasks.id"), nullable=False)
    user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
    content = Column(Text, nullable=False)
    parent_note_id = Column(Integer, ForeignKey("production_notes.id"), nullable=True)
    created_at = Column(DateTime(timezone=True), server_default=func.now())
    updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
    
    # Soft deletion columns
    deleted_at = Column(DateTime(timezone=True), nullable=True)
    deleted_by = Column(Integer, ForeignKey("users.id"), nullable=True)

    # Relationships
    task = relationship("Task", back_populates="production_notes")
    user = relationship("User", foreign_keys=[user_id], back_populates="production_notes")
    parent_note = relationship("ProductionNote", remote_side=[id], back_populates="child_notes")
    child_notes = relationship("ProductionNote", back_populates="parent_note", cascade="all, delete-orphan")
    deleted_by_user = relationship("User", foreign_keys=[deleted_by])

    @property
    def is_deleted(self) -> bool:
        """Check if the production note is soft deleted."""
        return self.deleted_at is not None

    @classmethod
    def query_active(cls, query: Query) -> Query:
        """Filter query to exclude soft deleted production notes."""
        return query.filter(cls.deleted_at.is_(None))

    @classmethod
    def query_deleted(cls, query: Query) -> Query:
        """Filter query to include only soft deleted production notes."""
        return query.filter(cls.deleted_at.isnot(None))

    @classmethod
    def query_all_including_deleted(cls, query: Query) -> Query:
        """Return query without soft deletion filtering (for admin use)."""
        return query

    def __repr__(self):
        return f"<ProductionNote(id={self.id}, task_id={self.task_id}, user_id={self.user_id})>"


class TaskAttachment(Base):
    __tablename__ = "task_attachments"

    id = Column(Integer, primary_key=True, index=True)
    task_id = Column(Integer, ForeignKey("tasks.id"), nullable=False)
    user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
    file_name = Column(String, nullable=False)
    file_path = Column(String, nullable=False)
    file_type = Column(String, nullable=False)
    file_size = Column(Integer, nullable=False)
    attachment_type = Column(Enum(AttachmentType), nullable=False, default=AttachmentType.REFERENCE)
    description = Column(Text)
    uploaded_at = Column(DateTime(timezone=True), server_default=func.now())
    
    # Soft deletion columns
    deleted_at = Column(DateTime(timezone=True), nullable=True)
    deleted_by = Column(Integer, ForeignKey("users.id"), nullable=True)

    # Relationships
    task = relationship("Task", back_populates="attachments")
    user = relationship("User", foreign_keys=[user_id], back_populates="task_attachments")
    deleted_by_user = relationship("User", foreign_keys=[deleted_by])

    @property
    def is_deleted(self) -> bool:
        """Check if the task attachment is soft deleted."""
        return self.deleted_at is not None

    @classmethod
    def query_active(cls, query: Query) -> Query:
        """Filter query to exclude soft deleted task attachments."""
        return query.filter(cls.deleted_at.is_(None))

    @classmethod
    def query_deleted(cls, query: Query) -> Query:
        """Filter query to include only soft deleted task attachments."""
        return query.filter(cls.deleted_at.isnot(None))

    @classmethod
    def query_all_including_deleted(cls, query: Query) -> Query:
        """Return query without soft deletion filtering (for admin use)."""
        return query

    def __repr__(self):
        return f"<TaskAttachment(id={self.id}, file_name='{self.file_name}', type='{self.attachment_type}')>"