package blueprint

import (
	"encoding/json"
	"strings"
)

// defaultImportExportOps Z9：业务表默认允许导入/导出。
var defaultImportExportOps = []string{"import", "export"}

// defaultListActions Z9：列表页默认工具栏（含导入）。
var defaultListActions = []string{"create", "edit", "delete", "export", "import", "refresh"}

// EnsureDefaultImportExport 发布/合并兜底（Z9d）：
// 可写业务 resource 缺 import/export 则补上；list 页 actions 缺 import 则补上。
// 跳过：只读 resource（仅 list/get）；meta.ui.disable_default_import == true。
func (bp *Blueprint) EnsureDefaultImportExport() {
	if bp == nil {
		return
	}
	if disableDefaultImport(bp) {
		return
	}
	for i := range bp.Apis.Resources {
		r := &bp.Apis.Resources[i]
		if resourceReadOnly(r.Operations) {
			continue
		}
		r.Operations = ensureOpList(r.Operations, defaultImportExportOps...)
	}
	for i := range bp.Pages {
		p := &bp.Pages[i]
		if !strings.EqualFold(strings.TrimSpace(p.Type), "list") {
			continue
		}
		if p.Layout == nil {
			p.Layout = &PageLayout{}
		}
		p.Layout.Actions = ensureListActions(p.Layout.Actions)
		if p.Layout.ActionLabels == nil {
			p.Layout.ActionLabels = map[string]string{}
		}
		if _, ok := p.Layout.ActionLabels["import"]; !ok {
			p.Layout.ActionLabels["import"] = "导入 Excel"
		}
		if _, ok := p.Layout.ActionLabels["export"]; !ok {
			p.Layout.ActionLabels["export"] = "导出 Excel"
		}
	}
}

func disableDefaultImport(bp *Blueprint) bool {
	if len(bp.Meta.UI) == 0 {
		return false
	}
	var ui map[string]any
	if err := json.Unmarshal(bp.Meta.UI, &ui); err != nil {
		return false
	}
	v, ok := ui["disable_default_import"]
	if !ok {
		return false
	}
	switch t := v.(type) {
	case bool:
		return t
	case string:
		return strings.EqualFold(t, "true") || t == "1"
	default:
		return false
	}
}

func resourceReadOnly(ops []string) bool {
	if len(ops) == 0 {
		return false
	}
	writable := false
	for _, op := range ops {
		switch strings.ToLower(strings.TrimSpace(op)) {
		case "create", "update", "delete", "import", "export":
			writable = true
		}
	}
	// 仅 list/get → 只读，不强加 import
	if !writable {
		onlyRead := true
		for _, op := range ops {
			switch strings.ToLower(strings.TrimSpace(op)) {
			case "list", "get", "":
			default:
				onlyRead = false
			}
		}
		return onlyRead
	}
	return false
}

func ensureOpList(ops []string, add ...string) []string {
	seen := map[string]struct{}{}
	out := make([]string, 0, len(ops)+len(add))
	for _, op := range ops {
		op = strings.ToLower(strings.TrimSpace(op))
		if op == "" {
			continue
		}
		if _, ok := seen[op]; ok {
			continue
		}
		seen[op] = struct{}{}
		out = append(out, op)
	}
	for _, op := range add {
		op = strings.ToLower(strings.TrimSpace(op))
		if op == "" {
			continue
		}
		if _, ok := seen[op]; ok {
			continue
		}
		seen[op] = struct{}{}
		out = append(out, op)
	}
	return out
}

func ensureListActions(actions []string) []string {
	if len(actions) == 0 {
		return append([]string{}, defaultListActions...)
	}
	seen := map[string]struct{}{}
	out := make([]string, 0, len(actions)+2)
	for _, a := range actions {
		a = strings.ToLower(strings.TrimSpace(a))
		if a == "" {
			continue
		}
		if _, ok := seen[a]; ok {
			continue
		}
		seen[a] = struct{}{}
		out = append(out, a)
	}
	for _, need := range []string{"import", "export"} {
		if _, ok := seen[need]; ok {
			continue
		}
		// 插在 refresh 前；若无 refresh 则追加
		inserted := false
		for i, a := range out {
			if a == "refresh" {
				out = append(out[:i], append([]string{need}, out[i:]...)...)
				seen[need] = struct{}{}
				inserted = true
				break
			}
		}
		if !inserted {
			out = append(out, need)
			seen[need] = struct{}{}
		}
	}
	return out
}
