from datetime import datetime, timezone

from app.extensions import db


class File(db.Model):
    __tablename__ = 'files'

    id = db.Column(db.Integer, primary_key=True)
    owner_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False, index=True)
    parent_id = db.Column(db.Integer, db.ForeignKey('files.id'), nullable=True, index=True)
    name = db.Column(db.String(255), nullable=False)
    is_folder = db.Column(db.Boolean, default=False, nullable=False)
    mime_type = db.Column(db.String(255), nullable=True)
    size = db.Column(db.BigInteger, default=0)
    storage_path = db.Column(db.String(500), nullable=True)  # UUID-based path on disk
    checksum = db.Column(db.String(64), nullable=True)  # SHA-256 for sync
    is_trashed = db.Column(db.Boolean, default=False, nullable=False, index=True)
    trashed_at = db.Column(db.DateTime, nullable=True)
    original_parent_id = db.Column(db.Integer, nullable=True)  # to restore to original location
    created_at = db.Column(db.DateTime, default=lambda: datetime.now(timezone.utc))
    updated_at = db.Column(db.DateTime, default=lambda: datetime.now(timezone.utc),
                           onupdate=lambda: datetime.now(timezone.utc))

    # Relationships
    children = db.relationship('File', backref=db.backref('parent', remote_side='File.id'),
                               lazy='dynamic')
    permissions = db.relationship('FilePermission', backref='file', lazy='dynamic',
                                  cascade='all, delete-orphan')
    share_links = db.relationship('ShareLink', backref='file', lazy='dynamic',
                                  cascade='all, delete-orphan')

    def to_dict(self):
        d = {
            'id': self.id,
            'owner_id': self.owner_id,
            'parent_id': self.parent_id,
            'name': self.name,
            'is_folder': self.is_folder,
            'mime_type': self.mime_type,
            'size': self.size,
            'created_at': self.created_at.isoformat() if self.created_at else None,
            'updated_at': self.updated_at.isoformat() if self.updated_at else None,
        }
        if self.is_trashed:
            d['is_trashed'] = True
            d['trashed_at'] = self.trashed_at.isoformat() if self.trashed_at else None
        return d


class FilePermission(db.Model):
    __tablename__ = 'file_permissions'

    id = db.Column(db.Integer, primary_key=True)
    file_id = db.Column(db.Integer, db.ForeignKey('files.id'), nullable=False, index=True)
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False, index=True)
    permission = db.Column(db.String(20), nullable=False)  # 'read', 'write', 'admin'

    user = db.relationship('User', backref='file_permissions')

    __table_args__ = (
        db.UniqueConstraint('file_id', 'user_id', name='uq_file_user_permission'),
    )


class ShareLink(db.Model):
    __tablename__ = 'share_links'

    id = db.Column(db.Integer, primary_key=True)
    file_id = db.Column(db.Integer, db.ForeignKey('files.id'), nullable=False, index=True)
    token = db.Column(db.String(64), unique=True, nullable=False, index=True)
    permission = db.Column(db.String(20), default='read', nullable=False)  # 'read' or 'write'
    password_hash = db.Column(db.String(255), nullable=True)
    expires_at = db.Column(db.DateTime, nullable=True)
    created_by = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
    download_count = db.Column(db.Integer, default=0)
    max_downloads = db.Column(db.Integer, nullable=True)
    created_at = db.Column(db.DateTime, default=lambda: datetime.now(timezone.utc))

    creator = db.relationship('User', backref='share_links')

    def is_expired(self):
        if self.expires_at is None:
            return False
        return datetime.now(timezone.utc) > self.expires_at

    def is_download_limit_reached(self):
        if self.max_downloads is None:
            return False
        return self.download_count >= self.max_downloads
