package sitemapgen

import (
	"encoding/json"
	"os"
	"path/filepath"
	"sync"
	"time"
)

// State checkpoint em JSON para retomar geração incremental.
type State struct {
	Version           int       `json:"version"`
	SiteURL           string    `json:"site_url"`
	Source            string    `json:"source"`
	LastCNPJ          string    `json:"last_cnpj"`
	TotalURLs         int64     `json:"total_urls"`
	CompletedFiles    []string  `json:"completed_files"`
	CurrentFile       string    `json:"current_file,omitempty"`
	URLsInCurrentFile int       `json:"urls_in_current_file"`
	StartedAt         time.Time `json:"started_at"`
	UpdatedAt         time.Time `json:"updated_at"`
	Finished          bool              `json:"finished"`
	APIUFProgress     map[string]string `json:"api_uf_progress,omitempty"`
	APICompletedUFs   []string          `json:"api_completed_ufs,omitempty"`
}

func (s *State) CompletedUFSet() map[string]bool {
	set := make(map[string]bool, len(s.APICompletedUFs))
	for _, uf := range s.APICompletedUFs {
		set[uf] = true
	}
	return set
}

func LoadState(path string) (*State, error) {
	data, err := os.ReadFile(path)
	if err != nil {
		if os.IsNotExist(err) {
			return nil, nil
		}
		return nil, err
	}
	var s State
	if err := json.Unmarshal(data, &s); err != nil {
		return nil, err
	}
	return &s, nil
}

func (s *State) Save(path string) error {
	if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
		return err
	}
	s.UpdatedAt = time.Now().UTC()
	data, err := json.MarshalIndent(s, "", "  ")
	if err != nil {
		return err
	}
	tmp := path + ".tmp"
	if err := os.WriteFile(tmp, data, 0o644); err != nil {
		return err
	}
	return os.Rename(tmp, path)
}

type StateStore struct {
	path string
	mu   sync.Mutex
	S    *State
}

func NewStateStore(path string, initial *State) *StateStore {
	return &StateStore{path: path, S: initial}
}

func (st *StateStore) Update(fn func(*State)) error {
	st.mu.Lock()
	defer st.mu.Unlock()
	fn(st.S)
	return st.S.Save(st.path)
}
