package web

import (
	"bytes"
	"context"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"time"
)

type diskInfo struct {
	Free  int64 `json:"free"`
	Total int64 `json:"total"`
}

// makeThumb erzeugt mit ffmpeg ein Vorschaubild. Bei Videos wird ein Einzelbild
// aus der ersten Sekunde genommen.
func makeThumb(src, dst, kind string) error {
	if err := os.MkdirAll(filepath.Dir(dst), 0o775); err != nil {
		return err
	}
	tmp := dst + ".tmp.jpg"
	defer os.Remove(tmp)

	ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
	defer cancel()

	seek := "1"
	if kind != "video" {
		seek = ""
	}
	err := runFFmpeg(ctx, src, tmp, seek)
	if err != nil && seek != "" {
		// Sehr kurze Videos haben nach einer Sekunde nichts mehr: von vorne.
		err = runFFmpeg(ctx, src, tmp, "")
	}
	if err != nil {
		return err
	}
	return os.Rename(tmp, dst)
}

// convertToJPEG wandelt ein Standbild (etwa HEIC vom iPhone) in JPEG um.
func convertToJPEG(src, dst string) error {
	ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
	defer cancel()
	out, err := exec.CommandContext(ctx, "ffmpeg",
		"-nostdin", "-loglevel", "error", "-y",
		"-i", src,
		"-frames:v", "1",
		"-q:v", "2",
		"-f", "image2", dst,
	).CombinedOutput()
	if err != nil {
		return fmt.Errorf("ffmpeg: %v: %s", err, bytes.TrimSpace(out))
	}
	return nil
}

func runFFmpeg(ctx context.Context, src, dst, seek string) error {
	args := []string{"-nostdin", "-loglevel", "error", "-y"}
	if seek != "" {
		args = append(args, "-ss", seek)
	}
	args = append(args,
		"-i", src,
		"-frames:v", "1",
		"-vf", "scale=480:-2:force_original_aspect_ratio=decrease",
		"-q:v", "5",
		dst,
	)
	out, err := exec.CommandContext(ctx, "ffmpeg", args...).CombinedOutput()
	if err != nil {
		return fmt.Errorf("ffmpeg: %v: %s", err, bytes.TrimSpace(out))
	}
	return nil
}
