package FikoYTDosya

import (
	"fmt"
	"io"
	"mime/multipart"
	"net/http"
	"os"
	"path/filepath"

	"github.com/gofiber/fiber/v3"
	"go.mongodb.org/mongo-driver/bson/primitive"
)

// FikoYTDosya: Dosya ile ilgili bilgileri tutan struct
type FikoYTDosya struct {
	File          *multipart.FileHeader
	Id            primitive.ObjectID
	Path          string
	ProcessedPath string
	MimeType      string
	Saved         bool
	Processed     bool
}

// Kaydet: Dosyayı kaydetme işlemi
func (f *FikoYTDosya) Kaydet() error {
	if f.File == nil {
		return fiber.NewError(fiber.StatusInternalServerError, "File is nil")
	}

	if f.Path == "" {
		return fiber.NewError(fiber.StatusInternalServerError, "Path is empty")
	}

	// Dosyayı aç
	file, err := f.File.Open()
	if err != nil {
		return fiber.NewError(fiber.StatusInternalServerError, "Error opening file: "+err.Error())
	}
	defer func() {
		if file != nil {
			file.Close()
		}
	}()

	// Geçici dosya yolu
	tempDir := "./ffmpeg/files"
	if _, err := os.Stat(tempDir); os.IsNotExist(err) {
		if err := os.MkdirAll(tempDir, 0755); err != nil {
			return fiber.NewError(fiber.StatusInternalServerError, "Error creating temp directory: "+err.Error())
		}
	}

	// Geçici dosya oluştur
	f.Path = filepath.Join(tempDir, f.Id.Hex()+f.Path)
	tempFile, err := os.Create(f.Path)
	if err != nil {
		return fiber.NewError(fiber.StatusInternalServerError, "Error creating temp file: "+err.Error())
	}
	defer func() {
		if tempFile != nil {
			tempFile.Close()
		}
	}()

	// Veriyi buffer ile kopyala
	buffer := make([]byte, 5*1024*1024)
	for {
		n, readErr := file.Read(buffer)
		if n > 0 {
			if _, writeErr := tempFile.Write(buffer[:n]); writeErr != nil {
				return fiber.NewError(fiber.StatusInternalServerError, "Error writing to temp file: "+writeErr.Error())
			}
		}
		if readErr != nil {
			if readErr == io.EOF {
				break
			}
			return fiber.NewError(fiber.StatusInternalServerError, "Error reading file: "+readErr.Error())
		}
	}

	// MIME türünü tespit et
	mimeType, err := detectMimeType(f.Path)
	if err != nil {
		return fiber.NewError(fiber.StatusInternalServerError, "Error detecting MIME type: "+err.Error())
	}

	if mimeType == "" {
		return fiber.NewError(fiber.StatusInternalServerError, "Failed to detect MIME type")
	}

	f.MimeType = mimeType
	f.Saved = true

	return nil
}

// Save: Dosyayı kaydetme işlemi
func (f *FikoYTDosya) Isle() error {

	// Sıkıştırma işlemi
	outputFile := f.Path + "-processed" + filepath.Ext(f.File.Filename)
	compressWithFFmpeg(f.Path, outputFile)
	f.Processed = true
	f.ProcessedPath = f.Path + "-processed" + filepath.Ext(f.File.Filename)
	return nil
}

// Save: Dosyayı kaydetme işlemi
func (f *FikoYTDosya) KaydetGridFs(metadata fiber.Map) error {

	// İşlenen dosyayı GridFS'ye kaydet
	fileOid := f.Id
	_, err := saveToGridFS(fileOid, f.Path, &metadata)
	if err != nil {
		return fiber.NewError(fiber.StatusInternalServerError, "Error saving to GridFS: "+err.Error())
	}

	return nil
}

// Save: Dosyayı kaydetme işlemi
func (f *FikoYTDosya) SilGridFs() error {

	// İşlenen dosyayı GridFS'ye kaydet
	fileOid := f.Id
	err := DeleteFromGridfs(fileOid)
	if err != nil {
		return fiber.NewError(fiber.StatusInternalServerError, "Error saving to GridFS: "+err.Error())
	}

	return nil
}

func (f *FikoYTDosya) TemizleDosyalar() error {
	_, err := os.Stat(f.Path)
	if os.IsNotExist(err) {

	}

	// Dosya varsa, sil
	err = os.Remove(f.Path)
	if err != nil {
	}

	_, err1 := os.Stat(f.ProcessedPath)
	if os.IsNotExist(err1) {

	}

	// Dosya varsa, sil
	err1 = os.Remove(f.ProcessedPath)
	if err1 != nil {
	}
	return nil
}

func detectMimeType(filePath string) (string, error) {
	file, err := os.Open(filePath)
	if err != nil {
		return "", fmt.Errorf("Dosya açılamadı: %v", err)
	}
	defer file.Close()

	buf := make([]byte, 512)
	if _, err := file.Read(buf); err != nil {
		return "", fmt.Errorf("Dosya okunamadı: %v", err)
	}

	return http.DetectContentType(buf), nil
}
