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

import {
  PlatformFloatingMenu,
  PlatformFloatingMenuItem,
} from '../common/PlatformFloatingMenu';
import { PlatformActionButton } from '../common/PlatformActionButton';
import { PlatformIconButton } from '../common/PlatformIconButton';
import { PlatformInlineOptionButton } from '../common/PlatformInlineOptionButton';
import { PlatformTextField } from '../common/PlatformTextField';
import { ImageCanvasBasicGenerationComposerView } from './ImageCanvasBasicGenerationComposerView';
import { ImageCanvasCharacterAnimationPanelView } from './ImageCanvasCharacterAnimationPanelView';
import { ImageCanvasCharacterGenerationComposerView } from './ImageCanvasCharacterGenerationComposerView';
import { ImageCanvasEditGenerationModalView } from './ImageCanvasEditGenerationModalView';
import { ImageCanvasIconSpritesheetComposerView } from './ImageCanvasIconSpritesheetComposerView';
import { ImageCanvasQuickEditPanelView } from './ImageCanvasQuickEditPanelView';
import { ImageCanvasSpecGenerationPanelView } from './ImageCanvasSpecGenerationPanelView';
import {
  EDITOR_VIDEO_MODEL_OPTIONS,
  SPEC_TYPE_LABEL,
  calculateEditorVideoPrice,
} 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>;
  generationReferenceButtonRef: RefObject<HTMLButtonElement | null>;
  iconSpecButtonRef: RefObject<HTMLButtonElement | null>;
  isSpecMenuOpen: boolean;
  isGenerationReferenceMenuOpen: boolean;
  isCharacterSpecMenuOpen: boolean;
  isCharacterReferenceMenuOpen: boolean;
  isIconSpecMenuOpen: boolean;
  isUiDesignSpecMenuOpen: boolean;
  isPickingGenerationReferenceFromCanvas: boolean;
  isPickingCharacterSpecFromCanvas: boolean;
  isPickingCharacterReferenceFromCanvas: boolean;
  isPickingIconSpecFromCanvas: boolean;
  isPickingUiDesignSpecFromCanvas: 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>
  >;
  setIsGenerationReferenceMenuOpen: Dispatch<SetStateAction<boolean>>;
  setIsCharacterSpecMenuOpen: Dispatch<SetStateAction<boolean>>;
  setIsCharacterReferenceMenuOpen: Dispatch<SetStateAction<boolean>>;
  setIsIconSpecMenuOpen: Dispatch<SetStateAction<boolean>>;
  setIsUiDesignSpecMenuOpen: Dispatch<SetStateAction<boolean>>;
  setIsPickingGenerationReferenceFromCanvas: Dispatch<SetStateAction<boolean>>;
  setIsPickingCharacterSpecFromCanvas: Dispatch<SetStateAction<boolean>>;
  setIsPickingCharacterReferenceFromCanvas: Dispatch<SetStateAction<boolean>>;
  setIsPickingIconSpecFromCanvas: Dispatch<SetStateAction<boolean>>;
  setIsPickingUiDesignSpecFromCanvas: 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 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 ImageCanvasVideoGenerationComposerView({
  dialog,
  style,
  generationReferenceButtonRef,
  isGenerationReferenceMenuOpen,
  setGenerateDialog,
  setIsGenerationReferenceMenuOpen,
  setIsPickingGenerationReferenceFromCanvas,
  onRequestUpload,
  onSubmit,
}: {
  dialog: GenerateDialogState;
  style: CSSProperties;
  generationReferenceButtonRef: RefObject<HTMLButtonElement | null>;
  isGenerationReferenceMenuOpen: boolean;
  setGenerateDialog: Dispatch<SetStateAction<GenerateDialogState | null>>;
  setIsGenerationReferenceMenuOpen: Dispatch<SetStateAction<boolean>>;
  setIsPickingGenerationReferenceFromCanvas: Dispatch<SetStateAction<boolean>>;
  onRequestUpload: (target: UploadTarget) => void;
  onSubmit: (dialog: GenerateDialogState) => void;
}) {
  const resolution = dialog.videoResolution ?? '480p';
  const durationSeconds = dialog.videoDurationSeconds ?? 4;
  const currentModel =
    EDITOR_VIDEO_MODEL_OPTIONS.find((item) => item.value === dialog.videoModel)
      ?? EDITOR_VIDEO_MODEL_OPTIONS[0];
  const price = calculateEditorVideoPrice(resolution, durationSeconds);
  return (
    <>
      <form
        className="image-canvas-editor__generation-composer image-canvas-editor__generation-composer--image"
        style={style}
        role="dialog"
        aria-label="生成视频"
        onPointerDown={(event) => event.stopPropagation()}
        onSubmit={(event) => {
          event.preventDefault();
          if (dialog.status !== 'generating') {
            onSubmit(dialog);
          }
        }}
      >
        <PlatformIconButton
          ref={generationReferenceButtonRef}
          variant="surfaceFloating"
          className="image-canvas-editor__generation-ref"
          label="添加视频参考图"
          disabled={dialog.status === 'generating'}
          onClick={() => setIsGenerationReferenceMenuOpen((open) => !open)}
          icon={<ImageIcon className="h-4 w-4" />}
        >
          <span>参考图</span>
        </PlatformIconButton>
        <PlatformTextField
          variant="textarea"
          aria-label="视频描述"
          value={dialog.prompt}
          disabled={dialog.status === 'generating'}
          placeholder="描述视频画面"
          size="sm"
          density="compact"
          className="image-canvas-editor__generation-prompt"
          onChange={(event) =>
            setGenerateDialog((currentDialog) =>
              currentDialog
                ? {
                    ...currentDialog,
                    prompt: event.target.value,
                    status:
                      currentDialog.status === 'failed'
                        ? 'idle'
                        : currentDialog.status,
                    errorMessage:
                      currentDialog.status === 'failed'
                        ? undefined
                        : currentDialog.errorMessage,
                  }
                : currentDialog,
            )
          }
        />
        <div className="image-canvas-editor__generation-composer-footer">
          <PlatformInlineOptionButton
            className="image-canvas-editor__generation-ratio"
            aria-label={`视频参数 16:9 · ${durationSeconds}秒 · ${resolution}`}
            disabled={dialog.status === 'generating'}
            trailingIcon={<ChevronDown className="h-3 w-3" />}
            onClick={() => {
              setGenerateDialog((currentDialog) =>
                currentDialog?.mode === 'video'
                  ? {
                      ...currentDialog,
                      videoDurationSeconds:
                        currentDialog.videoDurationSeconds === 5 ? 4 : 5,
                      status:
                        currentDialog.status === 'failed'
                          ? 'idle'
                          : currentDialog.status,
                      errorMessage:
                        currentDialog.status === 'failed'
                          ? undefined
                          : currentDialog.errorMessage,
                    }
                  : currentDialog,
              );
            }}
          >
            16:9 · {resolution} · {durationSeconds}秒
          </PlatformInlineOptionButton>
          <PlatformInlineOptionButton
            className="image-canvas-editor__generation-model"
            aria-label={`模型 ${currentModel.label}`}
            disabled={dialog.status === 'generating'}
            trailingIcon={<ChevronDown className="h-3 w-3" />}
            onClick={() => {
              setGenerateDialog((currentDialog) => {
                if (currentDialog?.mode !== 'video') {
                  return currentDialog;
                }
                const currentIndex = EDITOR_VIDEO_MODEL_OPTIONS.findIndex(
                  (item) => item.value === currentDialog.videoModel,
                );
                const nextModel =
                  EDITOR_VIDEO_MODEL_OPTIONS[
                    (Math.max(currentIndex, 0) + 1) %
                      EDITOR_VIDEO_MODEL_OPTIONS.length
                  ] ?? EDITOR_VIDEO_MODEL_OPTIONS[0];
                if (!nextModel) {
                  return currentDialog;
                }
                return {
                  ...currentDialog,
                  videoModel: nextModel.value,
                  status:
                    currentDialog.status === 'failed'
                      ? 'idle'
                      : currentDialog.status,
                  errorMessage:
                    currentDialog.status === 'failed'
                      ? undefined
                      : currentDialog.errorMessage,
                };
              });
            }}
          >
            {currentModel.label}
          </PlatformInlineOptionButton>
          <PlatformInlineOptionButton
            className="image-canvas-editor__generation-ratio"
            aria-label={`清晰度 ${resolution}`}
            disabled={dialog.status === 'generating'}
            trailingIcon={<ChevronDown className="h-3 w-3" />}
            onClick={() => {
              setGenerateDialog((currentDialog) =>
                currentDialog?.mode === 'video'
                  ? {
                      ...currentDialog,
                      videoResolution:
                        currentDialog.videoResolution === '720p'
                          ? '480p'
                          : '720p',
                      status:
                        currentDialog.status === 'failed'
                          ? 'idle'
                          : currentDialog.status,
                      errorMessage:
                        currentDialog.status === 'failed'
                          ? undefined
                          : currentDialog.errorMessage,
                    }
                  : currentDialog,
              );
            }}
          >
            {resolution}
          </PlatformInlineOptionButton>
          <PlatformActionButton
            type="submit"
            tone="secondary"
            size="xs"
            shape="pill"
            className="image-canvas-editor__generation-submit"
            disabled={dialog.status === 'generating'}
            aria-label="生成视频"
          >
            {dialog.status === 'generating' ? '生成中' : `${price}`}
          </PlatformActionButton>
        </div>
      </form>
      {isGenerationReferenceMenuOpen
        ? renderEditorPortal(
            <PlatformFloatingMenu
              className="image-canvas-editor__spec-menu image-canvas-editor__portal-menu"
              label="参考图来源"
              placement="top-start"
              style={buildPortalMenuStyle(
                generationReferenceButtonRef.current,
                'above',
              )}
            >
              <PlatformFloatingMenuItem
                onClick={() => {
                  setIsGenerationReferenceMenuOpen(false);
                  setIsPickingGenerationReferenceFromCanvas(true);
                }}
              >
                从画布中选择
              </PlatformFloatingMenuItem>
              <PlatformFloatingMenuItem
                onClick={() => {
                  setIsGenerationReferenceMenuOpen(false);
                  setIsPickingGenerationReferenceFromCanvas(false);
                  onRequestUpload('generation-reference');
                }}
              >
                上传图片
              </PlatformFloatingMenuItem>
            </PlatformFloatingMenu>,
          )
        : null}
    </>
  );
}

export function ImageCanvasGenerationComposerView({
  specToolWrapRef,
  characterSpecButtonRef,
  characterReferenceButtonRef,
  generationReferenceButtonRef,
  iconSpecButtonRef,
  isSpecMenuOpen,
  isGenerationReferenceMenuOpen,
  isCharacterSpecMenuOpen,
  isCharacterReferenceMenuOpen,
  isIconSpecMenuOpen,
  isUiDesignSpecMenuOpen,
  isPickingGenerationReferenceFromCanvas,
  isPickingCharacterSpecFromCanvas,
  isPickingCharacterReferenceFromCanvas,
  isPickingIconSpecFromCanvas,
  isPickingUiDesignSpecFromCanvas,
  generateDialog,
  generationComposerStyle,
  iconComposerStyle,
  quickEditPanel,
  quickEditSourceLayer,
  quickEditPanelStyle,
  quickEditSizeOptions,
  quickEditModelOptions,
  characterAnimationPanel,
  characterAnimationSourceLayer,
  characterAnimationPanelStyle,
  characterAnimationPrice,
  setGenerateDialog,
  setQuickEditPanel,
  setCharacterAnimationPanel,
  setIsGenerationReferenceMenuOpen,
  setIsCharacterSpecMenuOpen,
  setIsCharacterReferenceMenuOpen,
  setIsIconSpecMenuOpen,
  setIsUiDesignSpecMenuOpen,
  setIsPickingGenerationReferenceFromCanvas,
  setIsPickingCharacterSpecFromCanvas,
  setIsPickingCharacterReferenceFromCanvas,
  setIsPickingIconSpecFromCanvas,
  setIsPickingUiDesignSpecFromCanvas,
  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 ? (
        <ImageCanvasBasicGenerationComposerView
          dialog={generateDialog}
          style={generationComposerStyle}
          setGenerateDialog={setGenerateDialog}
          generationReferenceButtonRef={generationReferenceButtonRef}
          isGenerationReferenceMenuOpen={isGenerationReferenceMenuOpen}
          setIsGenerationReferenceMenuOpen={setIsGenerationReferenceMenuOpen}
          setIsPickingGenerationReferenceFromCanvas={
            setIsPickingGenerationReferenceFromCanvas
          }
          renderEditorPortal={renderEditorPortal}
          buildPortalMenuStyle={buildPortalMenuStyle}
          onRequestUpload={onRequestUpload}
          onToggleReferenceMenu={() =>
            setIsGenerationReferenceMenuOpen((open) => !open)
          }
          onSubmit={onSubmitImageGeneration}
          onClose={onCloseGenerateComposer}
        />
      ) : null}

      {generateDialog?.mode === 'spec' &&
      generateDialog.composerOpen !== false &&
      generationComposerStyle ? (
        <ImageCanvasSpecGenerationPanelView
          dialog={generateDialog}
          style={generationComposerStyle}
          isGenerationReferenceMenuOpen={isGenerationReferenceMenuOpen}
          generationReferenceButtonRef={generationReferenceButtonRef}
          setIsGenerationReferenceMenuOpen={setIsGenerationReferenceMenuOpen}
          setIsPickingGenerationReferenceFromCanvas={
            setIsPickingGenerationReferenceFromCanvas
          }
          renderEditorPortal={renderEditorPortal}
          buildPortalMenuStyle={buildPortalMenuStyle}
          setGenerateDialog={setGenerateDialog}
          onOpenSpecDialog={onOpenSpecDialog}
          onUpdateSpecFormValue={onUpdateSpecFormValue}
          onRequestUpload={onRequestUpload}
          onSubmit={onSubmitImageGeneration}
        />
      ) : null}

      {generateDialog?.mode === 'ui-design' &&
      generateDialog.composerOpen !== false &&
      generationComposerStyle ? (
        <ImageCanvasSpecGenerationPanelView
          dialog={generateDialog}
          style={generationComposerStyle}
          isGenerationReferenceMenuOpen={isUiDesignSpecMenuOpen}
          generationReferenceButtonRef={generationReferenceButtonRef}
          setIsGenerationReferenceMenuOpen={setIsUiDesignSpecMenuOpen}
          setIsPickingGenerationReferenceFromCanvas={
            setIsPickingUiDesignSpecFromCanvas
          }
          renderEditorPortal={renderEditorPortal}
          buildPortalMenuStyle={buildPortalMenuStyle}
          setGenerateDialog={setGenerateDialog}
          onOpenSpecDialog={onOpenSpecDialog}
          onUpdateSpecFormValue={onUpdateSpecFormValue}
          onRequestUpload={onRequestUpload}
          onSubmit={onSubmitImageGeneration}
        />
      ) : null}

      {generateDialog?.mode === 'video' &&
      generateDialog.composerOpen !== false &&
      generationComposerStyle ? (
        <ImageCanvasVideoGenerationComposerView
          dialog={generateDialog}
          style={generationComposerStyle}
          generationReferenceButtonRef={generationReferenceButtonRef}
          isGenerationReferenceMenuOpen={isGenerationReferenceMenuOpen}
          setGenerateDialog={setGenerateDialog}
          setIsGenerationReferenceMenuOpen={setIsGenerationReferenceMenuOpen}
          setIsPickingGenerationReferenceFromCanvas={
            setIsPickingGenerationReferenceFromCanvas
          }
          onRequestUpload={onRequestUpload}
          onSubmit={onSubmitImageGeneration}
        />
      ) : null}

      {generateDialog?.mode === 'character' && generationComposerStyle ? (
        <ImageCanvasCharacterGenerationComposerView
          dialog={generateDialog}
          style={generationComposerStyle}
          characterSpecButtonRef={characterSpecButtonRef}
          characterReferenceButtonRef={characterReferenceButtonRef}
          isCharacterSpecMenuOpen={isCharacterSpecMenuOpen}
          isCharacterReferenceMenuOpen={isCharacterReferenceMenuOpen}
          setGenerateDialog={setGenerateDialog}
          setIsCharacterSpecMenuOpen={setIsCharacterSpecMenuOpen}
          setIsCharacterReferenceMenuOpen={setIsCharacterReferenceMenuOpen}
          setIsPickingCharacterSpecFromCanvas={
            setIsPickingCharacterSpecFromCanvas
          }
          setIsPickingCharacterReferenceFromCanvas={
            setIsPickingCharacterReferenceFromCanvas
          }
          renderEditorPortal={renderEditorPortal}
          buildPortalMenuStyle={buildPortalMenuStyle}
          onOpenSpecDialog={onOpenSpecDialog}
          onRequestUpload={onRequestUpload}
          onRememberImageModel={onRememberImageModel}
          onSubmit={onSubmitImageGeneration}
        />
      ) : null}

      {generateDialog?.mode === 'icon' &&
      generateDialog.composerOpen !== false &&
      iconComposerStyle ? (
        <ImageCanvasIconSpritesheetComposerView
          dialog={generateDialog}
          style={iconComposerStyle}
          iconSpecButtonRef={iconSpecButtonRef}
          isIconSpecMenuOpen={isIconSpecMenuOpen}
          setGenerateDialog={setGenerateDialog}
          setIsIconSpecMenuOpen={setIsIconSpecMenuOpen}
          setIsPickingIconSpecFromCanvas={setIsPickingIconSpecFromCanvas}
          renderEditorPortal={renderEditorPortal}
          buildPortalMenuStyle={buildPortalMenuStyle}
          onOpenSpecDialog={onOpenSpecDialog}
          onRequestUpload={onRequestUpload}
          onUpdateIconDescription={onUpdateIconDescription}
          onAddIconDescription={onAddIconDescription}
          onRememberImageModel={onRememberImageModel}
          onSubmit={onSubmitIconSpritesheetGeneration}
        />
      ) : 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}
      {isPickingGenerationReferenceFromCanvas ? (
        <div className="image-canvas-editor__canvas-pick-hint">
          请选择画布中的图片作为参考图，按 Esc 退出
        </div>
      ) : null}
      {isPickingIconSpecFromCanvas ? (
        <div className="image-canvas-editor__canvas-pick-hint">
          请选择画布中的图标素材规范，按 Esc 退出
        </div>
      ) : null}
      {isPickingUiDesignSpecFromCanvas ? (
        <div className="image-canvas-editor__canvas-pick-hint">
          请选择画布中的图标素材规范，按 Esc 退出
        </div>
      ) : null}

      {quickEditPanel &&
      quickEditPanel.status !== 'generating' &&
      quickEditSourceLayer &&
      quickEditPanelStyle ? (
        <ImageCanvasQuickEditPanelView
          panel={quickEditPanel}
          sourceLayer={quickEditSourceLayer}
          style={quickEditPanelStyle}
          sizeOptions={quickEditSizeOptions}
          modelOptions={quickEditModelOptions}
          setQuickEditPanel={setQuickEditPanel}
          onSubmit={onSubmitQuickEdit}
        />
      ) : null}

      {characterAnimationPanel &&
      characterAnimationSourceLayer &&
      characterAnimationPanelStyle ? (
        <ImageCanvasCharacterAnimationPanelView
          panel={characterAnimationPanel}
          style={characterAnimationPanelStyle}
          price={characterAnimationPrice}
          setCharacterAnimationPanel={setCharacterAnimationPanel}
          onUpdateDuration={onUpdateCharacterAnimationDuration}
          onSubmit={onSubmitCharacterAnimation}
        />
      ) : null}

      <ImageCanvasEditGenerationModalView
        dialog={generateDialog}
        setGenerateDialog={setGenerateDialog}
        onSubmit={onSubmitImageGeneration}
      />
    </>
  );
}
