from sqlalchemy import Integer, String, DateTime, ForeignKey, Text
from sqlalchemy.sql import func
from sqlalchemy.orm import relationship, Mapped, mapped_column
from src.apps.base.models.base import Base
import os
from src.core.config import settings
from src.core.utils.enums import FileTypes
from src.core.utils.constants import API_PREFIXES
from sqlalchemy.ext.hybrid import hybrid_property
from typing import Optional
from datetime import datetime


class File(Base):
    """
    File Model: ORM class for File Entity
    """

    __tablename__ = "files"

    id: Mapped[int] = mapped_column(Integer, primary_key=True, index=True, autoincrement=True)
    original_name: Mapped[str] = mapped_column(Text)
    name: Mapped[str] = mapped_column(Text)
    path: Mapped[str] = mapped_column(Text)
    file_type: Mapped[str] = mapped_column(String(50), default=FileTypes.DOCUMENT)
    mime: Mapped[str] = mapped_column(String(255))
    storage_key: Mapped[Optional[str]] = mapped_column(String(100), index=True, unique=True, nullable=True)
    created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now())

    created_by_id: Mapped[int] = mapped_column(Integer, ForeignKey("users.id"))
    created_by: Mapped["User"] = relationship("User", foreign_keys=[created_by_id], uselist=False)

    # TODO: Uncomment when CDN model is created
    cdn_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey("cdns.id"), nullable=True)
    cdn: Mapped[Optional["CDN"]] = relationship("CDN", foreign_keys=[cdn_id], uselist=False)

    @hybrid_property
    def full_url(self) -> str:
        private_file_host_endpoint: str = (
            f"{settings.API_ROUTE_PREFIX}{API_PREFIXES.FILE.value}/download?filepath="
        )
        filepath: str = self.path
        # TODO: Uncomment when CDN model is created
        if self.cdn:
            cdn_serve_path: str = self.cdn.serve_path
            if self.storage_key:
                filepath = f"/{self.storage_key}"
                if cdn_serve_path.find(private_file_host_endpoint) < 0:
                    cdn_serve_path = "".join(
                        [self.cdn.host, private_file_host_endpoint]
                    )
            return "".join([cdn_serve_path, filepath])
        return "".join([settings.SERVER_HOST, filepath])

    @hybrid_property
    def upload_path(self) -> str:
        # TODO: Uncomment when CDN model is created
        if self.cdn:
            return "".join([self.cdn.upload_path, self.path])
        return "".join([os.getcwd(), settings.UPLOADS_DIR, self.path])
