package models

import (
	"fmt"
	"time"

	"gorm.io/gorm"
)

type FileUpload struct {
	ID        uint           `json:"id" gorm:"primaryKey"`
	CreatedAt time.Time      `json:"created_at"`
	UpdatedAt time.Time      `json:"updated_at"`
	DeletedAt gorm.DeletedAt `json:"deleted_at" gorm:"index"`

	FileName     string `json:"file_name" gorm:"not null"`
	OriginalName string `json:"original_name" gorm:"not null"`
	FilePath     string `json:"file_path" gorm:"not null"`
	FileSize     int64  `json:"file_size" gorm:"not null"`
	MimeType     string `json:"mime_type" gorm:"not null"`
	Description  string `json:"description"`

	// Foreign Keys
	UploadedByID uint  `json:"uploaded_by_id" gorm:"not null"`
	ProjectID    *uint `json:"project_id"`
	TaskID       *uint `json:"task_id"`

	// Relationships
	UploadedBy User     `json:"uploaded_by" gorm:"foreignKey:UploadedByID"`
	Project    *Project `json:"project" gorm:"foreignKey:ProjectID"`
	Task       *Task    `json:"task" gorm:"foreignKey:TaskID"`
}

// GetFileExtension returns the file extension
func (f *FileUpload) GetFileExtension() string {
	if len(f.OriginalName) == 0 {
		return ""
	}

	lastDot := -1
	for i := len(f.OriginalName) - 1; i >= 0; i-- {
		if f.OriginalName[i] == '.' {
			lastDot = i
			break
		}
	}

	if lastDot == -1 {
		return ""
	}

	return f.OriginalName[lastDot:]
}

// IsImage checks if the file is an image
func (f *FileUpload) IsImage() bool {
	imageTypes := []string{
		"image/jpeg", "image/jpg", "image/png", "image/gif",
		"image/webp", "image/svg+xml", "image/bmp", "image/tiff",
	}

	for _, imgType := range imageTypes {
		if f.MimeType == imgType {
			return true
		}
	}
	return false
}

// IsDocument checks if the file is a document
func (f *FileUpload) IsDocument() bool {
	docTypes := []string{
		"application/pdf", "application/msword",
		"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
		"application/vnd.ms-excel",
		"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
		"application/vnd.ms-powerpoint",
		"application/vnd.openxmlformats-officedocument.presentationml.presentation",
		"text/plain", "text/csv",
	}

	for _, docType := range docTypes {
		if f.MimeType == docType {
			return true
		}
	}
	return false
}

// FormatFileSize returns a human-readable file size
func (f *FileUpload) FormatFileSize() string {
	const unit = 1024
	if f.FileSize < unit {
		return fmt.Sprintf("%d B", f.FileSize)
	}
	div, exp := int64(unit), 0
	for n := f.FileSize / unit; n >= unit; n /= unit {
		div *= unit
		exp++
	}
	return fmt.Sprintf("%.1f %cB", float64(f.FileSize)/float64(div), "KMGTPE"[exp])
}
