import {
  ChevronDown,
  ClipboardList,
  ImageIcon,
  ImagePlus,
  X,
} from 'lucide-react';
import {
  type CSSProperties,
  type Dispatch,
  type ReactNode,
  type RefObject,
  type SetStateAction,
} from 'react';
import { createPortal } from 'react-dom';

import { PlatformActionButton } from '../common/PlatformActionButton';
import { PlatformFieldLabel } from '../common/PlatformFieldLabel';
import {
  PlatformFloatingMenu,
  PlatformFloatingMenuItem,
} from '../common/PlatformFloatingMenu';
import { PlatformIconButton } from '../common/PlatformIconButton';
import { PlatformInlineOptionButton } from '../common/PlatformInlineOptionButton';
import { PlatformStatusMessage } from '../common/PlatformStatusMessage';
import {
  PlatformSelectField,
  PlatformTextField,
} from '../common/PlatformTextField';
import { UnifiedModal } from '../common/UnifiedModal';
import { EditorIconButton } from './ImageCanvasEditorPrimitives';
import {
  CHARACTER_ANIMATION_ACTION_PROMPTS,
  CHARACTER_ANIMATION_DURATION_OPTIONS,
  CHARACTER_ANIMATION_RATIO_OPTIONS,
  CHARACTER_SPEC_VIEW_OPTIONS,
  DEFAULT_ICON_DESCRIPTIONS,
  EDITOR_IMAGE_DIMENSION_OPTIONS,
  EDITOR_IMAGE_MODEL_OPTIONS,
  ICON_DESCRIPTION_LIMIT,
  IMAGE_MODEL_NANOBANANA2,
  SPEC_GENERATION_COST,
  SPEC_TYPE_LABEL,
} from './ImageCanvasGenerationModel';
import type {
  CharacterAnimationPanelState,
  CanvasLayer,
  GenerateDialogState,
  QuickEditPanelState,
  SpecFormValues,
  SpecGenerationType,
  UploadTarget,
} from './ImageCanvasEditorTypes';

type ImageCanvasGenerationComposerViewProps = {
  specToolWrapRef: RefObject<HTMLSpanElement | null>;
  characterSpecButtonRef: RefObject<HTMLButtonElement | null>;
  characterReferenceButtonRef: RefObject<HTMLButtonElement | null>;
  iconSpecButtonRef: RefObject<HTMLButtonElement | null>;
  isSpecMenuOpen: boolean;
  isCharacterSpecMenuOpen: boolean;
  isCharacterReferenceMenuOpen: boolean;
  isIconSpecMenuOpen: boolean;
  isPickingCharacterSpecFromCanvas: boolean;
  isPickingCharacterReferenceFromCanvas: boolean;
  isPickingIconSpecFromCanvas: boolean;
  generateDialog: GenerateDialogState | null;
  generationComposerStyle: CSSProperties | null;
  iconComposerStyle: CSSProperties | null;
  quickEditPanel: QuickEditPanelState | null;
  quickEditSourceLayer: CanvasLayer | null;
  quickEditPanelStyle: CSSProperties | null;
  quickEditSizeOptions: string[];
  quickEditModelOptions: Array<{ label: string; value: string }>;
  characterAnimationPanel: CharacterAnimationPanelState | null;
  characterAnimationSourceLayer: CanvasLayer | null;
  characterAnimationPanelStyle: CSSProperties | null;
  characterAnimationPrice: number;
  setGenerateDialog: Dispatch<SetStateAction<GenerateDialogState | null>>;
  setQuickEditPanel: Dispatch<SetStateAction<QuickEditPanelState | null>>;
  setCharacterAnimationPanel: Dispatch<
    SetStateAction<CharacterAnimationPanelState | null>
  >;
  setIsCharacterSpecMenuOpen: Dispatch<SetStateAction<boolean>>;
  setIsCharacterReferenceMenuOpen: Dispatch<SetStateAction<boolean>>;
  setIsIconSpecMenuOpen: Dispatch<SetStateAction<boolean>>;
  setIsPickingCharacterSpecFromCanvas: Dispatch<SetStateAction<boolean>>;
  setIsPickingCharacterReferenceFromCanvas: Dispatch<SetStateAction<boolean>>;
  setIsPickingIconSpecFromCanvas: Dispatch<SetStateAction<boolean>>;
  onOpenSpecDialog: (specType: SpecGenerationType) => void;
  onRequestUpload: (target: UploadTarget) => void;
  onSubmitImageGeneration: (dialog: GenerateDialogState) => void;
  onSubmitIconSpritesheetGeneration: (dialog: GenerateDialogState) => void;
  onSubmitQuickEdit: () => void;
  onSubmitCharacterAnimation: () => void;
  onCloseGenerateComposer: () => void;
  onUpdateSpecFormValue: (key: keyof SpecFormValues, value: string) => void;
  onUpdateIconDescription: (index: number, value: string) => void;
  onAddIconDescription: () => void;
  onUpdateCharacterAnimationDuration: (frameCountValue: string) => void;
  onRememberImageModel: (model: string) => void;
};

function triggerPlaceholderAction(label: string) {
  window.alert(`${label}功能建设中`);
}

function buildPortalMenuStyle(
  anchor: HTMLElement | null,
  placement: 'above' | 'below',
): CSSProperties {
  const rect = anchor?.getBoundingClientRect();
  if (!rect) {
    return {
      position: 'fixed',
      left: 0,
      top: 0,
      right: 'auto',
      bottom: 'auto',
      zIndex: 70,
    };
  }

  return {
    position: 'fixed',
    left: Math.round(rect.left),
    top:
      placement === 'above'
        ? Math.round(rect.top)
        : Math.round(rect.bottom + 8),
    right: 'auto',
    bottom: 'auto',
    zIndex: 70,
    transform:
      placement === 'above' ? 'translateY(calc(-100% - 0.45rem))' : undefined,
  };
}

function renderEditorPortal(node: ReactNode) {
  if (typeof document === 'undefined') {
    return node;
  }
  return createPortal(node, document.body);
}

function resetFailedDialogStatus(dialog: GenerateDialogState) {
  return {
    ...dialog,
    status: dialog.status === 'failed' ? 'idle' : dialog.status,
    errorMessage: dialog.status === 'failed' ? undefined : dialog.errorMessage,
  };
}

function resetFailedPanelStatus<T extends { status: string; errorMessage?: string }>(
  panel: T,
) {
  return {
    ...panel,
    status: panel.status === 'failed' ? 'idle' : panel.status,
    errorMessage: panel.status === 'failed' ? undefined : panel.errorMessage,
  };
}

function getImageDimensionOptions(model: string | null | undefined) {
  return (
    EDITOR_IMAGE_DIMENSION_OPTIONS[
      (model ?? IMAGE_MODEL_NANOBANANA2) as keyof typeof EDITOR_IMAGE_DIMENSION_OPTIONS
    ] ?? EDITOR_IMAGE_DIMENSION_OPTIONS[IMAGE_MODEL_NANOBANANA2]
  );
}

function normalizeImageDialogSelection(dialog: GenerateDialogState) {
  const model = dialog.imageModel ?? IMAGE_MODEL_NANOBANANA2;
  const options = getImageDimensionOptions(model);
  const aspectRatios = options.aspectRatios as readonly string[];
  const imageSizes = options.imageSizes as readonly string[];
  return {
    model,
    aspectRatio:
      dialog.aspectRatio && aspectRatios.includes(dialog.aspectRatio)
        ? dialog.aspectRatio
        : options.aspectRatios[0],
    imageSize:
      dialog.imageSize && imageSizes.includes(dialog.imageSize)
        ? dialog.imageSize
        : (options.imageSizes.find((size) => size === '1K') ?? options.imageSizes[0]),
    options,
  };
}

function renderImageOptionButtons({
  dialog,
  setGenerateDialog,
  includeDimensions,
  onRememberImageModel,
}: {
  dialog: GenerateDialogState;
  setGenerateDialog: Dispatch<SetStateAction<GenerateDialogState | null>>;
  includeDimensions: boolean;
  onRememberImageModel: (model: string) => void;
}) {
  const selection = normalizeImageDialogSelection(dialog);
  const updateDialog = (patch: Partial<GenerateDialogState>) => {
    setGenerateDialog((currentDialog) =>
      currentDialog && currentDialog.mode === dialog.mode
        ? {
            ...resetFailedDialogStatus(currentDialog),
            ...patch,
          }
        : currentDialog,
    );
  };

  return (
    <>
      {includeDimensions ? (
        <>
          <div className="image-canvas-editor__option-field">
            <PlatformFieldLabel
              variant="field"
              className="image-canvas-editor__field-title"
            >
              画面比例
            </PlatformFieldLabel>
            <div className="image-canvas-editor__inline-option-group">
              {selection.options.aspectRatios.map((aspectRatio) => (
                <PlatformInlineOptionButton
                  key={aspectRatio}
                  className="image-canvas-editor__generation-ratio"
                  disabled={dialog.status === 'generating'}
                  aria-pressed={selection.aspectRatio === aspectRatio}
                  onClick={() => updateDialog({ aspectRatio })}
                >
                  {aspectRatio}
                </PlatformInlineOptionButton>
              ))}
            </div>
          </div>
          <div className="image-canvas-editor__option-field">
            <PlatformFieldLabel
              variant="field"
              className="image-canvas-editor__field-title"
            >
              大小尺寸
            </PlatformFieldLabel>
            <div className="image-canvas-editor__inline-option-group">
              {selection.options.imageSizes.map((imageSize) => (
                <PlatformInlineOptionButton
                  key={imageSize}
                  className="image-canvas-editor__generation-ratio"
                  disabled={dialog.status === 'generating'}
                  aria-pressed={selection.imageSize === imageSize}
                  onClick={() => updateDialog({ imageSize })}
                >
                  {imageSize}
                </PlatformInlineOptionButton>
              ))}
            </div>
          </div>
        </>
      ) : null}
      <div className="image-canvas-editor__option-field">
        <PlatformFieldLabel
          variant="field"
          className="image-canvas-editor__field-title"
        >
          模型
        </PlatformFieldLabel>
        <div className="image-canvas-editor__inline-option-group">
          {EDITOR_IMAGE_MODEL_OPTIONS.map((option) => {
            const nextOptions = getImageDimensionOptions(option.value);
            const nextAspectRatios = nextOptions.aspectRatios as readonly string[];
            const nextImageSizes = nextOptions.imageSizes as readonly string[];
            return (
              <PlatformInlineOptionButton
                key={option.value}
                className="image-canvas-editor__generation-model"
                disabled={dialog.status === 'generating'}
                aria-pressed={selection.model === option.value}
                onClick={() => {
                  onRememberImageModel(option.value);
                  updateDialog({
                    imageModel: option.value,
                    aspectRatio:
                      dialog.aspectRatio &&
                      nextAspectRatios.includes(dialog.aspectRatio)
                        ? dialog.aspectRatio
                        : nextOptions.aspectRatios[0],
                    imageSize:
                      dialog.imageSize &&
                      nextImageSizes.includes(dialog.imageSize)
                        ? dialog.imageSize
                        : (nextOptions.imageSizes.find((size) => size === '1K') ??
                          nextOptions.imageSizes[0]),
                  });
                }}
              >
                {option.label}
              </PlatformInlineOptionButton>
            );
          })}
        </div>
      </div>
    </>
  );
}

export function ImageCanvasGenerationComposerView({
  specToolWrapRef,
  characterSpecButtonRef,
  characterReferenceButtonRef,
  iconSpecButtonRef,
  isSpecMenuOpen,
  isCharacterSpecMenuOpen,
  isCharacterReferenceMenuOpen,
  isIconSpecMenuOpen,
  isPickingCharacterSpecFromCanvas,
  isPickingCharacterReferenceFromCanvas,
  isPickingIconSpecFromCanvas,
  generateDialog,
  generationComposerStyle,
  iconComposerStyle,
  quickEditPanel,
  quickEditSourceLayer,
  quickEditPanelStyle,
  quickEditSizeOptions,
  quickEditModelOptions,
  characterAnimationPanel,
  characterAnimationSourceLayer,
  characterAnimationPanelStyle,
  characterAnimationPrice,
  setGenerateDialog,
  setQuickEditPanel,
  setCharacterAnimationPanel,
  setIsCharacterSpecMenuOpen,
  setIsCharacterReferenceMenuOpen,
  setIsIconSpecMenuOpen,
  setIsPickingCharacterSpecFromCanvas,
  setIsPickingCharacterReferenceFromCanvas,
  setIsPickingIconSpecFromCanvas,
  onOpenSpecDialog,
  onRequestUpload,
  onSubmitImageGeneration,
  onSubmitIconSpritesheetGeneration,
  onSubmitQuickEdit,
  onSubmitCharacterAnimation,
  onCloseGenerateComposer,
  onUpdateSpecFormValue,
  onUpdateIconDescription,
  onAddIconDescription,
  onUpdateCharacterAnimationDuration,
  onRememberImageModel,
}: ImageCanvasGenerationComposerViewProps) {
  return (
    <>
      {isSpecMenuOpen
        ? renderEditorPortal(
            <PlatformFloatingMenu
              className="image-canvas-editor__spec-menu image-canvas-editor__portal-menu"
              label="生成规范类型"
              placement="top-start"
              style={buildPortalMenuStyle(specToolWrapRef.current, 'above')}
            >
              {(['character', 'ui', 'custom'] as const).map((specType) => (
                <PlatformFloatingMenuItem
                  key={specType}
                  className="image-canvas-editor__spec-menu-item"
                  onClick={() => onOpenSpecDialog(specType)}
                >
                  {SPEC_TYPE_LABEL[specType]}
                </PlatformFloatingMenuItem>
              ))}
            </PlatformFloatingMenu>,
          )
        : null}

      {generateDialog?.mode === 'generate' &&
      generateDialog.composerOpen !== false &&
      generationComposerStyle ? (
        <form
          className="image-canvas-editor__generation-composer"
          style={generationComposerStyle}
          role="dialog"
          aria-label="生成图片"
          onPointerDown={(event) => event.stopPropagation()}
          onSubmit={(event) => {
            event.preventDefault();
            if (generateDialog.status !== 'generating') {
              onSubmitImageGeneration(generateDialog);
            }
          }}
        >
          <PlatformIconButton
            variant="surfaceFloating"
            className="image-canvas-editor__generation-ref"
            label="添加参考图"
            disabled={generateDialog.status === 'generating'}
            onClick={() => onRequestUpload('asset')}
            icon={<ImageIcon className="h-4 w-4" />}
          >
            <span>参考图</span>
          </PlatformIconButton>
          <PlatformTextField
            variant="textarea"
            aria-label="生成提示词"
            value={generateDialog.prompt}
            disabled={generateDialog.status === 'generating'}
            placeholder="今天我们要创作什么"
            size="sm"
            density="compact"
            className="image-canvas-editor__generation-prompt"
            onChange={(event) =>
              setGenerateDialog((currentDialog) =>
                currentDialog
                  ? {
                      ...resetFailedDialogStatus(currentDialog),
                      prompt: event.target.value,
                    }
                  : currentDialog,
              )
            }
          />
          <div className="image-canvas-editor__generation-composer-footer">
            <PlatformInlineOptionButton
              className="image-canvas-editor__generation-ratio"
              aria-label="生成比例 1:1 2k 1张"
              disabled={generateDialog.status === 'generating'}
              onClick={() => triggerPlaceholderAction('生成参数')}
              trailingIcon={<ChevronDown className="h-3 w-3" />}
            >
              中 · 1:1(2k) · 1张
            </PlatformInlineOptionButton>
            <PlatformInlineOptionButton
              className="image-canvas-editor__generation-model"
              aria-label="生成模型 GPT Image"
              disabled={generateDialog.status === 'generating'}
              onClick={() => triggerPlaceholderAction('模型选择')}
              trailingIcon={<ChevronDown className="h-3 w-3" />}
            >
              GPT Im...
            </PlatformInlineOptionButton>
            <PlatformActionButton
              type="submit"
              tone="secondary"
              size="xs"
              shape="pill"
              className="image-canvas-editor__generation-submit"
              disabled={generateDialog.status === 'generating'}
              aria-label="生成"
            >
              {generateDialog.status === 'generating' ? '生成中' : '12'}
            </PlatformActionButton>
          </div>
          {generateDialog.status === 'generating' ? (
            <PlatformStatusMessage
              tone="info"
              surface="platform"
              size="xs"
              className="image-canvas-editor__generate-status"
              role="status"
            >
              生成中
            </PlatformStatusMessage>
          ) : null}
          {generateDialog.status === 'failed' ? (
            <PlatformStatusMessage
              tone="error"
              surface="platform"
              size="xs"
              className="image-canvas-editor__generate-status"
              role="alert"
            >
              {generateDialog.errorMessage}
            </PlatformStatusMessage>
          ) : null}
          <EditorIconButton
            className="image-canvas-editor__generation-close"
            label="关闭生成图片"
            icon={X}
            variant="surfaceFloating"
            disabled={generateDialog.status === 'generating'}
            onClick={onCloseGenerateComposer}
          />
        </form>
      ) : null}

      {generateDialog?.mode === 'spec' &&
      generateDialog.composerOpen !== false &&
      generationComposerStyle ? (
        <form
          className="image-canvas-editor__generation-composer image-canvas-editor__spec-composer"
          style={generationComposerStyle}
          role="dialog"
          aria-label="生成规范"
          onPointerDown={(event) => event.stopPropagation()}
          onSubmit={(event) => {
            event.preventDefault();
            if (generateDialog.status !== 'generating') {
              onSubmitImageGeneration(generateDialog);
            }
          }}
        >
          <div className="image-canvas-editor__spec-fields">
            {generateDialog.specType === 'custom' ? (
              <label className="image-canvas-editor__field-block">
                <PlatformFieldLabel
                  variant="form"
                  className="image-canvas-editor__field-title"
                >
                  自定义规范提示词
                </PlatformFieldLabel>
                <PlatformTextField
                  variant="textarea"
                  aria-label="自定义规范提示词"
                  value={generateDialog.specValues?.customPrompt ?? ''}
                  disabled={generateDialog.status === 'generating'}
                  size="sm"
                  density="compact"
                  className="image-canvas-editor__spec-textarea"
                  onChange={(event) =>
                    onUpdateSpecFormValue('customPrompt', event.target.value)
                  }
                />
              </label>
            ) : (
              <>
                <label className="image-canvas-editor__field-block">
                  <PlatformFieldLabel
                    variant="form"
                    className="image-canvas-editor__field-title"
                  >
                    玩法设定
                  </PlatformFieldLabel>
                  <PlatformTextField
                    aria-label="玩法设定"
                    value={generateDialog.specValues?.playSetting ?? ''}
                    disabled={generateDialog.status === 'generating'}
                    size="sm"
                    density="compact"
                    className="image-canvas-editor__spec-input"
                    onChange={(event) =>
                      onUpdateSpecFormValue('playSetting', event.target.value)
                    }
                  />
                </label>
                <label className="image-canvas-editor__field-block">
                  <PlatformFieldLabel
                    variant="form"
                    className="image-canvas-editor__field-title"
                  >
                    美术风格
                  </PlatformFieldLabel>
                  <PlatformTextField
                    aria-label="美术风格"
                    value={generateDialog.specValues?.artStyle ?? ''}
                    disabled={generateDialog.status === 'generating'}
                    size="sm"
                    density="compact"
                    className="image-canvas-editor__spec-input"
                    onChange={(event) =>
                      onUpdateSpecFormValue('artStyle', event.target.value)
                    }
                  />
                </label>
                {generateDialog.specType === 'character' ? (
                  <>
                    <label className="image-canvas-editor__field-block">
                      <PlatformFieldLabel
                        variant="form"
                        className="image-canvas-editor__field-title"
                      >
                        头身比
                      </PlatformFieldLabel>
                      <PlatformSelectField
                        aria-label="头身比"
                        value={generateDialog.specValues?.bodyRatio ?? '3'}
                        disabled={generateDialog.status === 'generating'}
                        size="sm"
                        density="compact"
                        className="image-canvas-editor__spec-input"
                        onChange={(event) =>
                          onUpdateSpecFormValue('bodyRatio', event.target.value)
                        }
                      >
                        {['2', '3', '4', '5', '6'].map((value) => (
                          <option key={value} value={value}>
                            {value}
                          </option>
                        ))}
                      </PlatformSelectField>
                    </label>
                    <label className="image-canvas-editor__field-block">
                      <PlatformFieldLabel
                        variant="form"
                        className="image-canvas-editor__field-title"
                      >
                        角色视角
                      </PlatformFieldLabel>
                      <PlatformSelectField
                        aria-label="角色视角"
                        value={generateDialog.specValues?.characterView ?? ''}
                        disabled={generateDialog.status === 'generating'}
                        size="sm"
                        density="compact"
                        className="image-canvas-editor__spec-input"
                        onChange={(event) =>
                          onUpdateSpecFormValue(
                            'characterView',
                            event.target.value,
                          )
                        }
                      >
                        {CHARACTER_SPEC_VIEW_OPTIONS.map((value) => (
                          <option key={value} value={value}>
                            {value}
                          </option>
                        ))}
                      </PlatformSelectField>
                    </label>
                  </>
                ) : null}
              </>
            )}
            {generateDialog.specType !== 'icon' ? (
              <div className="image-canvas-editor__field-block">
                <PlatformFieldLabel
                  variant="form"
                  className="image-canvas-editor__field-title"
                >
                  参考图
                </PlatformFieldLabel>
                <button
                  type="button"
                  className="image-canvas-editor__character-spec-ref image-canvas-editor__reference-tile image-canvas-editor__reference-tile--spec"
                  disabled={generateDialog.status === 'generating'}
                  onClick={() => onRequestUpload('spec-reference')}
                >
                  <span className="image-canvas-editor__reference-tile-visual">
                    {generateDialog.specReference ? (
                      <img
                        src={generateDialog.specReference.src}
                        alt=""
                        aria-hidden="true"
                      />
                    ) : (
                      <ImagePlus className="h-4 w-4" aria-hidden="true" />
                    )}
                  </span>
                  <span className="image-canvas-editor__reference-tile-copy">
                    {generateDialog.specReference?.label ?? '添加参考图'}
                  </span>
                </button>
              </div>
            ) : null}
          </div>
          {generateDialog.status === 'failed' ? (
            <PlatformStatusMessage
              tone="error"
              surface="platform"
              size="xs"
              className="image-canvas-editor__generate-status"
              role="alert"
            >
              {generateDialog.errorMessage}
            </PlatformStatusMessage>
          ) : null}
          <div className="image-canvas-editor__spec-footer">
            <PlatformActionButton
              type="submit"
              tone="secondary"
              size="sm"
              className="image-canvas-editor__spec-submit"
              disabled={generateDialog.status === 'generating'}
              aria-label="提交生成规范"
            >
              {generateDialog.status === 'generating'
                ? '生成中'
                : `消耗${SPEC_GENERATION_COST}泥点 · 生成`}
            </PlatformActionButton>
          </div>
        </form>
      ) : null}

      {generateDialog?.mode === 'character' && generationComposerStyle ? (
        <form
          className="image-canvas-editor__character-composer"
          style={generationComposerStyle}
          role="dialog"
          aria-label="生成角色形象"
          onPointerDown={(event) => event.stopPropagation()}
          onSubmit={(event) => {
            event.preventDefault();
            if (generateDialog.status !== 'generating') {
              onSubmitImageGeneration(generateDialog);
            }
          }}
        >
          <div className="image-canvas-editor__character-reference-row">
            <div className="image-canvas-editor__field-block image-canvas-editor__character-reference-field image-canvas-editor__character-reference-field--spec">
              <PlatformFieldLabel
                variant="field"
                className="image-canvas-editor__field-title"
              >
                角色形象规范
              </PlatformFieldLabel>
              <span className="image-canvas-editor__character-spec-wrap">
                <button
                  ref={characterSpecButtonRef}
                  type="button"
                  className="image-canvas-editor__character-spec-ref image-canvas-editor__reference-tile image-canvas-editor__reference-tile--spec"
                  disabled={generateDialog.status === 'generating'}
                  onClick={() => setIsCharacterSpecMenuOpen((open) => !open)}
                >
                  <span className="image-canvas-editor__reference-tile-visual">
                    {generateDialog.characterSpecReference ? (
                      <img
                        src={generateDialog.characterSpecReference.src}
                        alt=""
                        aria-hidden="true"
                      />
                    ) : (
                      <ClipboardList className="h-4 w-4" aria-hidden="true" />
                    )}
                  </span>
                  <span className="image-canvas-editor__reference-tile-copy">
                    {generateDialog.characterSpecReference?.label ??
                      '角色形象规范'}
                  </span>
                </button>
              </span>
            </div>
            {isCharacterSpecMenuOpen
              ? renderEditorPortal(
                  <PlatformFloatingMenu
                    className="image-canvas-editor__character-spec-menu image-canvas-editor__portal-menu"
                    label="角色形象规范来源"
                    placement="top-start"
                    style={buildPortalMenuStyle(
                      characterSpecButtonRef.current,
                      'above',
                    )}
                  >
                    <PlatformFloatingMenuItem
                      className="image-canvas-editor__context-menu-item"
                      onClick={() => {
                        setIsPickingCharacterSpecFromCanvas(true);
                        setIsCharacterSpecMenuOpen(false);
                      }}
                    >
                      从画布中选择
                    </PlatformFloatingMenuItem>
                    <PlatformFloatingMenuItem
                      className="image-canvas-editor__context-menu-item"
                      onClick={() => {
                        setIsCharacterSpecMenuOpen(false);
                        onOpenSpecDialog('character');
                      }}
                    >
                      新建角色形象规范
                    </PlatformFloatingMenuItem>
                    <PlatformFloatingMenuItem
                      className="image-canvas-editor__context-menu-item"
                      onClick={() => {
                        setIsCharacterSpecMenuOpen(false);
                        onRequestUpload('character-spec');
                      }}
                    >
                      上传图片
                    </PlatformFloatingMenuItem>
                  </PlatformFloatingMenu>,
                )
              : null}
            <div className="image-canvas-editor__field-block image-canvas-editor__character-reference-field image-canvas-editor__character-reference-field--regular">
              <PlatformFieldLabel
                variant="field"
                className="image-canvas-editor__field-title"
              >
                常规参考图
              </PlatformFieldLabel>
              <div className="image-canvas-editor__character-reference-list">
                {(generateDialog.characterReferences ?? []).map(
                  (reference, index) => (
                    <span
                      key={reference.id}
                      className="image-canvas-editor__character-ref-thumb"
                      title={reference.label}
                    >
                      <img src={reference.src} alt={reference.label} />
                      <span className="image-canvas-editor__character-ref-index">
                        {index + 1}
                      </span>
                    </span>
                  ),
                )}
                <button
                  ref={characterReferenceButtonRef}
                  type="button"
                  className="image-canvas-editor__character-reference-add image-canvas-editor__reference-tile image-canvas-editor__reference-tile--upload"
                  disabled={generateDialog.status === 'generating'}
                  onClick={() =>
                    setIsCharacterReferenceMenuOpen((open) => !open)
                  }
                >
                  <span className="image-canvas-editor__reference-tile-visual">
                    <ImagePlus className="h-4 w-4" aria-hidden="true" />
                  </span>
                  <span className="image-canvas-editor__reference-tile-copy">
                    上传常规参考图
                  </span>
                </button>
                {isCharacterReferenceMenuOpen
                  ? renderEditorPortal(
                      <PlatformFloatingMenu
                        className="image-canvas-editor__character-spec-menu image-canvas-editor__portal-menu"
                        label="常规参考图来源"
                        placement="top-start"
                        style={buildPortalMenuStyle(
                          characterReferenceButtonRef.current,
                          'above',
                        )}
                      >
                        <PlatformFloatingMenuItem
                          className="image-canvas-editor__context-menu-item"
                          onClick={() => {
                            setIsPickingCharacterReferenceFromCanvas(true);
                            setIsCharacterReferenceMenuOpen(false);
                          }}
                        >
                          从画布中选择
                        </PlatformFloatingMenuItem>
                        <PlatformFloatingMenuItem
                          className="image-canvas-editor__context-menu-item"
                          onClick={() => {
                            setIsCharacterReferenceMenuOpen(false);
                            onRequestUpload('character-reference');
                          }}
                        >
                          上传图片
                        </PlatformFloatingMenuItem>
                      </PlatformFloatingMenu>,
                    )
                  : null}
              </div>
            </div>
          </div>
          <label className="image-canvas-editor__field-block">
            <PlatformFieldLabel
              variant="field"
              className="image-canvas-editor__field-title"
            >
              角色设定
            </PlatformFieldLabel>
            <PlatformTextField
              variant="textarea"
              aria-label="角色设定"
              value={generateDialog.prompt}
              disabled={generateDialog.status === 'generating'}
              size="sm"
              density="compact"
              className="image-canvas-editor__generation-prompt"
              onChange={(event) =>
                setGenerateDialog((currentDialog) =>
                  currentDialog?.mode === 'character'
                    ? {
                        ...resetFailedDialogStatus(currentDialog),
                        prompt: event.target.value,
                      }
                    : currentDialog,
                )
              }
            />
          </label>
          {generateDialog.status === 'failed' ? (
            <PlatformStatusMessage
              tone="error"
              surface="platform"
              size="xs"
              className="image-canvas-editor__generate-status"
              role="alert"
            >
              {generateDialog.errorMessage}
            </PlatformStatusMessage>
          ) : null}
          <div className="image-canvas-editor__generation-composer-footer">
            {renderImageOptionButtons({
              dialog: generateDialog,
              setGenerateDialog,
              includeDimensions: true,
              onRememberImageModel,
            })}
            <PlatformActionButton
              type="submit"
              tone="secondary"
              size="xs"
              shape="pill"
              className="image-canvas-editor__generation-submit"
              disabled={generateDialog.status === 'generating'}
            >
              {generateDialog.status === 'generating' ? '生成中' : '生成'}
            </PlatformActionButton>
          </div>
        </form>
      ) : null}

      {generateDialog?.mode === 'icon' &&
      generateDialog.composerOpen !== false &&
      iconComposerStyle ? (
        <form
          className="image-canvas-editor__icon-composer"
          style={iconComposerStyle}
          role="dialog"
          aria-label="生成图标素材"
          onPointerDown={(event) => event.stopPropagation()}
          onSubmit={(event) => {
            event.preventDefault();
            if (generateDialog.status !== 'generating') {
              onSubmitIconSpritesheetGeneration(generateDialog);
            }
          }}
        >
          <div className="image-canvas-editor__field-block">
            <PlatformFieldLabel
              variant="field"
              className="image-canvas-editor__field-title"
            >
              图标素材规范
            </PlatformFieldLabel>
            <div className="image-canvas-editor__icon-spec-row">
              <span className="image-canvas-editor__character-spec-wrap">
                <button
                  ref={iconSpecButtonRef}
                  type="button"
                  className="image-canvas-editor__icon-spec-card"
                  disabled={generateDialog.status === 'generating'}
                  aria-label={
                    generateDialog.iconSpecReference?.label ?? '图标素材规范'
                  }
                  onClick={() => setIsIconSpecMenuOpen((open) => !open)}
                >
                  <span
                    className="image-canvas-editor__icon-spec-preview"
                    aria-hidden="true"
                  >
                    {generateDialog.iconSpecReference?.src ? (
                      <img src={generateDialog.iconSpecReference.src} alt="" />
                    ) : (
                      <ImageIcon className="h-5 w-5" />
                    )}
                  </span>
                  <span className="image-canvas-editor__icon-spec-copy">
                    <span className="image-canvas-editor__icon-spec-eyebrow">
                      图标素材规范
                    </span>
                    <span className="image-canvas-editor__icon-spec-title">
                      {generateDialog.iconSpecReference?.label ?? '待选择'}
                    </span>
                  </span>
                  <span className="image-canvas-editor__icon-spec-state">
                    {generateDialog.iconSpecReference ? '已绑定' : '待绑定'}
                  </span>
                </button>
              </span>
              {isIconSpecMenuOpen
                ? renderEditorPortal(
                    <PlatformFloatingMenu
                      className="image-canvas-editor__character-spec-menu image-canvas-editor__portal-menu"
                      label="图标素材规范来源"
                      placement="top-start"
                      style={buildPortalMenuStyle(
                        iconSpecButtonRef.current,
                        'above',
                      )}
                    >
                      <PlatformFloatingMenuItem
                        className="image-canvas-editor__context-menu-item"
                        onClick={() => {
                          setIsPickingIconSpecFromCanvas(true);
                          setIsIconSpecMenuOpen(false);
                        }}
                      >
                        从画布中选择
                      </PlatformFloatingMenuItem>
                      <PlatformFloatingMenuItem
                        className="image-canvas-editor__context-menu-item"
                        onClick={() => {
                          setIsIconSpecMenuOpen(false);
                          onOpenSpecDialog('icon');
                        }}
                      >
                        新建图标素材规范
                      </PlatformFloatingMenuItem>
                      <PlatformFloatingMenuItem
                        className="image-canvas-editor__context-menu-item"
                        onClick={() => {
                          setIsIconSpecMenuOpen(false);
                          onRequestUpload('icon-spec');
                        }}
                      >
                        上传图片
                      </PlatformFloatingMenuItem>
                    </PlatformFloatingMenu>,
                  )
                : null}
              <div
                className="image-canvas-editor__icon-spec-actions"
                aria-label="图标素材规范操作"
              >
                <button
                  type="button"
                  disabled={generateDialog.status === 'generating'}
                  onClick={() => {
                    setIsPickingIconSpecFromCanvas(true);
                    setIsIconSpecMenuOpen(false);
                  }}
                >
                  画布
                </button>
                <button
                  type="button"
                  disabled={generateDialog.status === 'generating'}
                  onClick={() => {
                    setIsIconSpecMenuOpen(false);
                    onOpenSpecDialog('icon');
                  }}
                >
                  新建
                </button>
                <button
                  type="button"
                  disabled={generateDialog.status === 'generating'}
                  onClick={() => {
                    setIsIconSpecMenuOpen(false);
                    onRequestUpload('icon-spec');
                  }}
                >
                  上传
                </button>
              </div>
            </div>
          </div>
          <div className="image-canvas-editor__field-block">
            <PlatformFieldLabel
              variant="field"
              className="image-canvas-editor__field-title"
            >
              素材描述
            </PlatformFieldLabel>
            <div className="image-canvas-editor__icon-description-list">
              {(generateDialog.iconDescriptions ?? DEFAULT_ICON_DESCRIPTIONS).map(
                (description, index) => (
                  <label
                    key={index}
                    className="image-canvas-editor__icon-description-card"
                  >
                    <span className="image-canvas-editor__icon-description-index">
                      {String(index + 1).padStart(2, '0')}
                    </span>
                    <span className="image-canvas-editor__icon-description-title">
                      素材描述 {index + 1}
                    </span>
                    <PlatformTextField
                      aria-label={`素材描述${index + 1}`}
                      value={description}
                      disabled={generateDialog.status === 'generating'}
                      size="sm"
                      density="compact"
                      className="image-canvas-editor__icon-description-input"
                      onChange={(event) =>
                        onUpdateIconDescription(index, event.target.value)
                      }
                    />
                  </label>
                ),
              )}
            </div>
          </div>
          {generateDialog.status === 'failed' ? (
            <PlatformStatusMessage
              tone="error"
              surface="platform"
              size="xs"
              className="image-canvas-editor__generate-status"
              role="alert"
            >
              {generateDialog.errorMessage}
            </PlatformStatusMessage>
          ) : null}
          <div className="image-canvas-editor__icon-footer">
            <button
              type="button"
              className="image-canvas-editor__character-reference-add"
              disabled={
                generateDialog.status === 'generating' ||
                (generateDialog.iconDescriptions ?? DEFAULT_ICON_DESCRIPTIONS)
                  .length >= ICON_DESCRIPTION_LIMIT
              }
              onClick={onAddIconDescription}
            >
              添加素材描述
            </button>
            {renderImageOptionButtons({
              dialog: generateDialog,
              setGenerateDialog,
              includeDimensions: true,
              onRememberImageModel,
            })}
            <PlatformActionButton
              type="submit"
              tone="secondary"
              size="xs"
              shape="pill"
              className="image-canvas-editor__generation-submit"
              disabled={generateDialog.status === 'generating'}
              aria-label="生成"
            >
              {generateDialog.status === 'generating' ? '生成中' : '生成'}
            </PlatformActionButton>
          </div>
        </form>
      ) : null}

      {isPickingCharacterSpecFromCanvas ? (
        <div className="image-canvas-editor__canvas-pick-hint">
          请选择画布中的图片作为角色形象规范，按 Esc 退出
        </div>
      ) : null}
      {isPickingCharacterReferenceFromCanvas ? (
        <div className="image-canvas-editor__canvas-pick-hint">
          请选择画布中的图片作为常规参考图，按 Esc 退出
        </div>
      ) : null}
      {isPickingIconSpecFromCanvas ? (
        <div className="image-canvas-editor__canvas-pick-hint">
          请选择画布中的图标素材规范，按 Esc 退出
        </div>
      ) : null}

      {quickEditPanel &&
      quickEditPanel.status !== 'generating' &&
      quickEditSourceLayer &&
      quickEditPanelStyle ? (
        <form
          className="image-canvas-editor__quick-edit-panel"
          style={quickEditPanelStyle}
          role="dialog"
          aria-label="快速编辑图片"
          onPointerDown={(event) => event.stopPropagation()}
          onSubmit={(event) => {
            event.preventDefault();
            onSubmitQuickEdit();
          }}
        >
          <div className="image-canvas-editor__quick-edit-head">
            <div className="image-canvas-editor__quick-edit-reference">
              <img
                src={quickEditSourceLayer.src}
                alt={`${quickEditSourceLayer.title}参考图`}
              />
              <span>{quickEditSourceLayer.title}</span>
            </div>
            <EditorIconButton
              label="关闭快速编辑图片"
              title="关闭"
              icon={X}
              onClick={() => setQuickEditPanel(null)}
            />
          </div>
          <PlatformTextField
            variant="textarea"
            aria-label="快速编辑提示词"
            value={quickEditPanel.prompt}
            size="sm"
            density="compact"
            className="image-canvas-editor__quick-edit-prompt"
            onChange={(event) =>
              setQuickEditPanel((currentPanel) =>
                currentPanel
                  ? {
                      ...resetFailedPanelStatus(currentPanel),
                      prompt: event.target.value,
                    }
                  : currentPanel,
              )
            }
          />
          <div className="image-canvas-editor__quick-edit-controls">
            <PlatformSelectField
              aria-label="快速编辑尺寸"
              value={quickEditPanel.size}
              size="xs"
              density="compact"
              onChange={(event) =>
                setQuickEditPanel((currentPanel) =>
                  currentPanel
                    ? { ...currentPanel, size: event.target.value }
                    : currentPanel,
                )
              }
            >
              {quickEditSizeOptions.map((size) => (
                <option key={size} value={size}>
                  {size}
                </option>
              ))}
            </PlatformSelectField>
            <PlatformSelectField
              aria-label="快速编辑模型"
              value={quickEditPanel.model}
              size="xs"
              density="compact"
              onChange={(event) =>
                setQuickEditPanel((currentPanel) =>
                  currentPanel
                    ? { ...currentPanel, model: event.target.value }
                    : currentPanel,
                )
              }
            >
              {quickEditModelOptions.map((option) => (
                <option key={option.value} value={option.value}>
                  {option.label}
                </option>
              ))}
            </PlatformSelectField>
          </div>
          {quickEditPanel.status === 'failed' ? (
            <PlatformStatusMessage
              tone="error"
              surface="platform"
              size="xs"
              role="alert"
            >
              {quickEditPanel.errorMessage}
            </PlatformStatusMessage>
          ) : null}
          <PlatformActionButton
            type="submit"
            tone="secondary"
            size="sm"
            className="image-canvas-editor__quick-edit-submit"
          >
            生成
          </PlatformActionButton>
        </form>
      ) : null}

      {characterAnimationPanel &&
      characterAnimationSourceLayer &&
      characterAnimationPanelStyle ? (
        <form
          className="image-canvas-editor__character-animation-panel"
          style={characterAnimationPanelStyle}
          role="dialog"
          aria-label="角色动画生成面板"
          onPointerDown={(event) => event.stopPropagation()}
          onSubmit={(event) => {
            event.preventDefault();
            if (characterAnimationPanel.status !== 'generating') {
              onSubmitCharacterAnimation();
            }
          }}
        >
          <div className="image-canvas-editor__character-animation-head">
            <strong>角色动画</strong>
            <EditorIconButton
              label="关闭角色动画生成面板"
              title="关闭"
              icon={X}
              onClick={() => setCharacterAnimationPanel(null)}
            />
          </div>
          <PlatformTextField
            variant="textarea"
            aria-label="动画描述"
            value={characterAnimationPanel.promptText}
            maxLength={4000}
            disabled={characterAnimationPanel.status === 'generating'}
            size="sm"
            density="compact"
            className="image-canvas-editor__character-animation-textarea"
            onChange={(event) =>
              setCharacterAnimationPanel((currentPanel) =>
                currentPanel
                  ? {
                      ...resetFailedPanelStatus(currentPanel),
                      promptText: event.target.value.slice(0, 4000),
                    }
                  : currentPanel,
              )
            }
          />
          <div className="image-canvas-editor__character-animation-presets">
            {CHARACTER_ANIMATION_ACTION_PROMPTS.map((preset) => (
              <button
                key={preset.label}
                type="button"
                className="image-canvas-editor__character-animation-preset"
                disabled={characterAnimationPanel.status === 'generating'}
                onClick={() =>
                  setCharacterAnimationPanel((currentPanel) =>
                    currentPanel
                      ? {
                          ...currentPanel,
                          promptText: preset.text,
                          status: 'idle',
                          errorMessage: undefined,
                        }
                      : currentPanel,
                  )
                }
              >
                {preset.label}
              </button>
            ))}
          </div>
          <div className="image-canvas-editor__character-animation-grid">
            <PlatformSelectField
              aria-label="分辨率"
              value={characterAnimationPanel.resolution}
              disabled={characterAnimationPanel.status === 'generating'}
              size="xs"
              density="compact"
              onChange={(event) =>
                setCharacterAnimationPanel((currentPanel) =>
                  currentPanel
                    ? {
                        ...resetFailedPanelStatus(currentPanel),
                        resolution:
                          event.target.value === '720p' ? '720p' : '480p',
                      }
                    : currentPanel,
                )
              }
            >
              <option value="480p">480p</option>
              <option value="720p">720p</option>
            </PlatformSelectField>
            <PlatformSelectField
              aria-label="画面比例"
              value={characterAnimationPanel.ratio}
              disabled={characterAnimationPanel.status === 'generating'}
              size="xs"
              density="compact"
              onChange={(event) =>
                setCharacterAnimationPanel((currentPanel) =>
                  currentPanel
                    ? {
                        ...resetFailedPanelStatus(currentPanel),
                        ratio:
                          CHARACTER_ANIMATION_RATIO_OPTIONS.find(
                            (item) => item.value === event.target.value,
                          )?.value ?? 'same',
                      }
                    : currentPanel,
                )
              }
            >
              {CHARACTER_ANIMATION_RATIO_OPTIONS.map((option) => (
                <option key={option.value} value={option.value}>
                  {option.label}
                </option>
              ))}
            </PlatformSelectField>
            <PlatformSelectField
              aria-label="时长"
              value={String(characterAnimationPanel.frameCount)}
              disabled={characterAnimationPanel.status === 'generating'}
              size="xs"
              density="compact"
              onChange={(event) =>
                onUpdateCharacterAnimationDuration(event.target.value)
              }
            >
              {CHARACTER_ANIMATION_DURATION_OPTIONS.map((option) => (
                <option
                  key={option.frameCount}
                  value={String(option.frameCount)}
                >
                  {option.label}
                </option>
              ))}
            </PlatformSelectField>
          </div>
          <div className="image-canvas-editor__character-animation-summary">
            <span
              className="image-canvas-editor__character-animation-summary-text"
              title={characterAnimationPanel.promptText.trim() || undefined}
              aria-label={`生成文本：${
                characterAnimationPanel.promptText.trim() || '动画描述'
              }`}
            >
              {characterAnimationPanel.promptText.trim()
                ? characterAnimationPanel.promptText.trim()
                : '动画描述'}
            </span>
            <strong>{characterAnimationPrice}泥点</strong>
          </div>
          {characterAnimationPanel.status === 'completed' &&
          characterAnimationPanel.result ? (
            <PlatformStatusMessage
              tone="success"
              surface="platform"
              size="xs"
              role="status"
            >
              已生成 {characterAnimationPanel.result.frameCount} 帧
            </PlatformStatusMessage>
          ) : null}
          {characterAnimationPanel.status === 'failed' ? (
            <PlatformStatusMessage
              tone="error"
              surface="platform"
              size="xs"
              role="alert"
            >
              {characterAnimationPanel.errorMessage}
            </PlatformStatusMessage>
          ) : null}
          <PlatformActionButton
            type="submit"
            tone="secondary"
            size="sm"
            className="image-canvas-editor__character-animation-submit"
            disabled={characterAnimationPanel.status === 'generating'}
          >
            {characterAnimationPanel.status === 'generating'
              ? '生成中'
              : '生成'}
          </PlatformActionButton>
        </form>
      ) : null}

      <UnifiedModal
        open={
          generateDialog?.mode === 'edit' &&
          generateDialog.status !== 'generating'
        }
        title={generateDialog?.mode === 'edit' ? '修改图片' : '生成图片'}
        size="sm"
        closeLabel={
          generateDialog?.mode === 'edit' ? '关闭修改图片' : '关闭生成图片'
        }
        closeDisabled={generateDialog?.status === 'generating'}
        onClose={() => setGenerateDialog(null)}
        panelClassName="image-canvas-editor__generate-dialog"
        bodyClassName="image-canvas-editor__generate-dialog-body"
      >
        {generateDialog?.mode === 'edit' ? (
          <form
            className="image-canvas-editor__generate-form"
            onSubmit={(event) => {
              event.preventDefault();
              if (generateDialog.status !== 'generating') {
                onSubmitImageGeneration(generateDialog);
              }
            }}
          >
            <div className="image-canvas-editor__generate-body">
              <PlatformTextField
                variant="textarea"
                aria-label="生成提示词"
                value={generateDialog.prompt}
                disabled={generateDialog.status === 'generating'}
                size="sm"
                density="roomy"
                className="image-canvas-editor__generate-prompt"
                placeholder="描述你想如何修改这张图片"
                onChange={(event) =>
                  setGenerateDialog((currentDialog) =>
                    currentDialog
                      ? {
                          ...currentDialog,
                          prompt: event.target.value,
                        }
                      : currentDialog,
                  )
                }
              />
              {generateDialog.status === 'generating' ? (
                <PlatformStatusMessage
                  tone="info"
                  surface="platform"
                  size="xs"
                  className="image-canvas-editor__generate-status"
                  role="status"
                >
                  修改中
                </PlatformStatusMessage>
              ) : null}
              {generateDialog.status === 'failed' ? (
                <PlatformStatusMessage
                  tone="error"
                  surface="platform"
                  size="xs"
                  className="image-canvas-editor__generate-status"
                  role="alert"
                >
                  {generateDialog.errorMessage}
                </PlatformStatusMessage>
              ) : null}
              <PlatformActionButton
                type="submit"
                size="sm"
                className="image-canvas-editor__generate-submit"
                disabled={generateDialog.status === 'generating'}
              >
                {generateDialog.status === 'generating' ? '修改中' : '修改'}
              </PlatformActionButton>
            </div>
          </form>
        ) : null}
      </UnifiedModal>
    </>
  );
}
