// filter — 依條件過濾陣列
// op 支援: eq, ne, gt, lt, contains
//
//go:build tinygo

package main

import (
	"encoding/json"
	"io"
	"os"
	"strconv"
	"strings"
)

type Condition struct {
	Key   string `json:"key"`
	Op    string `json:"op"`
	Value string `json:"value"`
}

type Input struct {
	Items     []json.RawMessage `json:"items"`
	Condition Condition         `json:"condition"`
}

func main() {
	raw, err := io.ReadAll(os.Stdin)
	if err != nil {
		writeError("failed to read stdin: " + err.Error())
		return
	}
	var input Input
	if err := json.Unmarshal(raw, &input); err != nil {
		writeError("invalid input JSON: " + err.Error())
		return
	}
	if input.Condition.Key == "" {
		writeError("condition.key 必填")
		return
	}

	var filtered []json.RawMessage
	for _, item := range input.Items {
		var obj map[string]json.RawMessage
		if err := json.Unmarshal(item, &obj); err != nil {
			continue
		}
		fieldRaw, ok := obj[input.Condition.Key]
		if !ok {
			continue
		}
		if matchCondition(fieldRaw, input.Condition.Op, input.Condition.Value) {
			filtered = append(filtered, item)
		}
	}

	if filtered == nil {
		filtered = []json.RawMessage{}
	}

	out, _ := json.Marshal(map[string]interface{}{
		"success": true,
		"data": map[string]interface{}{
			"items": filtered,
			"count": len(filtered),
		},
	})
	os.Stdout.Write(out)
}

func matchCondition(fieldRaw json.RawMessage, op, expected string) bool {
	// 取得欄位字串值
	var strVal string
	var numVal float64
	isNum := false

	// 嘗試解析為數字
	if err := json.Unmarshal(fieldRaw, &numVal); err == nil {
		isNum = true
		strVal = strconv.FormatFloat(numVal, 'f', -1, 64)
	} else {
		// 嘗試解析為字串
		if err := json.Unmarshal(fieldRaw, &strVal); err != nil {
			strVal = string(fieldRaw)
		}
	}

	switch strings.ToLower(op) {
	case "eq":
		return strVal == expected
	case "ne":
		return strVal != expected
	case "gt":
		if !isNum {
			return false
		}
		threshold, err := strconv.ParseFloat(expected, 64)
		if err != nil {
			return false
		}
		return numVal > threshold
	case "lt":
		if !isNum {
			return false
		}
		threshold, err := strconv.ParseFloat(expected, 64)
		if err != nil {
			return false
		}
		return numVal < threshold
	case "contains":
		return strings.Contains(strVal, expected)
	default:
		return false
	}
}

func writeError(msg string) {
	out, _ := json.Marshal(map[string]interface{}{"success": false, "error": msg})
	os.Stdout.Write(out)
}
