<script setup>
import { computed, ref } from "vue";
import { Icon } from "@iconify/vue";
import { Field, FieldLabel } from "../../../../ui/field";
import { ExpressionEditor } from "../../../../ui/expression-editor";
import { Locale as LocaleField } from "../../../../ui/locale";
import { ColorPicker } from "../../../../ui/color-picker";
import { Markdown } from "../../../../ui/markdown";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue
} from "../../../../ui/select";
import { Separator } from "../../../../ui/separator";
import { ScrollArea } from "../../../../ui/scroll-area";
import { Button } from "../../../../ui/button";
import {
  InputGroup,
  InputGroupButton,
  InputGroupInput,
  InputGroupNumberField
} from "../../../../ui/input-group";
import {
  dataSourceSchema,
  getStructFieldDescription,
  getStructFieldTitle,
  schema,
  ySeriesSchema
} from "./schema";
defineOptions({ name: "ShwfedBlockChartXyConfig" });
const block = defineModel({ type: null, ...{ required: true } });
const blockSchema = schema(() => {
});
const dsSchema = dataSourceSchema(() => {
});
const ySchema = ySeriesSchema(() => {
});
const fieldTitle = (f) => getStructFieldTitle(blockSchema, f) ?? f;
const fieldDescription = (f) => getStructFieldDescription(blockSchema, f);
const dsTitle = (f) => getStructFieldTitle(dsSchema, f) ?? f;
const dsDescription = (f) => getStructFieldDescription(dsSchema, f);
const yTitle = (f) => getStructFieldTitle(ySchema, f) ?? f;
const yDescription = (f) => getStructFieldDescription(ySchema, f);
const CHART_TYPE_OPTIONS = [
  { value: "line", label: "\u6298\u7EBF" },
  { value: "area", label: "\u9762\u79EF" },
  { value: "groupedBar", label: "\u5206\u7EC4\u67F1" },
  { value: "scatter", label: "\u6563\u70B9" },
  { value: "stackedBar", label: "\u5806\u53E0\u67F1" }
];
const CURVE_OPTIONS = [
  { value: "linear", label: "\u76F4\u7EBF (linear)" },
  { value: "monotoneX", label: "\u5355\u8C03\u5E73\u6ED1 (monotoneX)" },
  { value: "natural", label: "\u81EA\u7136\u6837\u6761 (natural)" },
  { value: "basis", label: "B \u6837\u6761 (basis)" },
  { value: "cardinal", label: "Cardinal" },
  { value: "catmullRom", label: "Catmull-Rom" },
  { value: "step", label: "\u9636\u68AF (step)" },
  { value: "stepAfter", label: "\u9636\u68AF\u540E (stepAfter)" },
  { value: "stepBefore", label: "\u9636\u68AF\u524D (stepBefore)" }
];
const DATA_VARS = {
  json: { type: "optional<dyn>", label: "HTTP \u54CD\u5E94\u4F53\uFF08\u914D\u7F6E\u4E86\u8BF7\u6C42\u65F6\u53EF\u7528\uFF09" }
};
const dataSourceVars = computed(() => {
  const out = {};
  for (const ds of block.value.dataSources) {
    if (ds.name) out[ds.name] = { type: "list<dyn>", label: `\u6570\u636E\u6E90\u300C${ds.name}\u300D\u7684\u7ED3\u679C\u5217\u8868` };
  }
  return out;
});
const selectedId = ref("");
const selectedDataSource = computed(
  () => block.value.dataSources.find((d) => d.id === selectedId.value) ?? null
);
function writeDataSources(next) {
  block.value = { ...block.value, dataSources: next };
}
function addDataSource() {
  const existing = new Set(block.value.dataSources.map((d) => d.name));
  let n = block.value.dataSources.length + 1;
  let name = `source${n}`;
  while (existing.has(name)) {
    n += 1;
    name = `source${n}`;
  }
  const ds = { id: crypto.randomUUID(), name, data: "[]" };
  writeDataSources([...block.value.dataSources, ds]);
  selectedId.value = ds.id;
}
function removeDataSource(id) {
  writeDataSources(block.value.dataSources.filter((d) => d.id !== id));
  if (selectedId.value === id) selectedId.value = "";
}
function patchDataSource(id, patch) {
  writeDataSources(block.value.dataSources.map((d) => d.id === id ? { ...d, ...patch } : d));
}
function setDsName(id, v) {
  patchDataSource(id, { name: String(v ?? "") });
}
function setDsData(id, v) {
  patchDataSource(id, { data: v });
}
function setDsRequest(id, v) {
  const ds = block.value.dataSources.find((d) => d.id === id);
  if (!ds) return;
  const next = v.trim() === "" ? { id: ds.id, name: ds.name, data: ds.data } : { ...ds, request: v };
  writeDataSources(block.value.dataSources.map((d) => d.id === id ? next : d));
}
function setDisplayName(v) {
  const s = String(v ?? "");
  block.value = { ...block.value, displayName: s.length > 0 ? s : void 0 };
}
function setCaption(v) {
  block.value = { ...block.value, caption: v };
}
function setX(v) {
  block.value = { ...block.value, x: v };
}
function writeY(next) {
  block.value = { ...block.value, y: next };
}
function patchYItem(i, patch) {
  writeY(block.value.y.map((s, idx) => idx === i ? { ...s, ...patch } : s));
}
function setYValue(i, v) {
  patchYItem(i, { value: v });
}
function setYLabel(i, v) {
  patchYItem(i, { label: v });
}
function setYChart(i, v) {
  patchYItem(i, { chart: v });
}
function setYColor(i, v) {
  patchYItem(i, { color: v.length > 0 ? v : void 0 });
}
function setYCurveType(i, v) {
  patchYItem(i, { curveType: v });
}
function setYLineWidth(i, v) {
  patchYItem(i, { lineWidth: typeof v === "number" && v > 0 ? v : 2 });
}
function setYDash(i, v) {
  patchYItem(i, { dash: v.length > 0 ? v : void 0 });
}
function setYLineColor(i, v) {
  patchYItem(i, { lineColor: v.length > 0 ? v : void 0 });
}
function setYWidth(i, v) {
  patchYItem(i, { width: v.length > 0 ? v : void 0 });
}
function setYSize(i, v) {
  patchYItem(i, { size: v.length > 0 ? v : void 0 });
}
function addY() {
  writeY([...block.value.y, {
    id: crypto.randomUUID(),
    value: "[]",
    chart: "line",
    curveType: "monotoneX",
    lineWidth: 2
  }]);
}
function removeY(i) {
  if (block.value.y.length <= 1) return;
  writeY(block.value.y.filter((_, idx) => idx !== i));
}
</script>

<template>
  <div class="flex min-h-96 gap-3">
    <!-- Sidebar: general config + data sources -->
    <div class="flex w-52 shrink-0 flex-col">
      <ScrollArea class="flex-1">
        <div class="flex flex-col gap-0.5">
          <button
            type="button"
            class="flex items-center gap-1.5 rounded px-2 py-1.5 text-sm transition-colors"
            :class="!selectedDataSource ? 'bg-[color-mix(in_srgb,var(--primary)_10%,white)] text-(--primary)' : 'text-zinc-700 hover:bg-zinc-50'"
            @click="selectedId = ''"
          >
            <Icon
              icon="fluent:settings-20-regular"
              class="size-4 shrink-0"
            />
            <span>通用配置</span>
          </button>

          <Separator class="my-1" />

          <div
            v-for="ds in block.dataSources"
            :key="ds.id"
            class="group flex cursor-pointer items-center gap-1.5 rounded px-2 py-1.5 text-sm transition-colors"
            :class="selectedId === ds.id ? 'bg-[color-mix(in_srgb,var(--primary)_10%,white)] text-(--primary)' : 'text-zinc-700 hover:bg-zinc-50'"
            @click="selectedId = ds.id"
          >
            <Icon
              icon="fluent:database-20-regular"
              class="size-4 shrink-0"
            />
            <span class="flex-1 truncate font-mono text-xs">{{ ds.name || "\u672A\u547D\u540D" }}</span>
            <button
              type="button"
              class="inline-flex size-5 shrink-0 items-center justify-center rounded text-zinc-300 opacity-0 transition-opacity group-hover:opacity-100 hover:bg-red-50 hover:text-red-500"
              aria-label="删除数据源"
              @click.stop="removeDataSource(ds.id)"
            >
              <Icon
                icon="fluent:delete-20-regular"
                class="size-3.5"
              />
            </button>
          </div>
        </div>
      </ScrollArea>

      <Button
        type="button"
        variant="ghost"
        size="sm"
        class="mt-1 w-full justify-center"
        @click="addDataSource()"
      >
        <Icon
          icon="fluent:add-20-regular"
          class="size-4"
        />
        <span>新增数据源</span>
      </Button>
    </div>

    <Separator orientation="vertical" />

    <!-- Right pane -->
    <div class="min-w-0 flex-1">
      <!-- Data source editor -->
      <div
        v-if="selectedDataSource"
        class="space-y-4"
      >
        <Field orientation="vertical">
          <FieldLabel class="text-xs text-zinc-500">
            <template
              v-if="dsDescription('name')"
              #tooltip
            >
              <Markdown
                :source="dsDescription('name')"
                block
                class="prose prose-sm prose-zinc"
              />
            </template>
            {{ dsTitle("name") }}
          </FieldLabel>
          <InputGroup>
            <InputGroupInput
              :model-value="selectedDataSource.name"
              placeholder="例：btc"
              class="font-mono"
              @update:model-value="(v) => setDsName(selectedDataSource.id, v)"
            />
          </InputGroup>
        </Field>
        <Field orientation="vertical">
          <FieldLabel class="text-xs text-zinc-500">
            <template
              v-if="dsDescription('request')"
              #tooltip
            >
              <Markdown
                :source="dsDescription('request')"
                block
                class="prose prose-sm prose-zinc"
              />
            </template>
            {{ dsTitle("request") }}
          </FieldLabel>
          <ExpressionEditor
            :model-value="selectedDataSource.request ?? ''"
            placeholder="可选；如 http.get('/api/metrics')"
            result-type="HttpRequest"
            multiline
            class="min-h-20"
            @update:model-value="(v) => setDsRequest(selectedDataSource.id, v)"
          />
        </Field>
        <Field orientation="vertical">
          <FieldLabel class="text-xs text-zinc-500">
            <template
              v-if="dsDescription('data')"
              #tooltip
            >
              <Markdown
                :source="dsDescription('data')"
                block
                class="prose prose-sm prose-zinc"
              />
            </template>
            {{ dsTitle("data") }}
          </FieldLabel>
          <ExpressionEditor
            :model-value="selectedDataSource.data"
            placeholder="返回列表的表达式，如 json.?data.orValue([])"
            result-type="list"
            :extra-vars="DATA_VARS"
            @update:model-value="(v) => setDsData(selectedDataSource.id, v)"
          />
        </Field>
      </div>

      <!-- General config -->
      <div
        v-else
        class="space-y-5"
      >
        <div class="grid grid-cols-2 items-start gap-x-6">
          <Field orientation="vertical">
            <FieldLabel class="text-xs text-zinc-500">
              <template
                v-if="fieldDescription('displayName')"
                #tooltip
              >
                <Markdown
                  :source="fieldDescription('displayName')"
                  block
                  class="prose prose-sm prose-zinc"
                />
              </template>
              {{ fieldTitle("displayName") }}
            </FieldLabel>
            <InputGroup>
              <InputGroupInput
                :model-value="block.displayName ?? ''"
                placeholder="例：月度销售趋势"
                @update:model-value="setDisplayName"
              />
            </InputGroup>
          </Field>

          <Field orientation="vertical">
            <FieldLabel class="text-xs text-zinc-500">
              <template
                v-if="fieldDescription('caption')"
                #tooltip
              >
                <Markdown
                  :source="fieldDescription('caption')"
                  block
                  class="prose prose-sm prose-zinc"
                />
              </template>
              {{ fieldTitle("caption") }}
            </FieldLabel>
            <LocaleField
              markdown
              translate-hint="chart caption"
              :model-value="block.caption"
              @update:model-value="setCaption"
            />
          </Field>
        </div>

        <Separator />

        <Field orientation="vertical">
          <FieldLabel class="text-xs text-zinc-500">
            <template
              v-if="fieldDescription('x')"
              #tooltip
            >
              <Markdown
                :source="fieldDescription('x')"
                block
                class="prose prose-sm prose-zinc"
              />
            </template>
            {{ fieldTitle("x") }}
          </FieldLabel>
          <ExpressionEditor
            :model-value="block.x"
            result-type="list"
            :extra-vars="dataSourceVars"
            unlisted-vars-are-dyn
            placeholder="返回列表，如 range(0, 12)"
            @update:model-value="setX"
          />
        </Field>

        <Separator />

        <Field orientation="vertical">
          <FieldLabel class="text-xs text-zinc-500">
            <template
              v-if="fieldDescription('y')"
              #tooltip
            >
              <Markdown
                :source="fieldDescription('y')"
                block
                class="prose prose-sm prose-zinc"
              />
            </template>
            {{ fieldTitle("y") }}
          </FieldLabel>
          <div class="flex flex-col gap-3 pt-1">
            <div
              v-for="(s, i) in block.y"
              :key="s.id"
              class="relative space-y-3 rounded border border-zinc-200 bg-zinc-50/40 p-3 pt-9"
            >
              <InputGroupButton
                variant="destructive"
                size="icon-xs"
                class="absolute top-2 right-2 z-10"
                :disabled="block.y.length <= 1"
                aria-label="删除系列"
                @click="removeY(i)"
              >
                <Icon icon="fluent:delete-20-regular" />
              </InputGroupButton>

              <Field orientation="vertical">
                <FieldLabel class="text-xs text-zinc-500">
                  <template
                    v-if="yDescription('value')"
                    #tooltip
                  >
                    <Markdown
                      :source="yDescription('value')"
                      block
                      class="prose prose-sm prose-zinc"
                    />
                  </template>
                  {{ yTitle("value") }}
                </FieldLabel>
                <ExpressionEditor
                  :model-value="s.value"
                  result-type="list"
                  :extra-vars="dataSourceVars"
                  unlisted-vars-are-dyn
                  :placeholder="`\u7B2C ${i + 1} \u4E2A\u7CFB\u5217\uFF0C\u5982 source1.map(r, r.value)`"
                  @update:model-value="(v) => setYValue(i, v)"
                />
              </Field>

              <div class="grid grid-cols-2 gap-3">
                <Field orientation="vertical">
                  <FieldLabel class="text-xs text-zinc-500">
                    <template
                      v-if="yDescription('chart')"
                      #tooltip
                    >
                      <Markdown
                        :source="yDescription('chart')"
                        block
                        class="prose prose-sm prose-zinc"
                      />
                    </template>
                    {{ yTitle("chart") }}
                  </FieldLabel>
                  <Select
                    :model-value="s.chart"
                    @update:model-value="(v) => setYChart(i, v)"
                  >
                    <SelectTrigger class="w-full">
                      <SelectValue />
                    </SelectTrigger>
                    <SelectContent>
                      <SelectItem
                        v-for="opt in CHART_TYPE_OPTIONS"
                        :key="opt.value"
                        :value="opt.value"
                      >
                        {{ opt.label }}
                      </SelectItem>
                    </SelectContent>
                  </Select>
                </Field>
                <Field orientation="vertical">
                  <FieldLabel class="text-xs text-zinc-500">
                    <template
                      v-if="yDescription('color')"
                      #tooltip
                    >
                      <Markdown
                        :source="yDescription('color')"
                        block
                        class="prose prose-sm prose-zinc"
                      />
                    </template>
                    {{ yTitle("color") }}
                  </FieldLabel>
                  <ColorPicker
                    :model-value="s.color ?? ''"
                    placeholder="自动取色"
                    @update:model-value="(v) => setYColor(i, v)"
                  />
                </Field>
              </div>

              <!-- line -->
              <template v-if="s.chart === 'line'">
                <div class="grid grid-cols-2 gap-3">
                  <Field orientation="vertical">
                    <FieldLabel class="text-xs text-zinc-500">
                      <template
                        v-if="yDescription('curveType')"
                        #tooltip
                      >
                        <Markdown
                          :source="yDescription('curveType')"
                          block
                          class="prose prose-sm prose-zinc"
                        />
                      </template>
                      {{ yTitle("curveType") }}
                    </FieldLabel>
                    <Select
                      :model-value="s.curveType"
                      @update:model-value="(v) => setYCurveType(i, v)"
                    >
                      <SelectTrigger class="w-full">
                        <SelectValue />
                      </SelectTrigger>
                      <SelectContent>
                        <SelectItem
                          v-for="opt in CURVE_OPTIONS"
                          :key="opt.value"
                          :value="opt.value"
                        >
                          {{ opt.label }}
                        </SelectItem>
                      </SelectContent>
                    </Select>
                  </Field>
                  <Field orientation="vertical">
                    <FieldLabel class="text-xs text-zinc-500">
                      <template
                        v-if="yDescription('lineWidth')"
                        #tooltip
                      >
                        <Markdown
                          :source="yDescription('lineWidth')"
                          block
                          class="prose prose-sm prose-zinc"
                        />
                      </template>
                      {{ yTitle("lineWidth") }}
                    </FieldLabel>
                    <InputGroup>
                      <InputGroupNumberField
                        :model-value="s.lineWidth"
                        :min="1"
                        @update:model-value="(v) => setYLineWidth(i, v)"
                      />
                    </InputGroup>
                  </Field>
                </div>
                <Field orientation="vertical">
                  <FieldLabel class="text-xs text-zinc-500">
                    <template
                      v-if="yDescription('dash')"
                      #tooltip
                    >
                      <Markdown
                        :source="yDescription('dash')"
                        block
                        class="prose prose-sm prose-zinc"
                      />
                    </template>
                    {{ yTitle("dash") }}
                  </FieldLabel>
                  <ExpressionEditor
                    :model-value="s.dash ?? ''"
                    result-type="list"
                    :extra-vars="dataSourceVars"
                    unlisted-vars-are-dyn
                    placeholder="留空为实线，如 [4, 4]"
                    @update:model-value="(v) => setYDash(i, v)"
                  />
                </Field>
              </template>

              <!-- area -->
              <div
                v-else-if="s.chart === 'area'"
                class="grid grid-cols-2 gap-3"
              >
                <Field orientation="vertical">
                  <FieldLabel class="text-xs text-zinc-500">
                    <template
                      v-if="yDescription('lineColor')"
                      #tooltip
                    >
                      <Markdown
                        :source="yDescription('lineColor')"
                        block
                        class="prose prose-sm prose-zinc"
                      />
                    </template>
                    {{ yTitle("lineColor") }}
                  </FieldLabel>
                  <ColorPicker
                    :model-value="s.lineColor ?? ''"
                    placeholder="同填充色"
                    @update:model-value="(v) => setYLineColor(i, v)"
                  />
                </Field>
                <Field orientation="vertical">
                  <FieldLabel class="text-xs text-zinc-500">
                    <template
                      v-if="yDescription('lineWidth')"
                      #tooltip
                    >
                      <Markdown
                        :source="yDescription('lineWidth')"
                        block
                        class="prose prose-sm prose-zinc"
                      />
                    </template>
                    {{ yTitle("lineWidth") }}
                  </FieldLabel>
                  <InputGroup>
                    <InputGroupNumberField
                      :model-value="s.lineWidth"
                      :min="1"
                      @update:model-value="(v) => setYLineWidth(i, v)"
                    />
                  </InputGroup>
                </Field>
              </div>

              <!-- grouped / stacked bar -->
              <Field
                v-else-if="s.chart === 'groupedBar' || s.chart === 'stackedBar'"
                orientation="vertical"
              >
                <FieldLabel class="text-xs text-zinc-500">
                  <template
                    v-if="yDescription('width')"
                    #tooltip
                  >
                    <Markdown
                      :source="yDescription('width')"
                      block
                      class="prose prose-sm prose-zinc"
                    />
                  </template>
                  {{ yTitle("width") }}
                </FieldLabel>
                <ExpressionEditor
                  :model-value="s.width ?? ''"
                  result-type="number"
                  :extra-vars="dataSourceVars"
                  unlisted-vars-are-dyn
                  placeholder="留空自动，如 24"
                  @update:model-value="(v) => setYWidth(i, v)"
                />
              </Field>

              <!-- scatter -->
              <Field
                v-else-if="s.chart === 'scatter'"
                orientation="vertical"
              >
                <FieldLabel class="text-xs text-zinc-500">
                  <template
                    v-if="yDescription('size')"
                    #tooltip
                  >
                    <Markdown
                      :source="yDescription('size')"
                      block
                      class="prose prose-sm prose-zinc"
                    />
                  </template>
                  {{ yTitle("size") }}
                </FieldLabel>
                <ExpressionEditor
                  :model-value="s.size ?? ''"
                  result-type="list"
                  :extra-vars="dataSourceVars"
                  unlisted-vars-are-dyn
                  placeholder="留空用默认大小，如 source1.map(r, r.weight)"
                  @update:model-value="(v) => setYSize(i, v)"
                />
              </Field>

              <Field orientation="vertical">
                <FieldLabel class="text-xs text-zinc-500">
                  <template
                    v-if="yDescription('label')"
                    #tooltip
                  >
                    <Markdown
                      :source="yDescription('label')"
                      block
                      class="prose prose-sm prose-zinc"
                    />
                  </template>
                  {{ yTitle("label") }}
                </FieldLabel>
                <LocaleField
                  translate-hint="chart series label"
                  :model-value="s.label"
                  @update:model-value="(v) => setYLabel(i, v)"
                />
              </Field>
            </div>
            <Button
              type="button"
              class="w-full justify-center"
              @click="addY()"
            >
              <Icon icon="fluent:add-20-regular" />
              <span>新增 Y</span>
            </Button>
          </div>
        </Field>
      </div>
    </div>
  </div>
</template>
