package achievements

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

type Achievement struct {
	ID          string `json:"id"`
	Name        string `json:"name"`
	Description string `json:"description"`
	Icon        string `json:"icon"`
	Unlocked    bool   `json:"unlocked"`
	Progress    int    `json:"progress"`
	Target      int    `json:"target"`
}

type Manager struct {
	Achievements map[string]*Achievement `json:"achievements"`
	NewUnlocks   []string                `json:"-"`
}

func New() *Manager {
	return &Manager{
		Achievements: map[string]*Achievement{
			"first_win": {
				ID:          "first_win",
				Name:        "First Victory",
				Description: "Complete your first puzzle",
				Icon:        "🏆",
				Target:      1,
			},
			"speed_demon": {
				ID:          "speed_demon",
				Name:        "Speed Demon",
				Description: "Complete an Easy puzzle in under 3 minutes",
				Icon:        "⚡",
				Target:      1,
			},
			"perfectionist": {
				ID:          "perfectionist",
				Name:        "Perfectionist",
				Description: "Complete a puzzle without using hints",
				Icon:        "💎",
				Target:      1,
			},
			"streak_master": {
				ID:          "streak_master",
				Name:        "Streak Master",
				Description: "Achieve a 5-day streak",
				Icon:        "🔥",
				Target:      5,
			},
			"century": {
				ID:          "century",
				Name:        "Century Club",
				Description: "Complete 100 puzzles",
				Icon:        "💯",
				Target:      100,
			},
			"lunatic_legend": {
				ID:          "lunatic_legend",
				Name:        "Lunatic Legend",
				Description: "Complete 10 Lunatic puzzles",
				Icon:        "🌙",
				Target:      10,
			},
			"daily_devotee": {
				ID:          "daily_devotee",
				Name:        "Daily Devotee",
				Description: "Complete 30 daily puzzles",
				Icon:        "📅",
				Target:      30,
			},
			"no_mistakes": {
				ID:          "no_mistakes",
				Name:        "Flawless",
				Description: "Complete a Hard puzzle without auto-check",
				Icon:        "✨",
				Target:      1,
			},
		},
		NewUnlocks: []string{},
	}
}

func path() (string, error) {
	h, err := os.UserHomeDir()
	if err != nil {
		return "", err
	}
	return filepath.Join(h, ".termdoku", "achievements.json"), nil
}

func Load() (*Manager, error) {
	m := New()
	p, err := path()
	if err != nil {
		return m, err
	}
	b, err := os.ReadFile(p)
	if err != nil {
		if errors.Is(err, fs.ErrNotExist) {
			return m, nil
		}
		return m, err
	}
	if err := json.Unmarshal(b, m); err != nil {
		return m, err
	}
	return m, nil
}

func Save(m *Manager) 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(m, "", "  ")
	if err != nil {
		return err
	}
	return os.WriteFile(p, data, 0o644)
}

func (m *Manager) CheckAndUnlock(id string, progress int) bool {
	if ach, ok := m.Achievements[id]; ok {
		if !ach.Unlocked {
			ach.Progress = progress
			if ach.Progress >= ach.Target {
				ach.Unlocked = true
				m.NewUnlocks = append(m.NewUnlocks, id)
				return true
			}
		}
	}
	return false
}

func (m *Manager) GetUnlockedCount() int {
	count := 0
	for _, ach := range m.Achievements {
		if ach.Unlocked {
			count++
		}
	}
	return count
}

func (m *Manager) GetTotalCount() int {
	return len(m.Achievements)
}

func (m *Manager) ClearNewUnlocks() {
	m.NewUnlocks = []string{}
}
