package topdata

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

func importLegacyArmor(referenceBuilderDir, dataDir string, legacyTLK *legacyTLKData) (int, error) {
	_ = legacyTLK

	legacyDir := filepath.Join(referenceBuilderDir, "data", "armor")
	if _, err := os.Stat(legacyDir); err != nil {
		if os.IsNotExist(err) {
			return 0, nil
		}
		return 0, err
	}

	targetDir := filepath.Join(dataDir, "armor")
	targetPath := filepath.Join(targetDir, "armor.json")
	if _, err := os.Stat(targetPath); err == nil {
		obj, err := loadJSONObject(targetPath)
		if err == nil && countLegacyTLKRefsInValue(obj) == 0 {
			return 0, nil
		}
	}

	baseObj, err := loadJSONObject(filepath.Join(legacyDir, "base.json"))
	if err != nil {
		return 0, err
	}
	rows, err := mergeArmorRows(baseObj, filepath.Join(legacyDir, "modules"))
	if err != nil {
		return 0, err
	}

	if err := os.MkdirAll(targetDir, 0o755); err != nil {
		return 0, err
	}
	if err := removePathIfExists(filepath.Join(targetDir, "base.json")); err != nil {
		return 0, err
	}
	if err := removePathIfExists(filepath.Join(targetDir, "lock.json")); err != nil {
		return 0, err
	}
	if err := removePathIfExists(filepath.Join(targetDir, "modules")); err != nil {
		return 0, err
	}

	out := map[string]any{
		"output":  "armor.2da",
		"columns": baseObj["columns"],
		"rows":    rows,
	}
	raw, err := json.MarshalIndent(out, "", "  ")
	if err != nil {
		return 0, err
	}
	raw = append(raw, '\n')
	if err := os.WriteFile(targetPath, raw, 0o644); err != nil {
		return 0, err
	}
	return 1, nil
}

func mergeArmorRows(baseObj map[string]any, modulesDir string) ([]any, error) {
	rawRows, ok := baseObj["rows"].([]any)
	if !ok {
		return nil, nil
	}

	rows := make([]map[string]any, 0, len(rawRows))
	byID := map[int]map[string]any{}
	for _, raw := range rawRows {
		row, ok := deepCopyValue(raw).(map[string]any)
		if !ok {
			continue
		}
		delete(row, "key")
		rawID, ok := row["id"]
		if !ok {
			continue
		}
		id, err := asInt(rawID)
		if err != nil {
			return nil, err
		}
		row["id"] = id
		rows = append(rows, row)
		byID[id] = row
	}

	modulePaths, err := collectModulePaths(modulesDir)
	if err != nil {
		return nil, err
	}
	for _, path := range modulePaths {
		obj, err := loadJSONObject(path)
		if err != nil {
			return nil, err
		}
		if entries, ok := obj["entries"].(map[string]any); ok {
			for _, raw := range entries {
				row, ok := deepCopyValue(raw).(map[string]any)
				if !ok {
					continue
				}
				delete(row, "key")
				rawID, ok := row["id"]
				if !ok {
					continue
				}
				id, err := asInt(rawID)
				if err != nil {
					return nil, err
				}
				row["id"] = id
				rows = append(rows, row)
				byID[id] = row
			}
		}
		if overrides, ok := obj["overrides"].([]any); ok {
			for _, raw := range overrides {
				override, ok := raw.(map[string]any)
				if !ok {
					continue
				}
				rawID, ok := override["id"]
				if !ok {
					continue
				}
				id, err := asInt(rawID)
				if err != nil {
					return nil, err
				}
				row := byID[id]
				if row == nil {
					continue
				}
				for key, value := range override {
					if key == "id" || key == "key" || key == "_tlk" || isMetadataField(key) {
						continue
					}
					row[key] = deepCopyValue(value)
				}
			}
		}
	}

	sort.Slice(rows, func(i, j int) bool {
		return rows[i]["id"].(int) < rows[j]["id"].(int)
	})
	out := make([]any, 0, len(rows))
	for _, row := range rows {
		out = append(out, row)
	}
	return out, nil
}
