package persona

import (
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"
)

// SavePlan writes a persona plan to disk atomically.
func SavePlan(path string, plan *Plan) error {
	if plan == nil {
		return fmt.Errorf("persona plan is nil")
	}
	if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
		return fmt.Errorf("create plan dir: %w", err)
	}
	data, err := json.MarshalIndent(plan, "", "  ")
	if err != nil {
		return fmt.Errorf("marshal plan: %w", err)
	}
	tmp, err := os.CreateTemp(filepath.Dir(path), "service-plan.json.*.tmp")
	if err != nil {
		return fmt.Errorf("create plan temp file: %w", err)
	}
	tmpPath := tmp.Name()
	defer os.Remove(tmpPath)
	if _, err := tmp.Write(data); err != nil {
		_ = tmp.Close()
		return fmt.Errorf("write plan temp file: %w", err)
	}
	if err := tmp.Close(); err != nil {
		return fmt.Errorf("close plan temp file: %w", err)
	}
	if err := os.Rename(tmpPath, path); err != nil {
		return fmt.Errorf("rename plan file: %w", err)
	}
	return nil
}

// LoadPlan reads a previously persisted service plan.
func LoadPlan(path string) (*Plan, error) {
	data, err := os.ReadFile(path)
	if err != nil {
		if os.IsNotExist(err) && filepath.Base(path) == "service-plan.json" {
			legacyPath := filepath.Join(filepath.Dir(path), "plan.json")
			data, err = os.ReadFile(legacyPath)
		}
	}
	if err != nil {
		return nil, fmt.Errorf("read plan file: %w", err)
	}
	var plan Plan
	if err := json.Unmarshal(data, &plan); err != nil {
		return nil, fmt.Errorf("parse plan file: %w", err)
	}
	normalizePlanRoles(&plan)
	return &plan, nil
}

func normalizePlanRoles(plan *Plan) {
	if plan == nil {
		return
	}
	for i := range plan.Services {
		switch plan.Services[i].Role {
		case "REAL":
			plan.Services[i].Role = RoleSource
		case "STUB":
			plan.Services[i].Role = RoleStub
		case "SKIP":
			plan.Services[i].Role = RoleSkip
		}
	}
}
