package savegame

import (
	"encoding/json"
	"errors"
	"io/fs"
	"os"
	"path/filepath"
	"time"

	"termdoku/internal/game"
)

// SavedGame represents a saved game state
type SavedGame struct {
	Board        game.Grid          `json:"board"`
	Solution     game.Grid          `json:"solution"`
	Given        [9][9]bool         `json:"given"`
	Difficulty   string             `json:"difficulty"`
	Elapsed      int64              `json:"elapsed"` // seconds
	StartTime    time.Time          `json:"startTime"`
	HintsUsed    int                `json:"hintsUsed"`
	Notes        map[string][]uint8 `json:"notes"` // JSON keys must be strings
	SavedAt      time.Time          `json:"savedAt"`
	AutoCheck    bool               `json:"autoCheck"`
	TimerEnabled bool               `json:"timerEnabled"`
}

// path returns the save file path
func path() (string, error) {
	h, err := os.UserHomeDir()
	if err != nil {
		return "", err
	}
	return filepath.Join(h, ".termdoku", "savegame.json"), nil
}

// Save writes a game state to disk
func Save(sg SavedGame) error {
	p, err := path()
	if err != nil {
		return err
	}
	if err := os.MkdirAll(filepath.Dir(p), 0o755); err != nil {
		return err
	}
	data, err := json.MarshalIndent(sg, "", "  ")
	if err != nil {
		return err
	}
	return os.WriteFile(p, data, 0o644)
}

// Load reads a game state from disk
func Load() (SavedGame, error) {
	var sg SavedGame
	p, err := path()
	if err != nil {
		return sg, err
	}
	b, err := os.ReadFile(p)
	if err != nil {
		if errors.Is(err, fs.ErrNotExist) {
			return sg, errors.New("no saved game found")
		}
		return sg, err
	}
	if err := json.Unmarshal(b, &sg); err != nil {
		return sg, err
	}
	return sg, nil
}

// Exists checks if a saved game exists
func Exists() bool {
	p, err := path()
	if err != nil {
		return false
	}
	_, err = os.Stat(p)
	return err == nil
}

// Delete removes the saved game
func Delete() error {
	p, err := path()
	if err != nil {
		return err
	}
	return os.Remove(p)
}
