package infra

import (
	"fmt"
	"io"
	"mime"
	"os"
	"path/filepath"
	"strings"
	"time"
)

// FileSaveDisk escribe el contenido de data en baseDir con un nombre unico generado a
// partir de filename original. Crea baseDir si no existe.
//
// Retorna el UploadedFile con la metadata y la ruta completa en disco. El campo
// ContentType se infiere de la extension via mime.TypeByExtension; si la app necesita
// validacion mas estricta, debe usar FileValidateType antes y/o sobreescribir el campo.
func FileSaveDisk(baseDir string, filename string, data io.Reader) (UploadedFile, error) {
	if err := os.MkdirAll(baseDir, 0o755); err != nil {
		return UploadedFile{}, fmt.Errorf("file_save_disk: mkdir %s: %w", baseDir, err)
	}

	stored := FileUniqueName(filename)
	dst := filepath.Join(baseDir, stored)

	f, err := os.Create(dst)
	if err != nil {
		return UploadedFile{}, fmt.Errorf("file_save_disk: create %s: %w", dst, err)
	}
	defer f.Close()

	n, err := io.Copy(f, data)
	if err != nil {
		_ = os.Remove(dst)
		return UploadedFile{}, fmt.Errorf("file_save_disk: copy: %w", err)
	}

	ext := strings.ToLower(filepath.Ext(stored))
	ct := mime.TypeByExtension(ext)
	if ct == "" {
		ct = "application/octet-stream"
	}

	return UploadedFile{
		Filename:    filename,
		StoredName:  stored,
		Size:        n,
		ContentType: ct,
		Path:        dst,
		CreatedAt:   time.Now().UTC(),
	}, nil
}
