package application

import (
	"context"
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/mmmy/snapgo/internal/infrastructure/clipboard"
)

// CaptureActionsService handles non-upload actions on already-produced PNG
// screenshots. Keeping these actions here makes save/copy available across
// overlay implementations without binding them to Wails or a specific OS.
type CaptureActionsService struct {
	Clipboard clipboard.Writer
	Notifier  Notifier
}

func (s *CaptureActionsService) CopyImage(_ context.Context, pngBytes []byte) error {
	if len(pngBytes) == 0 {
		err := fmt.Errorf("empty screenshot")
		s.notifyFailure(err.Error())
		return err
	}
	if s.Clipboard == nil {
		err := fmt.Errorf("clipboard is not configured")
		s.notifyFailure(err.Error())
		return err
	}
	if err := s.Clipboard.WriteImage(pngBytes); err != nil {
		s.notifyFailure("clipboard write failed: " + err.Error())
		return err
	}
	if s.Notifier != nil {
		s.Notifier.NotifySuccess("image copied to clipboard")
	}
	return nil
}

func (s *CaptureActionsService) SaveImage(_ context.Context, pngBytes []byte, dir string) (string, error) {
	if len(pngBytes) == 0 {
		err := fmt.Errorf("empty screenshot")
		s.notifyFailure(err.Error())
		return "", err
	}
	dir = strings.TrimSpace(dir)
	if dir == "" {
		err := fmt.Errorf("save directory is empty")
		s.notifyFailure(err.Error())
		return "", err
	}
	if err := os.MkdirAll(dir, 0o755); err != nil {
		s.notifyFailure("create save directory failed: " + err.Error())
		return "", err
	}
	path := uniquePNGPath(dir, time.Now())
	if err := os.WriteFile(path, pngBytes, 0o644); err != nil {
		s.notifyFailure("save failed: " + err.Error())
		return "", err
	}
	// Copy the saved path to the clipboard so the user can paste it right
	// away, mirroring how the upload/summary flows copy their result. A
	// clipboard failure must not fail the save itself.
	if s.Clipboard != nil {
		if err := s.Clipboard.WriteText(path); err != nil {
			s.notifyFailure("clipboard write failed: " + err.Error())
		}
	}
	if s.Notifier != nil {
		s.Notifier.NotifySuccess(path)
	}
	return path, nil
}

func (s *CaptureActionsService) notifyFailure(reason string) {
	if s.Notifier != nil {
		s.Notifier.NotifyFailure(reason)
	}
}

func uniquePNGPath(dir string, now time.Time) string {
	base := now.Format("20060102-150405")
	path := filepath.Join(dir, base+".png")
	for i := 1; fileExists(path); i++ {
		path = filepath.Join(dir, fmt.Sprintf("%s-%02d.png", base, i))
	}
	return path
}

func fileExists(path string) bool {
	_, err := os.Stat(path)
	return err == nil
}
