import os
from sqlalchemy.sql import func
from sqlalchemy import Column, Integer, String, DateTime
 
from app.core.extensions import db
from app.utils.file_handler import FileHandler 


class File(db.Model):
    __tablename__ = 'files'

    id = Column(Integer, primary_key=True)
    name = Column(String(255), nullable=False)
    extension = Column(String(10), nullable=False)
    content_type = Column(String(100), nullable=False)
    size = Column(Integer, nullable=False)
    sha256_hash = Column(String(64), nullable=False)
    filepath = Column(String(255), nullable=False)
    uploaded_at = Column(DateTime, nullable=False, default=func.now())
    updated_at = Column(DateTime, nullable=False, default=func.now(), onupdate=func.now())
    
    @property
    def url(self):
        """
        Get the URL of the file.
        """
        return f"/files/{self.id}/{self.name}"

    @classmethod
    def create(cls, file_storage, upload_dir):
        """
        Create a new File instance from a FileStorage object.

        :param file_storage: The FileStorage object containing the uploaded file.
        :param upload_dir: The directory where the file will be saved.
        :return: The new File instance if successful, None otherwise.
        """
        try:
            filename, extension = os.path.splitext(file_storage.filename) 
            file_path, file_hash = FileHandler.save_file(file_storage, upload_dir)

            file = cls(
                name=filename,
                extension=extension[1:],
                content_type=file_storage.content_type,
                size=os.path.getsize(file_path),
                sha256_hash=file_hash,
                filepath=file_path
            )
            
            # Add the file object to the session
            db.session.add(file)
            # Commit the session
            db.session.commit()
            
            return file
        except Exception as e:
            print(f"Error creating file: {e}")
            # Rollback the session if an error occurs
            db.session.rollback()
            return None
    
    @classmethod
    def delete(cls, file_id):
        """
        Delete the file from the file system and database.
        
        :param file_id: The ID of the file to delete.
        :return: True if the file is successfully deleted, False otherwise.
        """
        file = cls.query.get(file_id)
        if file:
            try:
                # Remove the file from the file system
                if os.path.exists(file.filepath):
                    os.remove(file.filepath)

                # Delete the database record
                db.session.delete(file)
                db.session.commit()
                return True
            except Exception as e:
                print(f"Error deleting file: {e}")
                db.session.rollback()
                return False
        else:
            return False
        
    def update(self, new_name):
        """
        Update the name of the file.

        :param new_name: The new name of the file.
        :return: True if the update is successful, False otherwise.
        """
        try:
            self.name = new_name
            self.updated_at = func.now()
            db.session.commit()
            return True
        except Exception as e:
            print(f"Error updating file name: {e}")
            db.session.rollback()
            return False