import { Effect, Schema } from "effect";
import { getProperty } from "dot-prop";
import { Expression, HttpRequestResult, LocaleMarkdown } from "../../../../../share/expression.js";
import { Locale } from "../../../../../share/locale.js";
import { Triggers } from "../../../../../share/event-bus.js";
import {
  CelRowAccess,
  columnFields,
  columnIdentityFields,
  editableHeader,
  LocaleMarkdownWithRow,
  registerRowVariablesIfAbsent
} from "../../../utils/shared.js";
export const type = "com.shwfed.table.column.combobox-multi";
export const compatibilityDate = "2026-05-28";
export const metadata = {
  name: "\u591A\u9009",
  icon: "fluent:chevron-down-20-regular",
  // Publishes its resolved options (array) to the per-row `selections` registry
  // (runtime.vue), readable via `selections["<id>"]`.
  selection: true
};
const isListType = (actual) => actual === "dyn" || actual.startsWith("list");
const isKeywordsType = (actual) => actual === "dyn" || actual.startsWith("list") || actual.startsWith("optional");
export function itemSchema(configure) {
  const LocaleMd = LocaleMarkdownWithRow(configure);
  const TextValue = Schema.Struct({
    kind: Schema.Literal("text"),
    value: Schema.String
  });
  const NumberValue = Schema.Struct({
    kind: Schema.Literal("number"),
    value: Schema.Number
  });
  const ItemValue = Schema.Union(TextValue, NumberValue).annotations({
    title: "\u503C",
    description: "\u9009\u9879\u7ED1\u5B9A\u7684\u503C\uFF0C\u53EF\u4EE5\u662F\u6587\u672C\u6216\u6570\u5B57"
  });
  return Schema.Struct({
    id: Schema.UUID.annotations({ description: "\u9009\u9879\u552F\u4E00\u6807\u8BC6\uFF0C\u7528\u4E8E\u7A33\u5B9A\u7684 v-for key" }),
    label: LocaleMd.annotations({
      title: "\u6807\u7B7E",
      description: "\u9009\u9879\u5C55\u793A\u7684\u672C\u5730\u5316\u6587\u672C\uFF0C\u652F\u6301 Markdown \u4E0E `{{ row.foo }}` / `{{ form.bar }}` \u63D2\u503C"
    }),
    value: ItemValue,
    tooltip: Schema.optional(LocaleMd.annotations({
      title: "\u63D0\u793A",
      description: "\u9F20\u6807\u60AC\u505C\u5728\u9009\u9879\u4E0A\u65F6\u5C55\u793A\u7684\u672C\u5730\u5316\u63D0\u793A\uFF0C\u652F\u6301 Markdown"
    })),
    keywords: Schema.optional(Schema.Array(Schema.String).annotations({
      title: "\u5173\u952E\u8BCD",
      description: "\u9664\u6807\u7B7E\u5916\u53EF\u53C2\u4E0E\u641C\u7D22\u5339\u914D\u7684\u989D\u5916\u5173\u952E\u8BCD\uFF1B\u7528\u4E8E\u8BA9\u9009\u9879\u547D\u4E2D\u6807\u7B7E\u672A\u5C55\u793A\u7684\u522B\u540D / \u4EE3\u53F7"
    }))
  }).annotations({
    title: "ComboboxMultiItem"
  });
}
export function remoteOptionsSchema(configure) {
  const CelRequest = Expression({
    configure: (env) => {
      configure(env);
      registerRowVariablesIfAbsent(env);
    },
    resultType: HttpRequestResult
  });
  const CelOptions = Expression({
    configure: (env) => {
      configure(env);
      registerRowVariablesIfAbsent(env);
      env.registerVariable("json", "dyn", { description: "HTTP \u54CD\u5E94\u4F53\uFF08\u5DF2\u89E3\u6790 JSON\uFF09\uFF1B\u8BF7\u6C42\u5931\u8D25\u6216\u5C1A\u672A\u5B8C\u6210\u65F6\u4E3A `null`" });
    },
    resultType: isListType
  });
  const CelOptionValue = Expression({
    configure: (env) => {
      configure(env);
      registerRowVariablesIfAbsent(env);
      env.registerVariable("option", "dyn", { description: "`\u9009\u9879` \u8868\u8FBE\u5F0F\u4EA7\u51FA\u7684\u6570\u7EC4\u4E2D\u8FED\u4EE3\u5230\u7684\u5355\u4E2A\u5143\u7D20" });
    },
    resultType: "dyn"
  });
  const LocaleOptionLabel = LocaleMarkdown({
    configure: (env) => {
      configure(env);
      registerRowVariablesIfAbsent(env);
      env.registerVariable("option", "dyn", { description: "`\u9009\u9879` \u8868\u8FBE\u5F0F\u4EA7\u51FA\u7684\u6570\u7EC4\u4E2D\u8FED\u4EE3\u5230\u7684\u5355\u4E2A\u5143\u7D20" });
    }
  });
  const CelOptionKeywords = Expression({
    configure: (env) => {
      configure(env);
      registerRowVariablesIfAbsent(env);
      env.registerVariable("option", "dyn", { description: "`\u9009\u9879` \u8868\u8FBE\u5F0F\u4EA7\u51FA\u7684\u6570\u7EC4\u4E2D\u8FED\u4EE3\u5230\u7684\u5355\u4E2A\u5143\u7D20" });
    },
    resultType: isKeywordsType
  });
  return Schema.Struct({
    kind: Schema.Literal("remote"),
    request: CelRequest.annotations({
      title: "\u8BF7\u6C42",
      description: "\u8FD4\u56DE `HttpRequest` \u7684 CEL \u8868\u8FBE\u5F0F\uFF1B\u53EF\u8BBF\u95EE `row` \u4E0E `index`\u3002\u76F8\u540C\u7B7E\u540D\u7684\u8BF7\u6C42\u4F1A\u5728\u8BE5\u8868\u683C\u5185\u81EA\u52A8\u53BB\u91CD"
    }),
    options: CelOptions.annotations({
      title: "\u9009\u9879",
      description: "\u4ECE HTTP \u54CD\u5E94\u4F53\u63D0\u53D6\u9009\u9879\u6570\u7EC4\u7684 CEL \u8868\u8FBE\u5F0F\uFF1B\u53EF\u8BBF\u95EE `row`\u3001`index` \u4E0E `json`\u3002\u4F8B\uFF1A`json.data`"
    }),
    optionValue: Schema.optionalWith(CelOptionValue.annotations({
      title: "\u9009\u9879\u503C",
      description: "\u4ECE\u5F53\u524D `option` \u63D0\u53D6\u5199\u5165\u503C\u7684 CEL\uFF1B\u4F8B\uFF1A`option.value`"
    }), { default: () => "option" }),
    optionLabel: Schema.optionalWith(LocaleOptionLabel.annotations({
      title: "\u9009\u9879\u6807\u7B7E",
      description: "\u6BCF\u4E2A\u9009\u9879\u5C55\u793A\u7684\u672C\u5730\u5316\u6587\u672C\uFF0C\u652F\u6301 `{{ string(option.foo) }}` \u63D2\u503C"
    }), { default: () => [{ locale: "zh", message: "" }] }),
    optionKeywords: Schema.optional(CelOptionKeywords.annotations({
      title: "\u5173\u952E\u8BCD",
      description: "\u4ECE\u5F53\u524D `option` \u63D0\u53D6\u989D\u5916\u641C\u7D22\u5173\u952E\u8BCD\u7684 CEL\uFF0C\u8FD4\u56DE\u5B57\u7B26\u4E32\u5217\u8868\uFF1B\u7528\u4E8E\u8BA9\u9009\u9879\u547D\u4E2D\u6807\u7B7E\u672A\u5C55\u793A\u7684\u522B\u540D / \u4EE3\u53F7\u3002\u4F8B\uFF1A`option.aliases`"
    }))
  }).annotations({ title: "ComboboxMultiOptionsRemote", description: "\u8FDC\u7A0B\u52A0\u8F7D\u7684\u9009\u9879\u5217\u8868" });
}
export function optionsSchema(configure) {
  const Item = itemSchema(configure);
  const StaticSpec = Schema.Struct({
    kind: Schema.Literal("static"),
    items: Schema.optionalWith(Schema.Array(Item).annotations({
      title: "\u9009\u9879",
      description: "\u4E0B\u62C9\u6846\u53EF\u9009\u9879\u5217\u8868"
    }), { default: () => [] })
  }).annotations({ title: "ComboboxMultiOptionsStatic", description: "\u9759\u6001\u914D\u7F6E\u7684\u9009\u9879\u5217\u8868" });
  const RemoteSpec = remoteOptionsSchema(configure);
  return Schema.Union(StaticSpec, RemoteSpec).annotations({
    title: "\u9009\u9879\u6765\u6E90",
    description: '\u9009\u9879\u53EF\u4EE5\u662F\u9759\u6001\u914D\u7F6E\uFF08`kind: "static"`\uFF09\u6216\u7531\u8FDC\u7A0B\u63A5\u53E3\u52A0\u8F7D\uFF08`kind: "remote"`\uFF09'
  });
}
export function writeSchema(configure) {
  const CelOnChange = Expression({
    configure: (env) => {
      configure(env);
      registerRowVariablesIfAbsent(env);
      env.registerVariable("value", "dyn", { description: "\u7528\u6237\u5F53\u524D\u9009\u4E2D\u9879 `value` \u7EC4\u6210\u7684\u6570\u7EC4\uFF1B\u6E05\u7A7A\u65F6\u4E3A\u7A7A\u6570\u7EC4 `[]`" });
    },
    resultType: "HttpRequest"
  });
  const CelMessage = Expression({
    configure: (env) => {
      configure(env);
      env.registerVariable("json", "dyn", { description: "HTTP \u54CD\u5E94\u4F53\uFF08\u5DF2\u89E3\u6790 JSON\uFF09" });
    },
    resultType: "string"
  });
  const WriteBinding = Schema.Struct({
    kind: Schema.Literal("binding"),
    binding: Schema.String.annotations({ title: "\u7ED1\u5B9A\u8DEF\u5F84", description: "\u5355\u5143\u683C\u8BFB\u5199\u7684 dot-prop \u8DEF\u5F84\uFF0C\u4F8B\u5982 `name` \u6216 `address.city`\uFF1B\u5199\u5165\u5373\u8986\u76D6\u8BE5\u8DEF\u5F84\u4E0A\u7684\u503C" })
  }).annotations({ title: "ComboboxMultiWriteBinding", description: "\u884C\u5185\u53EF\u7F16\u8F91\uFF1A\u8BFB\u5199\u540C\u4E00 dot-prop \u8DEF\u5F84" });
  const WriteRemote = Schema.Struct({
    kind: Schema.Literal("remote"),
    accessor: CelRowAccess(configure).annotations({ title: "\u8DEF\u5F84", description: "\u884C\u6570\u636E\u8BBF\u95EE CEL \u8868\u8FBE\u5F0F\uFF0C\u4F8B\u5982 `row.user.name`\uFF1B\u4F5C\u4E3A\u53EA\u8BFB\u56DE\u663E\u503C" }),
    onChange: Schema.optional(CelOnChange.annotations({ title: "\u5207\u6362\u8BF7\u6C42", description: "\u7528\u6237\u9009\u62E9\u540E\u7ACB\u5373\u53D1\u8D77\u7684 HTTP \u8BF7\u6C42\uFF1B`value` \u4E3A\u65B0\u503C" })),
    successMessage: Schema.optional(CelMessage.annotations({ title: "\u6210\u529F\u6D88\u606F", description: "\u8BF7\u6C42\u6210\u529F\u540E\u5F39\u51FA\u7684 toast\uFF1B\u672A\u914D\u7F6E\u5219\u9759\u9ED8" })),
    triggers: Schema.optional(Triggers.annotations({ title: "\u6210\u529F\u540E\u89E6\u53D1", description: "\u8BF7\u6C42\u6210\u529F\u540E\u5192\u6CE1\u7684\u64CD\u4F5C" }))
  }).annotations({ title: "ComboboxMultiWriteRemote", description: "\u670D\u52A1\u7AEF\u5199\u5165\uFF1A\u53EA\u8BFB\u56DE\u663E + \u5207\u6362\u8BF7\u6C42" });
  return Schema.Union(WriteBinding, WriteRemote).annotations({
    title: "\u5199\u5165\u65B9\u5F0F",
    description: '`kind: "binding"` \u884C\u5185\u7F16\u8F91\u5199\u56DE dot-prop \u8DEF\u5F84\uFF1B`kind: "remote"` \u53EA\u8BFB\u56DE\u663E\u5E76\u901A\u8FC7\u8BF7\u6C42\u5199\u5165\u670D\u52A1\u7AEF'
  });
}
export function schema(configure) {
  const CelBool = CelRowAccess(configure, { resultType: "bool" });
  const Options = optionsSchema(configure);
  const Write = writeSchema(configure);
  const display = columnFields(configure);
  return Schema.Struct({
    type: Schema.Literal(type),
    compatibilityDate: Schema.Literal(compatibilityDate),
    ...columnIdentityFields(),
    title: display.title,
    placeholder: Schema.optional(Locale.annotations({
      title: "\u5360\u4F4D\u7B26",
      description: "\u672A\u9009\u4E2D\u4EFB\u4F55\u9009\u9879\u65F6\u8F93\u5165\u6846\u4E2D\u7684\u5360\u4F4D\u6587\u672C"
    })),
    hidden: Schema.optional(CelBool.annotations({
      title: "\u9690\u85CF\u6761\u4EF6",
      description: "\u8FD4\u56DE `true` \u65F6\u8BE5\u884C\u7684\u4E0B\u62C9\u6846\u4E0D\u6E32\u67D3\uFF08\u5176\u4F59\u884C\u4E0D\u53D7\u5F71\u54CD\uFF09"
    })),
    disabled: Schema.optional(CelBool.annotations({
      title: "\u7981\u7528\u6761\u4EF6",
      description: "\u8FD4\u56DE `true` \u65F6\u4E0B\u62C9\u6846\u4ECD\u7136\u6E32\u67D3\u4F46\u4E0D\u53EF\u9009\u62E9"
    })),
    readonly: Schema.optional(CelBool.annotations({
      title: "\u53EA\u8BFB\u6761\u4EF6",
      description: "\u8FD4\u56DE `true` \u65F6\u4EC5\u4EE5\u7EAF\u6587\u672C\u5C55\u793A\u5F53\u524D\u5DF2\u9009\u9879\u7684\u6807\u7B7E"
    })),
    enableSorting: display.enableSorting,
    sortKey: display.sortKey,
    size: display.size,
    grow: display.grow,
    tooltip: display.tooltip,
    options: Schema.optionalWith(Options, {
      default: () => ({ kind: "static", items: [] })
    }),
    write: Schema.optionalWith(Write, {
      default: () => ({ kind: "binding", binding: "" })
    })
  }).annotations({
    title: "ComboboxMultiRenderer",
    description: "\u4E0B\u62C9\u591A\u9009\u6E32\u67D3\u5668"
  });
}
export function defaults() {
  return {
    title: [{ locale: "zh", message: "" }],
    size: 200,
    write: { kind: "binding", binding: "" },
    options: { kind: "static", items: [] }
  };
}
export const migrateFrom = [
  { type: "com.shwfed.table.column.combobox-multi", compatibilityDate: "2026-05-26" },
  { type: "com.shwfed.table.column.combobox-multi.remote", compatibilityDate: "2026-05-26" }
];
const CARRY = ["id", "groupId", "title", "size", "grow", "tooltip", "enableSorting", "sortKey", "placeholder", "hidden", "disabled", "readonly"];
export const migrate = (prev) => Effect.try({
  try: () => {
    if (!prev || typeof prev !== "object") {
      throw new Error("\u4E0B\u62C9\u591A\u9009\u8FC1\u79FB\u5931\u8D25\uFF1A\u539F\u503C\u4E0D\u662F\u5BF9\u8C61");
    }
    const src = prev;
    const out = { type, compatibilityDate };
    for (const k of CARRY) {
      if (src[k] !== void 0) out[k] = src[k];
    }
    if (typeof src.binding === "string") {
      out.write = { kind: "binding", binding: src.binding };
    } else if (typeof src.accessor === "string") {
      const remote = { kind: "remote", accessor: src.accessor };
      if (typeof src.onChange === "string") remote.onChange = src.onChange;
      if (typeof src.successMessage === "string") remote.successMessage = src.successMessage;
      if (Array.isArray(src.triggers)) remote.triggers = src.triggers;
      out.write = remote;
    } else {
      out.write = { kind: "binding", binding: "" };
    }
    const opts = src.options;
    if (opts && typeof opts === "object" && "kind" in opts) {
      out.options = opts;
    } else if (Array.isArray(src.items)) {
      out.options = { kind: "static", items: src.items };
    } else if (typeof src.request === "string" || typeof src.options === "string") {
      const remote = { kind: "remote" };
      if (typeof src.request === "string") remote.request = src.request;
      if (typeof src.options === "string") remote.options = src.options;
      if (typeof src.optionValue === "string") remote.optionValue = src.optionValue;
      if (Array.isArray(src.optionLabel)) remote.optionLabel = src.optionLabel;
      out.options = remote;
    } else {
      out.options = { kind: "static", items: [] };
    }
    return out;
  },
  catch: (e) => e instanceof Error ? e : new Error(String(e))
});
export function toColumnDef(value, { getLocaleText, $cel, inheritedContext }) {
  const write = value.write;
  const accessorFn = write.kind === "binding" ? (row) => {
    if (!row || typeof row !== "object") return void 0;
    return getProperty(row, write.binding);
  } : (row, index) => {
    try {
      return Effect.runSync($cel(write.accessor, { ...inheritedContext, row, index }));
    } catch (e) {
      console.error("[shwfed-table] combobox-multi accessor failed", e);
      return void 0;
    }
  };
  return {
    header: editableHeader(getLocaleText(value.title)),
    accessorFn,
    enableSorting: value.enableSorting ?? false,
    sortingFn: "basic",
    size: value.size,
    meta: {
      grow: value.grow ?? false,
      tooltip: getLocaleText(value.tooltip)
    }
  };
}
