package pipeline

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

	"gitea.westgate.pw/ShadowsOverWestgate/sow-tools/internal/gff"
	"gitea.westgate.pw/ShadowsOverWestgate/sow-tools/internal/project"
)

type ApplyManifestResult struct {
	ManifestPath string
	ModuleSource string
	HAKCount     int
}

func ApplyHAKManifest(p *project.Project, manifestPath string) (ApplyManifestResult, error) {
	if manifestPath == "" {
		manifestPath = p.HAKManifestPath()
	}
	if strings.TrimSpace(p.EffectiveConfig().Paths.Source) == "" {
		return ApplyManifestResult{}, fmt.Errorf("cannot apply hak manifest: paths.source is not configured")
	}
	sourceRoot := filepath.Clean(p.SourceDir())
	if sourceRoot == "." || sourceRoot == string(filepath.Separator) || sourceRoot == filepath.Clean(p.Root) {
		return ApplyManifestResult{}, fmt.Errorf("cannot apply hak manifest: paths.source resolves to unsafe source root %s", sourceRoot)
	}

	raw, err := os.ReadFile(manifestPath)
	if err != nil {
		return ApplyManifestResult{}, fmt.Errorf("read hak manifest: %w", err)
	}

	var manifest BuildManifest
	if err := json.Unmarshal(raw, &manifest); err != nil {
		return ApplyManifestResult{}, fmt.Errorf("parse hak manifest: %w", err)
	}

	moduleSource := filepath.Join(sourceRoot, "module", "module.ifo.json")
	sourceRaw, err := os.ReadFile(moduleSource)
	if err != nil {
		return ApplyManifestResult{}, fmt.Errorf("read module ifo source: %w", err)
	}

	var document gff.Document
	if err := json.Unmarshal(sourceRaw, &document); err != nil {
		return ApplyManifestResult{}, fmt.Errorf("parse module ifo source: %w", err)
	}

	setModuleHAKList(&document, manifest.ModuleHAKs)

	formatted, err := json.MarshalIndent(document, "", "  ")
	if err != nil {
		return ApplyManifestResult{}, fmt.Errorf("marshal updated module ifo: %w", err)
	}
	formatted = append(formatted, '\n')

	if err := os.WriteFile(moduleSource, formatted, 0o644); err != nil {
		return ApplyManifestResult{}, fmt.Errorf("write module ifo source: %w", err)
	}

	return ApplyManifestResult{
		ManifestPath: manifestPath,
		ModuleSource: moduleSource,
		HAKCount:     len(manifest.ModuleHAKs),
	}, nil
}
