from sqlalchemy import Column, Integer, String, DateTime, Boolean, Text, ForeignKey, JSON
from sqlalchemy.orm import relationship
from datetime import datetime, timezone
from .database import Base


class Source(Base):
    __tablename__ = "sources"

    id = Column(Integer, primary_key=True)
    name = Column(String, nullable=False)
    type = Column(String, nullable=False)  # local, ssh, database
    config = Column(JSON, default=lambda: {})
    created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc))
    updated_at = Column(
        DateTime,
        default=lambda: datetime.now(timezone.utc),
        onupdate=lambda: datetime.now(timezone.utc),
    )

    jobs = relationship("Job", back_populates="source", cascade="all, delete-orphan")

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


class Job(Base):
    __tablename__ = "jobs"

    id = Column(Integer, primary_key=True)
    name = Column(String, nullable=False)
    source_id = Column(Integer, ForeignKey("sources.id"), nullable=False, index=True)
    strategy = Column(String, nullable=False, default="full")  # full, incremental
    destination_path = Column(String, nullable=False)
    exclude_patterns = Column(JSON, default=lambda: [])
    enabled = Column(Boolean, default=True)
    created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc))
    updated_at = Column(
        DateTime,
        default=lambda: datetime.now(timezone.utc),
        onupdate=lambda: datetime.now(timezone.utc),
    )

    source = relationship("Source", back_populates="jobs")
    schedule = relationship(
        "Schedule", back_populates="job", uselist=False, cascade="all, delete-orphan"
    )
    executions = relationship(
        "JobExecution", back_populates="job", cascade="all, delete-orphan"
    )

    def __repr__(self):
        return f"<Job(id={self.id}, name='{self.name}', source_id={self.source_id})>"


class Schedule(Base):
    __tablename__ = "schedules"

    id = Column(Integer, primary_key=True)
    job_id = Column(
        Integer, ForeignKey("jobs.id"), unique=True, nullable=False, index=True
    )
    cron_expression = Column(String, nullable=False)
    enabled = Column(Boolean, default=True)
    created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc))
    updated_at = Column(
        DateTime,
        default=lambda: datetime.now(timezone.utc),
        onupdate=lambda: datetime.now(timezone.utc),
    )

    job = relationship("Job", back_populates="schedule")

    def __repr__(self):
        return f"<Schedule(id={self.id}, job_id={self.job_id}, cron='{self.cron_expression}')>"


class JobExecution(Base):
    __tablename__ = "job_executions"

    id = Column(Integer, primary_key=True)
    job_id = Column(Integer, ForeignKey("jobs.id"), nullable=False, index=True)
    status = Column(
        String, nullable=False, default="pending"
    )  # pending, running, success, failed, cancelled
    started_at = Column(DateTime, nullable=True)
    completed_at = Column(DateTime, nullable=True)
    bytes_processed = Column(Integer, default=0)
    bytes_backed_up = Column(Integer, default=0)
    error_message = Column(Text, nullable=True)
    triggered_by = Column(String, nullable=False)  # manual, schedule

    job = relationship("Job", back_populates="executions")
    backups = relationship(
        "Backup", back_populates="execution", cascade="all, delete-orphan"
    )

    def __repr__(self):
        return f"<JobExecution(id={self.id}, job_id={self.job_id}, status='{self.status}')>"


class Backup(Base):
    __tablename__ = "backups"

    id = Column(Integer, primary_key=True)
    execution_id = Column(
        Integer, ForeignKey("job_executions.id"), nullable=False, index=True
    )
    storage_path = Column(String, nullable=False)
    size_bytes = Column(Integer, default=0)
    checksum = Column(String, nullable=True)
    type = Column(String, nullable=False)  # full, incremental
    parent_backup_id = Column(
        Integer, ForeignKey("backups.id"), nullable=True, index=True
    )
    created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc))

    execution = relationship("JobExecution", back_populates="backups")
    parent_backup = relationship("Backup", remote_side=[id])

    def __repr__(self):
        return f"<Backup(id={self.id}, execution_id={self.execution_id}, type='{self.type}')>"


class Setting(Base):
    __tablename__ = "settings"

    key = Column(String, primary_key=True)
    value = Column(Text, nullable=True)
    updated_at = Column(
        DateTime,
        default=lambda: datetime.now(timezone.utc),
        onupdate=lambda: datetime.now(timezone.utc),
    )

    def __repr__(self):
        return f"<Setting(key='{self.key}', value='{self.value}')>"
