<script lang="ts">
  import {
    type Node,
    useNodesData,
    useStore,
    useSvelteFlow,
  } from '@xyflow/svelte';

  import type {
    Parameter,
    SelectItem,
    TinyflowNodeData,
  } from '#types';
  import { getCurrentNodeId } from '#components/utils/NodeUtils';
  import { MixedInput, Select } from '../../base';
  import {
    buildLoopItemParameter,
    resolveLoopInputs,
  } from '../../../utils/loopScope';
  import { useRefOptions } from '../../utils/useRefOptions.svelte';
  import { filterRefOptionsByDataType } from '../../utils/refOptionFilter';

  const { data }: { data: TinyflowNodeData } = $props();
  const currentNodeId = getCurrentNodeId();
  const currentNode = useNodesData(currentNodeId);
  const { nodes } = $derived(useStore());
  const { updateNodeData } = useSvelteFlow();
  const referenceOptions = useRefOptions();

  const loopNode = $derived.by(() => {
    return (
      currentNode.current || {
        id: currentNodeId,
        type: 'loopNode',
        position: { x: 0, y: 0 },
        data,
      }
    ) as Node;
  });
  const loopInputs = $derived.by(() =>
    resolveLoopInputs(loopNode, nodes || []),
  );
  const loopItem = $derived.by(() =>
    buildLoopItemParameter(loopNode, nodes || []),
  );
  const countOptions = $derived.by(() =>
    filterRefOptionsByDataType(
      referenceOptions.current,
      ['Number'],
      loopInputs.count?.ref || '',
    ),
  );
  const itemsOptions = $derived.by(() =>
    filterRefOptionsByDataType(
      referenceOptions.current,
      ['Array'],
      loopInputs.items?.ref || '',
    ),
  );

  const countType = $derived<'fixed' | 'ref'>(
    loopInputs.count?.refType === 'ref' ? 'ref' : 'fixed',
  );
  const countTextValue = $derived(
    loopInputs.count?.refType === 'fixed'
      ? String(loopInputs.count.value || '')
      : '',
  );
  const countRefValue = $derived(
    loopInputs.count?.refType === 'ref'
      ? String(loopInputs.count.ref || '')
      : '',
  );
  const countHint = $derived.by(() => {
    const count = loopInputs.count;
    if (!count || count.refType !== 'fixed') {
      return '';
    }
    const value = Number(count.value);
    return Number.isInteger(value) && value >= 1 && value <= 300
      ? ''
      : '请输入 1～300 的整数';
  });
  const summary = $derived.by(() => {
    const count = loopInputs.count;
    const items = loopInputs.items;
    if (count && items) {
      return count.refType === 'fixed' && count.value
        ? `最多处理数组前 ${count.value} 项`
        : '按循环次数限制数组遍历';
    }
    if (items) {
      return '遍历数组全部元素';
    }
    if (count) {
      return count.refType === 'fixed' && count.value
        ? `循环 ${count.value} 次`
        : '按引用次数循环';
    }
    return '';
  });

  function updateInputs(
    updater: (inputs: {
      count?: Parameter;
      items?: Parameter;
    }) => {
      count?: Parameter;
      items?: Parameter;
    },
  ) {
    updateNodeData(currentNodeId, (node) => {
      const current = resolveLoopInputs(node, nodes || []);
      const next = updater({
        count: current.count,
        items: current.items,
      });
      const loopInputs: Record<string, Parameter> = {};
      if (next.count) {
        loopInputs.count = next.count;
      }
      if (next.items) {
        loopInputs.items = next.items;
      }
      return {
        loopInputs,
        loopVars: [],
      };
    });
  }

  function updateCountType(type: 'fixed' | 'ref') {
    updateInputs((current) => ({
      ...current,
      count:
        type === 'ref'
          ? {
              name: 'count',
              refType: 'ref',
              ref:
                current.count?.refType === 'ref'
                  ? current.count.ref || ''
                  : '',
              dataType: 'Number',
            }
          : {
              name: 'count',
              refType: 'fixed',
              value:
                current.count?.refType === 'fixed'
                  ? current.count.value || ''
                  : '',
              dataType: 'Number',
            },
    }));
  }

  function updateCountText(value: string) {
    const normalized = value.trim();
    updateInputs((current) => ({
      ...current,
      count: normalized
        ? {
            name: 'count',
            refType: 'fixed',
            value:
              /^\d+$/.test(normalized) &&
              Number(normalized) > 300
                ? '300'
                : normalized,
            dataType: 'Number',
          }
        : undefined,
    }));
  }

  function updateCountRef(value: string) {
    updateInputs((current) => ({
      ...current,
      count: value
        ? {
            name: 'count',
            refType: 'ref',
            ref: value,
            dataType: 'Number',
          }
        : undefined,
    }));
  }

  function updateItems(item: SelectItem) {
    updateInputs((current) => ({
      ...current,
      items: {
        name: 'items',
        refType: 'ref',
        ref: String(item.value),
        dataType: item.dataType || 'Array',
      },
    }));
  }

  function clearItems(event: MouseEvent) {
    event.stopPropagation();
    updateInputs((current) => ({
      ...current,
      items: undefined,
    }));
  }
</script>

<div class="loop-inputs">
  <div class="loop-field">
    <div class="loop-label">
      <span>循环次数</span>
      <span class="loop-optional">可选</span>
    </div>
    <MixedInput
      type={countType}
      textValue={countTextValue}
      refValue={countRefValue}
      refOptions={countOptions}
      placeholder="输入 1～300 或选择变量"
      onTypeChange={updateCountType}
      onTextChange={updateCountText}
      onRefChange={updateCountRef}
    />
    {#if countHint}
      <div class="loop-error" role="status">{countHint}</div>
    {/if}
  </div>

  <div class="loop-field">
    <div class="loop-label">
      <span>输入数组</span>
      <span class="loop-optional">可选</span>
    </div>
    <div class="loop-array-input">
      <Select
        items={itemsOptions}
        value={loopInputs.items?.ref ? [loopInputs.items.ref] : []}
        placeholder="选择要遍历的数组"
        variant="reference"
        style="width: 100%"
        onSelect={updateItems}
      />
      {#if loopInputs.items}
        <button
          type="button"
          class="loop-clear nopan nodrag"
          aria-label="清空输入数组"
          title="清空输入数组"
          onclick={clearItems}
        >
          <svg
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            stroke-width="2"
            aria-hidden="true"
          >
            <path d="M18 6 6 18M6 6l12 12" />
          </svg>
        </button>
      {/if}
    </div>
  </div>

  {#if summary}
    <div class="loop-summary">{summary}</div>
  {:else}
    <div class="loop-error" role="status">
      请至少配置循环次数或输入数组
    </div>
  {/if}

  <div class="loop-variables">
    <div class="loop-variables-title">循环体变量</div>
    <div class="loop-variable-list">
      <span class="loop-variable">
        <strong>index</strong>
        <small>Number</small>
      </span>
      {#if loopItem}
        <span class="loop-variable">
          <strong>loopItem</strong>
          <small>{loopItem.dataType}</small>
        </span>
      {/if}
    </div>
  </div>
</div>

<style lang="less">
  .loop-inputs {
    display: flex;
    flex-direction: column;
    gap: 16px;
  }

  .loop-field {
    display: flex;
    flex-direction: column;
    gap: 8px;
  }

  .loop-label {
    display: flex;
    align-items: center;
    gap: 8px;
    color: var(--tf-text-primary);
    font-size: 13px;
    font-weight: 500;
  }

  .loop-optional {
    color: var(--tf-text-muted);
    font-size: 12px;
    font-weight: 400;
  }

  .loop-array-input {
    position: relative;
    display: flex;
    min-width: 0;
  }

  .loop-array-input:has(.loop-clear) :global(.tf-select-input) {
    padding-right: 48px;
  }

  .loop-clear {
    position: absolute;
    top: 50%;
    right: 28px;
    z-index: 1;
    width: 24px;
    height: 24px;
    padding: 5px;
    border: 0;
    border-radius: 4px;
    background: transparent;
    color: var(--tf-text-muted);
    cursor: pointer;
    transform: translateY(-50%);
  }

  .loop-clear:hover {
    background: var(--tf-bg-hover);
    color: var(--tf-text-primary);
  }

  .loop-clear:focus-visible {
    outline: none;
    box-shadow: var(--tf-focus-shadow);
  }

  .loop-clear svg {
    width: 14px;
    height: 14px;
  }

  .loop-summary {
    margin-top: -8px;
    color: var(--tf-text-secondary);
    font-size: 12px;
    line-height: 1.5;
  }

  .loop-error {
    color: var(--tf-danger-soft-text);
    font-size: 12px;
    line-height: 1.5;
  }

  .loop-variables {
    padding-top: 16px;
    border-top: 1px solid var(--tf-border-color-soft);
  }

  .loop-variables-title {
    margin-bottom: 8px;
    color: var(--tf-text-secondary);
    font-size: 12px;
  }

  .loop-variable-list {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
  }

  .loop-variable {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-height: 24px;
    padding: 0 8px;
    border: 1px solid var(--tf-border-color-soft);
    border-radius: 6px;
    background: var(--tf-bg-surface-alt);
    color: var(--tf-text-primary);
    font-size: 12px;
  }

  .loop-variable strong {
    font-weight: 500;
  }

  .loop-variable small {
    color: var(--tf-text-muted);
    font-size: 11px;
  }
</style>
