import { type ReactNode, useDeferredValue, useEffect, useMemo, useState } from 'react';

import { PRESET_CHARACTERS } from '../data/characterPresets';
import { getInventoryItemValue } from '../data/economy';
import { validateItemOverrides } from '../data/editorValidation';
import { getEquipmentSlotFromItem, getEquipmentSlotLabel } from '../data/equipmentEffects';
import { isInventoryItemUsable, resolveInventoryItemUseEffect } from '../data/inventoryEffects';
import {
  applyItemCatalogOverride,
  buildItemCatalogFromAssetPaths,
  createInventoryItemFromCatalogEntry,
  ITEM_CATALOG_API_PATH,
  ITEM_CATEGORY_OPTIONS,
  ITEM_OVERRIDES_API_PATH,
} from '../data/itemCatalog';
import { fetchJson, saveJsonObject } from '../editor/shared/jsonClient';
import { SectionCard as Section } from '../editor/shared/SectionCard';
import { type ItemCatalogOverride, type ItemRarity, type TimedBuildBuff,WorldType } from '../types';
import { PixelIcon } from './PixelIcon';

const ITEM_PREVIEW_CHARACTER = PRESET_CHARACTERS[0] ?? null;
const LIST_PREVIEW_LIMIT = 240;

type ItemCatalogAssetResponse = {
  assetPaths: string[];
};

const RARITY_OPTIONS: ItemRarity[] = ['common', 'uncommon', 'rare', 'epic', 'legendary'];
const RARITY_LABELS: Record<ItemRarity, string> = {
    common: '普通',
    uncommon: '不普通',
    rare: '稀有',
    epic: '史诗',
    legendary: '传奇',
  };

function arraysEqual(left: string[], right: string[]) {
  if (left.length !== right.length) return false;
  return left.every((value, index) => value === right[index]);
}

function parseTagsInput(value: string) {
  return [...new Set(
    value
      .split(/[\n,]/u)
      .map(tag => tag.trim())
      .filter(Boolean),
  )];
}

function tagsInputValue(tags: string[]) {
  return tags.join(', ');
}

function parseBuildBuffLines(
  value: string,
  sourceType: TimedBuildBuff['sourceType'],
  sourceId: string,
) {
  return value
    .split('\n')
    .map(line => line.trim())
    .filter(Boolean)
    .map((line, index) => {
      const [namePart, tagsPart, durationPart] = line.split('|').map(part => part.trim());
      const tags = parseTagsInput(tagsPart ?? '');
      const durationTurns = Math.max(1, Number(durationPart ?? '1') || 1);
      return {
        id: `${sourceId}-buff-${index + 1}`,
        sourceType,
        sourceId,
        name: namePart || `${sourceId}-buff-${index + 1}`,
        tags,
        durationTurns,
      } satisfies TimedBuildBuff;
    })
    .filter(buff => buff.tags.length > 0);
}

function buildBuffLinesValue(buffs: TimedBuildBuff[] | null | undefined) {
  return (buffs ?? [])
    .map(buff => `${buff.name}|${buff.tags.join(',')}|${buff.durationTurns}`)
    .join('\n');
}

function Label({ children }: { children: ReactNode }) {
  return <div className="mb-1 text-xs font-medium text-zinc-300">{children}</div>;
}

function TextInput({
  value,
  onChange,
  placeholder,
  disabled = false,
}: {
  value: string;
  onChange: (value: string) => void;
  placeholder?: string;
  disabled?: boolean;
}) {
  return (
    <input
      value={value}
      onChange={event => onChange(event.target.value)}
      placeholder={placeholder}
      disabled={disabled}
      className="w-full rounded-lg border border-white/10 bg-black/30 px-3 py-2 text-sm text-white outline-none transition focus:border-emerald-400/40 disabled:cursor-not-allowed disabled:opacity-60"
    />
  );
}

function TextArea({
  value,
  onChange,
  rows = 4,
}: {
  value: string;
  onChange: (value: string) => void;
  rows?: number;
}) {
  return (
    <textarea
      rows={rows}
      value={value}
      onChange={event => onChange(event.target.value)}
      className="w-full rounded-lg border border-white/10 bg-black/30 px-3 py-2 text-sm leading-relaxed text-white outline-none transition focus:border-emerald-400/40"
    />
  );
}

function Select({
  value,
  onChange,
  options,
}: {
  value: string;
  onChange: (value: string) => void;
  options: Array<{ label: string; value: string }>;
}) {
  return (
    <select
      value={value}
      onChange={event => onChange(event.target.value)}
      className="w-full rounded-lg border border-white/10 bg-black/30 px-3 py-2 text-sm text-white outline-none transition focus:border-emerald-400/40"
    >
      {options.map(option => (
        <option key={`${option.value}-${option.label}`} value={option.value}>
          {option.label}
        </option>
      ))}
    </select>
  );
}

export function ItemCatalogEditor() {
  const [assetPaths, setAssetPaths] = useState<string[]>([]);
  const [overrideMap, setOverrideMap] = useState<Record<string, ItemCatalogOverride>>({});
  const [selectedItemId, setSelectedItemId] = useState('');
  const [searchText, setSearchText] = useState('');
  const [categoryFilter, setCategoryFilter] = useState('ALL');
  const [rarityFilter, setRarityFilter] = useState<'ALL' | ItemRarity>('ALL');
  const [previewWorld, setPreviewWorld] = useState<WorldType>(WorldType.WUXIA);
  const [isLoading, setIsLoading] = useState(true);
  const [isSaving, setIsSaving] = useState(false);
  const [loadError, setLoadError] = useState<string | null>(null);
  const [saveMessage, setSaveMessage] = useState<string | null>(null);
  const deferredSearchText = useDeferredValue(searchText);

  useEffect(() => {
    let disposed = false;

    const load = async () => {
      setIsLoading(true);
      setLoadError(null);

      try {
        const [catalogResponse, overridesResponse] = await Promise.all([
          fetchJson<ItemCatalogAssetResponse>(ITEM_CATALOG_API_PATH),
          fetchJson<Record<string, ItemCatalogOverride>>(ITEM_OVERRIDES_API_PATH),
        ]);

        if (disposed) return;

        const nextAssetPaths = catalogResponse.assetPaths ?? [];
        setAssetPaths(nextAssetPaths);
        setOverrideMap(overridesResponse ?? {});
        setSelectedItemId(current => current || (buildItemCatalogFromAssetPaths(nextAssetPaths)[0]?.id ?? ''));
      } catch (error) {
        if (disposed) return;
        setLoadError(error instanceof Error ? error.message : '物品目录加载失败');
      } finally {
        if (!disposed) {
          setIsLoading(false);
        }
      }
    };

    void load();

    return () => {
      disposed = true;
    };
  }, []);

  const baseItems = useMemo(
    () => buildItemCatalogFromAssetPaths(assetPaths),
    [assetPaths],
  );

  const baseItemMap = useMemo(
    () => new Map(baseItems.map(item => [item.id, item])),
    [baseItems],
  );

  const effectiveItems = useMemo(
    () => baseItems.map(item => applyItemCatalogOverride(item, overrideMap[item.id])),
    [baseItems, overrideMap],
  );

  const filteredItems = useMemo(() => {
    const query = deferredSearchText.trim().toLowerCase();

    return effectiveItems.filter(item => {
      if (categoryFilter !== 'ALL' && item.category !== categoryFilter) return false;
      if (rarityFilter !== 'ALL' && item.rarity !== rarityFilter) return false;
      if (!query) return true;

      const haystack = [
        item.name,
        item.category,
        item.rarity,
        item.description,
        item.sourcePath,
        ...item.tags,
      ].join(' ').toLowerCase();

      return haystack.includes(query);
    });
  }, [categoryFilter, deferredSearchText, effectiveItems, rarityFilter]);

  const visibleItems = useMemo(
    () => filteredItems.slice(0, LIST_PREVIEW_LIMIT),
    [filteredItems],
  );

  useEffect(() => {
    if (!effectiveItems.length) {
      setSelectedItemId('');
      return;
    }

    if (!selectedItemId || !baseItemMap.has(selectedItemId)) {
      setSelectedItemId(effectiveItems[0]?.id ?? '');
    }
  }, [baseItemMap, effectiveItems, selectedItemId]);

  const selectedBaseItem = selectedItemId ? baseItemMap.get(selectedItemId) ?? null : null;
  const selectedItem = selectedBaseItem
    ? applyItemCatalogOverride(selectedBaseItem, overrideMap[selectedBaseItem.id])
    : null;
  const selectedOverride = selectedItemId ? overrideMap[selectedItemId] ?? null : null;

  const previewInventoryItem = useMemo(
    () => selectedItem ? createInventoryItemFromCatalogEntry(selectedItem, 1, previewWorld) : null,
    [previewWorld, selectedItem],
  );
  const worldProfile = selectedItem?.worldProfiles?.[previewWorld] ?? null;

  const previewUseEffect = useMemo(
    () => (previewInventoryItem && ITEM_PREVIEW_CHARACTER)
      ? resolveInventoryItemUseEffect(previewInventoryItem, ITEM_PREVIEW_CHARACTER)
      : null,
    [previewInventoryItem],
  );

  const previewEquipmentSlot = useMemo(
    () => previewInventoryItem
      ? getEquipmentSlotFromItem(previewInventoryItem)
      : null,
    [previewInventoryItem],
  );

  const updateSelectedOverride = <K extends keyof ItemCatalogOverride>(
    key: K,
    value: ItemCatalogOverride[K],
  ) => {
    if (!selectedBaseItem) return;

    setOverrideMap(current => {
      const nextOverride = {
        ...(current[selectedBaseItem.id] ?? {}),
        [key]: value,
      };

      const normalizedOverride: ItemCatalogOverride = {...nextOverride};

      if ((normalizedOverride.name ?? selectedBaseItem.name) === selectedBaseItem.name) {
        delete normalizedOverride.name;
      }
      if ((normalizedOverride.category ?? selectedBaseItem.category) === selectedBaseItem.category) {
        delete normalizedOverride.category;
      }
      if ((normalizedOverride.rarity ?? selectedBaseItem.rarity) === selectedBaseItem.rarity) {
        delete normalizedOverride.rarity;
      }
      if ((normalizedOverride.description ?? selectedBaseItem.description) === selectedBaseItem.description) {
        delete normalizedOverride.description;
      }
      if (
        normalizedOverride.tags &&
        arraysEqual(normalizedOverride.tags, selectedBaseItem.tags)
      ) {
        delete normalizedOverride.tags;
      }

      const hasOverride = Object.keys(normalizedOverride).length > 0;
      if (!hasOverride) {
        const { [selectedBaseItem.id]: _removed, ...rest } = current;
        return rest;
      }

      return {
        ...current,
        [selectedBaseItem.id]: normalizedOverride,
      };
    });
  };

  const updateSelectedStatProfileField = (
    key: 'maxHpBonus' | 'maxManaBonus' | 'outgoingDamageBonus' | 'incomingDamageMultiplier',
    value: number,
  ) => {
    if (!selectedItem) return;
    const nextProfile = {
      ...(selectedItem.statProfile ?? {}),
      [key]: value,
    };
    updateSelectedOverride('statProfile', nextProfile);
  };

  const updateSelectedUseProfileField = (
    key: 'hpRestore' | 'manaRestore' | 'cooldownReduction',
    value: number,
  ) => {
    if (!selectedItem) return;
    const nextProfile = {
      ...(selectedItem.useProfile ?? {}),
      [key]: value,
      buildBuffs: selectedItem.useProfile?.buildBuffs ?? [],
    };
    updateSelectedOverride('useProfile', nextProfile);
  };

  const updateSelectedUseProfileBuffs = (value: string) => {
    if (!selectedItem) return;
    const nextProfile = {
      ...(selectedItem.useProfile ?? {}),
      hpRestore: selectedItem.useProfile?.hpRestore ?? 0,
      manaRestore: selectedItem.useProfile?.manaRestore ?? 0,
      cooldownReduction: selectedItem.useProfile?.cooldownReduction ?? 0,
      buildBuffs: parseBuildBuffLines(value, 'item', selectedItem.id),
    };
    updateSelectedOverride('useProfile', nextProfile);
  };

  const updateSelectedBuildProfileField = (
    key: 'role' | 'setId' | 'setName' | 'pieceName' | 'forgeRank',
    value: string | number,
  ) => {
    if (!selectedItem) return;
    const nextProfile = {
      ...(selectedItem.buildProfile ?? { role: '', tags: [], synergy: [], craftTags: [], forgeRank: 0 }),
      [key]: value,
      tags: selectedItem.buildProfile?.tags ?? [],
      synergy: selectedItem.buildProfile?.synergy ?? [],
      craftTags: selectedItem.buildProfile?.craftTags ?? [],
    };
    updateSelectedOverride('buildProfile', nextProfile);
  };

  const updateSelectedBuildProfileTags = (key: 'tags' | 'synergy' | 'craftTags', value: string) => {
    if (!selectedItem) return;
    const nextProfile = {
      ...(selectedItem.buildProfile ?? { role: '', tags: [], synergy: [], craftTags: [], forgeRank: 0 }),
      role: selectedItem.buildProfile?.role ?? '',
      tags: key === 'tags' ? parseTagsInput(value) : (selectedItem.buildProfile?.tags ?? []),
      synergy: key === 'synergy' ? parseTagsInput(value) : (selectedItem.buildProfile?.synergy ?? []),
      craftTags: key === 'craftTags' ? parseTagsInput(value) : (selectedItem.buildProfile?.craftTags ?? []),
      forgeRank: selectedItem.buildProfile?.forgeRank ?? 0,
    };
    updateSelectedOverride('buildProfile', nextProfile);
  };

  const resetSelectedOverride = () => {
    if (!selectedItemId) return;

    setOverrideMap(current => {
      const { [selectedItemId]: _removed, ...rest } = current;
      return rest;
    });
  };

  const handleSave = async () => {
    const validationErrors = validateItemOverrides(
      overrideMap,
      baseItems.map(item => item.id),
    );

    if (validationErrors.length > 0) {
      setSaveMessage(validationErrors.slice(0, 3).join(' | '));
      setTimeout(() => setSaveMessage(null), 5000);
      return;
    }

    setIsSaving(true);
    setSaveMessage(null);

    try {
      await saveJsonObject(ITEM_OVERRIDES_API_PATH, overrideMap as Record<string, unknown>);
      setSaveMessage('物品覆盖已保存到 src/data/itemOverrides.json。');
      setTimeout(() => setSaveMessage(null), 5000);
    } catch (error) {
      setSaveMessage(error instanceof Error ? error.message : '保存失败');
      setTimeout(() => setSaveMessage(null), 5000);
    } finally {
      setIsSaving(false);
    }
  };

  const categoryOptions = [
    { label: '全部分类', value: 'ALL' },
    ...ITEM_CATEGORY_OPTIONS.map(category => ({ label: category, value: category })),
  ];

  const rarityOptions = [
    { label: '全部稀有度', value: 'ALL' },
    ...RARITY_OPTIONS.map(rarity => ({ label: rarity, value: rarity })),
  ];

  if (isLoading) {
    return (
      <div className="rounded-2xl border border-white/10 bg-black/20 p-6 text-sm text-zinc-300">
        正在加载物品目录...
      </div>
    );
  }

  if (loadError) {
    return (
      <div className="rounded-2xl border border-rose-400/20 bg-rose-500/10 p-6 text-sm text-rose-100">
        {loadError}
      </div>
    );
  }

  return (
    <div className="grid gap-6 xl:grid-cols-[360px_1fr_420px]">
      <Section title="物品列表" description="基于 public/Icons 下的全部 png 素材自动构建物品目录，可按名称、路径、分类和稀有度筛选。">
        <div className="grid gap-3">
          <div>
            <Label>搜索</Label>
            <TextInput
              value={searchText}
              onChange={setSearchText}
              placeholder="按名称、路径、标签搜索"
            />
          </div>
          <div className="grid gap-3 md:grid-cols-2">
            <div>
              <Label>分类筛选</Label>
              <Select value={categoryFilter} onChange={setCategoryFilter} options={categoryOptions} />
            </div>
            <div>
              <Label>稀有度筛选</Label>
              <Select value={rarityFilter} onChange={value => setRarityFilter(value as 'ALL' | ItemRarity)} options={rarityOptions} />
            </div>
          </div>
        </div>

        <div className="mt-4 rounded-xl border border-white/10 bg-white/[0.03] px-3 py-2 text-xs text-zinc-400">
          总物品 {effectiveItems.length}，当前匹配 {filteredItems.length}，列表预渲染前 {Math.min(visibleItems.length, LIST_PREVIEW_LIMIT)} 条。
        </div>

        <div className="mt-4 max-h-[70vh] space-y-2 overflow-y-auto pr-1 scrollbar-hide">
          {visibleItems.map(item => {
            const selected = item.id === selectedItemId;
            const overridden = Boolean(overrideMap[item.id]);
            return (
              <button
                key={item.id}
                type="button"
                onClick={() => setSelectedItemId(item.id)}
                className={`flex w-full items-center gap-3 rounded-xl border px-3 py-2 text-left transition ${
                  selected
                    ? 'border-emerald-400/40 bg-emerald-500/10'
                    : 'border-white/8 bg-black/20 hover:border-white/15'
                }`}
              >
                <div className="flex h-12 w-12 shrink-0 items-center justify-center rounded-lg border border-white/10 bg-black/35">
                  <PixelIcon src={item.iconSrc} className="h-9 w-9" />
                </div>
                <div className="min-w-0 flex-1">
                  <div className="truncate text-sm font-semibold text-white">{item.name}</div>
                  <div className="mt-1 truncate text-[10px] text-zinc-500">{item.sourcePath}</div>
                  <div className="mt-1 flex flex-wrap gap-1.5">
                    <span className="rounded-full border border-white/10 bg-white/[0.04] px-2 py-0.5 text-[10px] text-zinc-300">
                      {item.category}
                    </span>
                    <span className="rounded-full border border-white/10 bg-white/[0.04] px-2 py-0.5 text-[10px] text-zinc-300">
                      {item.rarity}
                    </span>
                    {overridden && (
                      <span className="rounded-full border border-amber-400/20 bg-amber-500/10 px-2 py-0.5 text-[10px] text-amber-100">
                        已覆盖
                      </span>
                    )}
                  </div>
                </div>
              </button>
            );
          })}
        </div>
      </Section>

      <Section title="物品预览" description="这里会实时预览当前素材构建出的物品效果，包括图标、系统推断结果以及一张背包卡片。">
        {selectedItem ? (
          <div className="space-y-5">
            <div className="grid gap-4 lg:grid-cols-[220px_1fr]">
              <div className="flex min-h-[240px] items-center justify-center rounded-2xl border border-white/10 bg-[radial-gradient(circle_at_top,rgba(255,255,255,0.12),transparent_45%),linear-gradient(180deg,#171a22,#0d1016)] p-6">
                <PixelIcon src={selectedItem.iconSrc} className="h-40 w-40" />
              </div>

              <div className="space-y-3 rounded-2xl border border-white/10 bg-black/20 p-4">
                <div>
                  <div className="text-xs uppercase tracking-[0.2em] text-zinc-500">{selectedItem.category}</div>
                  <div className="mt-1 text-xl font-semibold text-white">{selectedItem.name}</div>
                  <div className="mt-1 text-xs text-zinc-500">{selectedItem.sourcePath}</div>
                </div>

                <div className="max-w-[12rem]">
                  <Label>世界语境</Label>
                  <Select
                    value={previewWorld}
                    onChange={value => setPreviewWorld(value as WorldType)}
                    options={[
                      { label: '武侠', value: WorldType.WUXIA },
                      { label: '仙侠', value: WorldType.XIANXIA },
                    ]}
                  />
                </div>

                <div className="flex flex-wrap gap-2">
                  <span className="rounded-full border border-white/10 bg-white/[0.04] px-2 py-1 text-[11px] text-zinc-200">
                    稀有度: {RARITY_LABELS[selectedItem.rarity]}
                  </span>
                  <span className="rounded-full border border-white/10 bg-white/[0.04] px-2 py-1 text-[11px] text-zinc-200">
                    价值: {getInventoryItemValue(previewInventoryItem!)}
                  </span>
                  <span className="rounded-full border border-white/10 bg-white/[0.04] px-2 py-1 text-[11px] text-zinc-200">
                    可使用: {isInventoryItemUsable(previewInventoryItem!) ? '是' : '否'}
                  </span>
                  <span className="rounded-full border border-white/10 bg-white/[0.04] px-2 py-1 text-[11px] text-zinc-200">
                    可装备: {previewEquipmentSlot ? getEquipmentSlotLabel(previewEquipmentSlot) : '否'}
                  </span>
                  <span className="rounded-full border border-white/10 bg-white/[0.04] px-2 py-1 text-[11px] text-zinc-200">
                    世界: {selectedItem.worldAffinity === 'neutral' ? '中立' : selectedItem.worldAffinity === 'wuxia' ? '武侠' : selectedItem.worldAffinity === 'xianxia' ? '仙侠' : '中立'}
                  </span>
                </div>

                <p className="text-sm leading-relaxed text-zinc-300">{selectedItem.description}</p>
                {worldProfile && (
                  <div className="rounded-xl border border-white/10 bg-white/[0.03] px-3 py-3">
                    <div className="text-[11px] uppercase tracking-[0.18em] text-zinc-500">
                      {previewWorld === WorldType.WUXIA ? '武侠命名' : '仙侠命名'}
                    </div>
                    <div className="mt-1 text-sm font-semibold text-white">{worldProfile.name}</div>
                    <div className="mt-2 text-sm leading-relaxed text-zinc-300">{worldProfile.description}</div>
                  </div>
                )}

                <div className="flex flex-wrap gap-2">
                  {selectedItem.tags.length > 0 ? selectedItem.tags.map(tag => (
                    <span
                      key={`${selectedItem.id}-${tag}`}
                      className="rounded-full border border-white/10 bg-black/25 px-2 py-1 text-[10px] text-zinc-300"
                    >
                      {tag}
                    </span>
                  )) : (
                    <span className="rounded-full border border-white/10 bg-black/25 px-2 py-1 text-[10px] text-zinc-300">
                      无标签
                    </span>
                  )}
                </div>
              </div>
            </div>

            <div className="grid gap-4 lg:grid-cols-3">
              <div className="rounded-2xl border border-white/10 bg-black/20 p-4">
                <div className="mb-2 text-xs font-semibold uppercase tracking-[0.2em] text-zinc-500">属性设计</div>
                <div className="space-y-1 text-sm text-zinc-300">
                  <div>生命值: {selectedItem.statProfile?.maxHpBonus ?? 0}</div>
                  <div>内力: {selectedItem.statProfile?.maxManaBonus ?? 0}</div>
                  <div>伤害: {selectedItem.statProfile?.outgoingDamageBonus ?? 0}</div>
                  <div>防御: {selectedItem.statProfile?.incomingDamageMultiplier ?? 1}</div>
                </div>
              </div>

              <div className="rounded-2xl border border-white/10 bg-black/20 p-4">
                <div className="mb-2 text-xs font-semibold uppercase tracking-[0.2em] text-zinc-500">使用效果</div>
                {selectedItem.useProfile ? (
                  <div className="space-y-1 text-sm text-zinc-300">
                    <div>生命值恢复: {selectedItem.useProfile.hpRestore ?? 0}</div>
                    <div>内力恢复: {selectedItem.useProfile.manaRestore ?? 0}</div>
                    <div>冷却减少: {selectedItem.useProfile.cooldownReduction ?? 0}</div>
                    <div>构筑增益: {(selectedItem.useProfile.buildBuffs ?? []).map(buff => buff.name).join(' / ') || '无'}</div>
                  </div>
                ) : (
                  <div className="text-sm text-zinc-500">无即时使用效果</div>
                )}
              </div>

              <div className="rounded-2xl border border-white/10 bg-black/20 p-4">
                <div className="mb-2 text-xs font-semibold uppercase tracking-[0.2em] text-zinc-500">构筑 / 套装</div>
                {selectedItem.buildProfile ? (
                  <div className="space-y-1 text-sm text-zinc-300">
                    <div>角色: {selectedItem.buildProfile.role}</div>
                    <div>套装: {selectedItem.buildProfile.setName ?? '无'}</div>
                    <div>部件: {selectedItem.buildProfile.pieceName ?? '独立'}</div>
                    <div>{(selectedItem.buildProfile.synergy ?? []).join(' / ') || '无'}</div>
                    <div>工艺标签: {(selectedItem.buildProfile.craftTags ?? []).join(' / ') || '无'}</div>
                    <div>锻造等级: {selectedItem.buildProfile.forgeRank ?? 0}</div>
                  </div>
                ) : (
                  <div className="text-sm text-zinc-500">无构筑信息</div>
                )}
              </div>
            </div>

            <div className="rounded-2xl border border-white/10 bg-black/20 p-4">
              <div className="mb-3 text-xs font-semibold uppercase tracking-[0.2em] text-zinc-500">背包卡片预览</div>
              <div className="flex items-center gap-4 rounded-2xl border border-white/10 bg-black/25 p-4">
                <div className="relative flex h-24 w-24 shrink-0 items-center justify-center rounded-2xl border border-white/10 bg-white/[0.04]">
                  <PixelIcon src={selectedItem.iconSrc} className="h-14 w-14" />
                  <div className="absolute bottom-2 right-2 rounded-full border border-black/30 bg-black/65 px-1.5 py-0.5 text-[10px] font-semibold text-white">
                    1
                  </div>
                </div>
                <div className="min-w-0 flex-1 space-y-2">
                  <div className="text-base font-semibold text-white">{selectedItem.name}</div>
                  <div className="text-sm text-zinc-400">{selectedItem.category} / {RARITY_LABELS[selectedItem.rarity]}</div>
                  {previewUseEffect && (
                    <div className="text-sm text-zinc-300">
                      效果预估：生命 +{previewUseEffect.hpRestore} / 灵力 +{previewUseEffect.manaRestore} / 冷却 -{previewUseEffect.cooldownReduction}
                    </div>
                  )}
                  {!previewUseEffect && (
                    <div className="text-sm text-zinc-400">
                      当前推断为非即时使用型物品。
                    </div>
                  )}
                </div>
              </div>
            </div>
          </div>
        ) : (
          <div className="rounded-xl border border-white/10 bg-black/20 px-4 py-6 text-sm text-zinc-400">
            没有可预览的物品。
          </div>
        )}
      </Section>

      <Section title="物品字段" description="编辑当前物品的覆盖字段。未修改的字段不会写入 override，重置后会恢复自动生成值。">
        {selectedBaseItem && selectedItem ? (
          <div className="space-y-4">
            <div>
              <Label>物品 ID</Label>
              <TextInput value={selectedItem.id} onChange={() => undefined} disabled />
            </div>

            <div>
              <Label>素材路径</Label>
              <TextInput value={selectedItem.sourcePath} onChange={() => undefined} disabled />
            </div>

            <div>
              <Label>名称</Label>
              <TextInput
                value={selectedItem.name}
                onChange={value => updateSelectedOverride('name', value)}
              />
            </div>

            <div className="grid gap-4 md:grid-cols-2">
              <div>
                <Label>分类</Label>
                <Select
                  value={selectedItem.category}
                  onChange={value => updateSelectedOverride('category', value)}
                  options={ITEM_CATEGORY_OPTIONS.map(category => ({ label: category, value: category }))}
                />
              </div>

              <div>
                <Label>稀有度</Label>
                <Select
                  value={selectedItem.rarity}
                  onChange={value => updateSelectedOverride('rarity', value as ItemRarity)}
                  options={RARITY_OPTIONS.map(rarity => ({ label: RARITY_LABELS[rarity], value: rarity }))}
                />
              </div>
            </div>

            <div>
              <Label>标签</Label>
              <TextArea
                value={tagsInputValue(selectedItem.tags)}
                onChange={value => updateSelectedOverride('tags', parseTagsInput(value))}
                rows={4}
              />
              <div className="mt-1 text-xs text-zinc-500">支持逗号或换行分隔。</div>
            </div>

            <div>
              <Label>描述</Label>
              <TextArea
                value={selectedItem.description}
                onChange={value => updateSelectedOverride('description', value)}
                rows={5}
              />
            </div>

            <div className="grid gap-4 md:grid-cols-2">
              <div>
                <Label>生命上限加成</Label>
                <TextInput
                  value={String(selectedItem.statProfile?.maxHpBonus ?? 0)}
                  onChange={value => updateSelectedStatProfileField('maxHpBonus', Number(value) || 0)}
                />
              </div>
              <div>
                <Label>灵力上限加成</Label>
                <TextInput
                  value={String(selectedItem.statProfile?.maxManaBonus ?? 0)}
                  onChange={value => updateSelectedStatProfileField('maxManaBonus', Number(value) || 0)}
                />
              </div>
              <div>
                <Label>输出倍率加成</Label>
                <TextInput
                  value={String(selectedItem.statProfile?.outgoingDamageBonus ?? 0)}
                  onChange={value => updateSelectedStatProfileField('outgoingDamageBonus', Number(value) || 0)}
                />
              </div>
              <div>
                <Label>承伤倍率</Label>
                <TextInput
                  value={String(selectedItem.statProfile?.incomingDamageMultiplier ?? 1)}
                  onChange={value => updateSelectedStatProfileField('incomingDamageMultiplier', Number(value) || 1)}
                />
              </div>
            </div>

            <div className="grid gap-4 md:grid-cols-2">
              <div>
                <Label>使用时恢复生命</Label>
                <TextInput
                  value={String(selectedItem.useProfile?.hpRestore ?? 0)}
                  onChange={value => updateSelectedUseProfileField('hpRestore', Number(value) || 0)}
                />
              </div>
              <div>
                <Label>使用时恢复灵力</Label>
                <TextInput
                  value={String(selectedItem.useProfile?.manaRestore ?? 0)}
                  onChange={value => updateSelectedUseProfileField('manaRestore', Number(value) || 0)}
                />
              </div>
              <div>
                <Label>使用减少冷却</Label>
                <TextInput
                  value={String(selectedItem.useProfile?.cooldownReduction ?? 0)}
                  onChange={value => updateSelectedUseProfileField('cooldownReduction', Number(value) || 0)}
                />
              </div>
            </div>

            <div>
              <Label>使用时附加构筑增益（每行：名称|标签1,标签2|回合）</Label>
              <TextArea
                value={buildBuffLinesValue(selectedItem.useProfile?.buildBuffs)}
                onChange={updateSelectedUseProfileBuffs}
                rows={4}
              />
            </div>

            <div className="grid gap-4 md:grid-cols-2">
              <div>
                <Label>构筑角色</Label>
                <TextInput
                  value={selectedItem.buildProfile?.role ?? ''}
                  onChange={value => updateSelectedBuildProfileField('role', value)}
                />
              </div>
              <div>
                <Label>套装 ID</Label>
                <TextInput
                  value={selectedItem.buildProfile?.setId ?? ''}
                  onChange={value => updateSelectedBuildProfileField('setId', value)}
                />
              </div>
              <div>
                <Label>套装名称</Label>
                <TextInput
                  value={selectedItem.buildProfile?.setName ?? ''}
                  onChange={value => updateSelectedBuildProfileField('setName', value)}
                />
              </div>
              <div>
                <Label>部件名称</Label>
                <TextInput
                  value={selectedItem.buildProfile?.pieceName ?? ''}
                  onChange={value => updateSelectedBuildProfileField('pieceName', value)}
                />
              </div>
              <div>
                <Label>锻造等级</Label>
                <TextInput
                  value={String(selectedItem.buildProfile?.forgeRank ?? 0)}
                  onChange={value => updateSelectedBuildProfileField('forgeRank', Number(value) || 0)}
                />
              </div>
            </div>

            <div>
              <Label>构筑标签</Label>
              <TextArea
                value={tagsInputValue(selectedItem.buildProfile?.tags ?? [])}
                onChange={value => updateSelectedBuildProfileTags('tags', value)}
                rows={3}
              />
            </div>

            <div>
              <Label>协同标签</Label>
              <TextArea
                value={tagsInputValue(selectedItem.buildProfile?.synergy ?? [])}
                onChange={value => updateSelectedBuildProfileTags('synergy', value)}
                rows={3}
              />
            </div>

            <div>
              <Label>工艺标签</Label>
              <TextArea
                value={tagsInputValue(selectedItem.buildProfile?.craftTags ?? [])}
                onChange={value => updateSelectedBuildProfileTags('craftTags', value)}
                rows={3}
              />
            </div>

            <div className="rounded-xl border border-white/10 bg-white/[0.03] px-3 py-2 text-xs text-zinc-400">
              当前状态：{selectedOverride ? '该物品有覆盖字段，保存后会写入 itemOverrides.json。' : '当前全部字段都在使用自动生成值。'}
            </div>

            <div className="flex flex-wrap items-center gap-3">
              <button
                type="button"
                onClick={handleSave}
                disabled={isSaving}
                className="rounded-lg bg-emerald-500 px-4 py-2 text-sm font-medium text-black transition hover:bg-emerald-400 disabled:cursor-not-allowed disabled:opacity-60"
              >
                {isSaving ? '保存中...' : '保存物品覆盖'}
              </button>
              <button
                type="button"
                onClick={resetSelectedOverride}
                disabled={!selectedOverride}
                className={`rounded-lg border px-4 py-2 text-sm transition ${
                  selectedOverride
                    ? 'border-white/15 bg-black/20 text-white hover:border-white/30'
                    : 'border-white/8 bg-black/20 text-zinc-500'
                }`}
              >
                重置当前物品覆盖
              </button>
              {saveMessage && <div className="text-xs text-zinc-400">{saveMessage}</div>}
            </div>
          </div>
        ) : (
          <div className="rounded-xl border border-white/10 bg-black/20 px-4 py-6 text-sm text-zinc-400">
            请选择一个物品开始编辑。
          </div>
        )}
      </Section>
    </div>
  );
}
