import { Loader2, Plus, Sparkles, WandSparkles, X } from 'lucide-react';
import { useEffect, useMemo, useRef, useState } from 'react';

import type {
  CreateMatch3DSessionRequest,
  ExecuteMatch3DActionRequest,
  Match3DAgentSessionSnapshot,
  SendMatch3DMessageRequest,
} from '../../../packages/shared/src/contracts/match3dAgent';

type Match3DAgentWorkspaceProps = {
  session: Match3DAgentSessionSnapshot | null;
  isBusy?: boolean;
  error?: string | null;
  onBack: () => void;
  onSubmitMessage?: (payload: SendMatch3DMessageRequest) => void;
  onExecuteAction: (payload: ExecuteMatch3DActionRequest) => void;
  onCreateFromForm?: (payload: CreateMatch3DSessionRequest) => void;
  initialFormPayload?: CreateMatch3DSessionRequest | null;
  showBackButton?: boolean;
  title?: string | null;
};

type Match3DFormState = {
  themeText: string;
  difficultyOptionId: Match3DDifficultyOptionId;
  assetStyleId: Match3DAssetStyleOptionId;
  customAssetStylePrompt: string;
};

const EMPTY_FORM_STATE: Match3DFormState = {
  themeText: '',
  difficultyOptionId: 'standard',
  assetStyleId: 'flat-icon',
  customAssetStylePrompt: '',
};

// 中文注释：入口页只暴露难度选项，消除次数和难度数值由选项稳定派生给后端。
const MATCH3D_DIFFICULTY_OPTIONS = [
  { id: 'easy', label: '轻松', clearCount: 8, difficulty: 2 },
  { id: 'standard', label: '标准', clearCount: 12, difficulty: 4 },
  { id: 'advanced', label: '进阶', clearCount: 16, difficulty: 6 },
  { id: 'hardcore', label: '硬核', clearCount: 21, difficulty: 8 },
] as const;

type Match3DDifficultyOptionId =
  (typeof MATCH3D_DIFFICULTY_OPTIONS)[number]['id'];

const MATCH3D_ASSET_STYLE_OPTIONS = [
  {
    id: 'flat-icon',
    label: '扁平图标',
    imageSrc: '/match3d-style-references/flat-icon.png',
    prompt:
      '干净扁平的2D游戏道具图标风格，正面视角，色块清楚，边缘硬朗。',
  },
  {
    id: 'cel-cartoon',
    label: '赛璐璐卡通',
    imageSrc: '/match3d-style-references/cel-cartoon.png',
    prompt:
      '明亮赛璐璐卡通2D游戏道具风格，清晰线稿，硬边阴影，饱和配色，轮廓醒目。',
  },
  {
    id: 'pixel-retro',
    label: '像素',
    imageSrc: '/match3d-style-references/pixel-retro.png',
    prompt:
      '像素2D游戏道具sprite风格',
  },
  {
    id: 'watercolor',
    label: '手绘水彩',
    imageSrc: '/match3d-style-references/watercolor.png',
    prompt:
      '手绘水彩2D道具素材风格',
  },
  {
    id: 'sticker-outline',
    label: '贴纸描边',
    imageSrc: '/match3d-style-references/sticker-outline.png',
    prompt:
      '贴纸描边2D游戏道具素材风格，粗白边与深色外轮廓',
  },
  {
    id: 'painterly-icon',
    label: '厚涂图标',
    imageSrc: '/match3d-style-references/painterly-icon.png',
    prompt:
      '厚涂2D游戏道具图标风格，笔触细腻，体积光影明确，中心构图，保持图标级清晰剪影。',
  },
  {
    id: 'custom',
    label: '自定义',
    imageSrc: null,
    prompt: '',
  },
] as const;

type Match3DAssetStyleOptionId =
  (typeof MATCH3D_ASSET_STYLE_OPTIONS)[number]['id'];

function normalizeDifficulty(value: number) {
  return Math.max(1, Math.min(10, Math.round(value)));
}

function resolveDifficultyOptionId(
  difficulty: number | null | undefined,
  clearCount: number | null | undefined,
): Match3DDifficultyOptionId {
  const clearCountMatchedOption = MATCH3D_DIFFICULTY_OPTIONS.find(
    (option) => option.clearCount === clearCount,
  );
  if (clearCountMatchedOption) {
    return clearCountMatchedOption.id;
  }

  if (typeof difficulty !== 'number' || !Number.isFinite(difficulty)) {
    return 'standard';
  }

  const normalizedDifficulty = normalizeDifficulty(Number(difficulty));
  return MATCH3D_DIFFICULTY_OPTIONS.reduce(
    (nearestOption, option) =>
      Math.abs(option.difficulty - normalizedDifficulty) <
      Math.abs(nearestOption.difficulty - normalizedDifficulty)
        ? option
        : nearestOption,
    MATCH3D_DIFFICULTY_OPTIONS[1],
  ).id;
}

function getDifficultyOption(optionId: Match3DDifficultyOptionId) {
  return (
    MATCH3D_DIFFICULTY_OPTIONS.find((option) => option.id === optionId) ??
    MATCH3D_DIFFICULTY_OPTIONS[1]
  );
}

function getAssetStyleOption(optionId: Match3DAssetStyleOptionId) {
  return (
    MATCH3D_ASSET_STYLE_OPTIONS.find((option) => option.id === optionId) ??
    MATCH3D_ASSET_STYLE_OPTIONS[0]
  );
}

function resolveAssetStyleOptionId(
  assetStyleId: string | null | undefined,
  assetStylePrompt: string | null | undefined,
): Match3DAssetStyleOptionId {
  const matchedOption = MATCH3D_ASSET_STYLE_OPTIONS.find(
    (option) => option.id === assetStyleId,
  );
  if (matchedOption) {
    return matchedOption.id;
  }

  return assetStylePrompt?.trim() ? 'custom' : 'flat-icon';
}

function resolveInitialFormState(
  session: Match3DAgentSessionSnapshot | null,
  initialFormPayload: CreateMatch3DSessionRequest | null = null,
): Match3DFormState {
  const config = session?.config;
  const themeText =
    initialFormPayload?.themeText?.trim() ||
    config?.themeText?.trim() ||
    session?.anchorPack.theme.value?.trim() ||
    initialFormPayload?.seedText?.trim() ||
    '';
  const clearCount =
    initialFormPayload?.clearCount ?? config?.clearCount ?? null;
  const difficulty =
    initialFormPayload?.difficulty ?? config?.difficulty ?? null;
  const assetStyleId =
    initialFormPayload?.assetStyleId ?? config?.assetStyleId ?? null;
  const assetStylePrompt =
    initialFormPayload?.assetStylePrompt ?? config?.assetStylePrompt ?? '';

  return {
    ...EMPTY_FORM_STATE,
    themeText,
    difficultyOptionId: resolveDifficultyOptionId(difficulty, clearCount),
    assetStyleId: resolveAssetStyleOptionId(assetStyleId, assetStylePrompt),
    customAssetStylePrompt: assetStylePrompt,
  };
}

/**
 * 抓大鹅创作入口已从固定 Agent 追问改成表单式。
 * 组件名保留为 Match3DAgentWorkspace，兼容现有路由、草稿恢复和父层分流。
 */
export function Match3DAgentWorkspace({
  session,
  isBusy = false,
  error = null,
  onBack,
  onExecuteAction,
  onCreateFromForm,
  initialFormPayload = null,
  showBackButton = true,
  title = '想做个什么玩法？',
}: Match3DAgentWorkspaceProps) {
  const [formState, setFormState] = useState<Match3DFormState>(() =>
    resolveInitialFormState(session, initialFormPayload),
  );
  const [isCustomStylePanelOpen, setIsCustomStylePanelOpen] = useState(false);
  const [draftCustomStylePrompt, setDraftCustomStylePrompt] = useState('');
  const appliedInitialFormKeyRef = useRef<string | null>(null);

  useEffect(() => {
    const nextInitialFormKey =
      session?.sessionId ?? JSON.stringify(initialFormPayload ?? null);
    if (appliedInitialFormKeyRef.current === nextInitialFormKey) {
      return;
    }

    appliedInitialFormKeyRef.current = nextInitialFormKey;
    setFormState(resolveInitialFormState(session, initialFormPayload));
    setIsCustomStylePanelOpen(false);
    setDraftCustomStylePrompt('');
  }, [initialFormPayload, session]);

  const themeText = formState.themeText.trim();
  const selectedDifficultyOption = getDifficultyOption(
    formState.difficultyOptionId,
  );
  const selectedAssetStyleOption = getAssetStyleOption(formState.assetStyleId);
  const assetStylePrompt =
    formState.assetStyleId === 'custom'
      ? formState.customAssetStylePrompt.trim()
      : selectedAssetStyleOption.prompt;
  const assetStyleLabel =
    formState.assetStyleId === 'custom'
      ? '自定义风格'
      : selectedAssetStyleOption.label;
  const canSubmit = Boolean(
    themeText &&
      !isBusy &&
      (formState.assetStyleId !== 'custom' ||
        formState.customAssetStylePrompt.trim()),
  );
  const formPayload = useMemo<CreateMatch3DSessionRequest>(
    () => ({
      seedText: themeText
        ? `${themeText}题材，消除${selectedDifficultyOption.clearCount}次，难度${selectedDifficultyOption.difficulty}`
        : themeText,
      themeText,
      referenceImageSrc: null,
      clearCount: selectedDifficultyOption.clearCount,
      difficulty: selectedDifficultyOption.difficulty,
      assetStyleId: formState.assetStyleId,
      assetStyleLabel,
      assetStylePrompt,
      generateClickSound: false,
    }),
    [
      assetStyleLabel,
      assetStylePrompt,
      formState.assetStyleId,
      selectedDifficultyOption,
      themeText,
    ],
  );

  const openCustomStylePanel = () => {
    setDraftCustomStylePrompt(formState.customAssetStylePrompt);
    setIsCustomStylePanelOpen(true);
  };

  const applyCustomStylePrompt = () => {
    setFormState((current) => ({
      ...current,
      assetStyleId: 'custom',
      customAssetStylePrompt: draftCustomStylePrompt.trim(),
    }));
    setIsCustomStylePanelOpen(false);
  };

  const submitForm = () => {
    if (!canSubmit) {
      return;
    }

    if (onCreateFromForm) {
      onCreateFromForm(formPayload);
      return;
    }

    if (session) {
      onExecuteAction({
        action: 'match3d_compile_draft',
        generateClickSound: false,
      });
    }
  };

  return (
    <div className="platform-remap-surface mx-auto flex h-full min-h-0 w-full max-w-5xl flex-col overflow-hidden">
      {showBackButton ? (
        <div className="mb-3 flex shrink-0 items-center justify-between gap-3 sm:mb-4">
          <button
            type="button"
            onClick={onBack}
            disabled={isBusy}
            className={`platform-button platform-button--ghost min-h-0 self-start px-3 py-1.5 text-[11px] ${isBusy ? 'opacity-45' : ''}`}
          >
            返回
          </button>
        </div>
      ) : null}

      <div className="flex min-h-0 flex-1 flex-col overflow-hidden pr-0">
        {title ? (
          <div className="mb-3 shrink-0 sm:mb-5">
            <div className="flex flex-wrap items-center gap-2">
              <h1 className="m-0 text-3xl font-black leading-none tracking-normal text-[var(--platform-text-strong)] sm:text-7xl">
                {title}
              </h1>
              <span className="rounded-full border border-emerald-200 bg-emerald-50 px-3 py-1 text-[11px] font-black text-emerald-700">
                BETA
              </span>
            </div>
          </div>
        ) : null}

        <section className="flex min-h-0 flex-1 flex-col overflow-hidden">
          <div
            className={`grid min-h-0 flex-1 grid-rows-[minmax(0,1fr)_auto] gap-3 lg:grid-cols-[minmax(0,1.1fr)_minmax(16rem,0.9fr)] lg:grid-rows-1 ${isBusy ? 'opacity-55' : ''}`}
          >
            <label className="block min-h-0">
              <span className="mb-2 block text-sm font-black text-[var(--platform-text-strong)]">
                想做一个什么题材的抓大鹅？
              </span>
              <textarea
                value={formState.themeText}
                disabled={isBusy}
                rows={5}
                placeholder=""
                onChange={(event) =>
                  setFormState((current) => ({
                    ...current,
                    themeText: event.target.value,
                  }))
                }
                className="h-full min-h-[7.75rem] w-full resize-none rounded-[1.15rem] border border-[var(--platform-subpanel-border)] bg-white/90 px-4 py-3 text-base leading-6 text-[var(--platform-text-strong)] outline-none transition focus:border-rose-200 focus:bg-white focus:ring-2 focus:ring-rose-100 sm:min-h-[9rem] lg:min-h-[14rem]"
                aria-label="想做一个什么题材的抓大鹅？"
              />
            </label>

            <div className="flex min-h-0 flex-col gap-2 overflow-hidden">
              <div className="min-h-0 rounded-[1.05rem] border border-[var(--platform-subpanel-border)] bg-white/52 p-2.5 shadow-[inset_0_1px_0_rgba(255,255,255,0.78)]">
                <div className="mb-1.5 text-sm font-black text-[var(--platform-text-strong)]">
                  2D素材风格
                </div>
                <div
                  className="flex snap-x gap-2.5 overflow-x-auto overscroll-x-contain pb-0.5 scrollbar-hide touch-pan-x [-webkit-overflow-scrolling:touch]"
                  aria-label="2D素材风格"
                >
                  {MATCH3D_ASSET_STYLE_OPTIONS.map((option) => {
                    const selected = formState.assetStyleId === option.id;
                    const isCustom = option.id === 'custom';
                    return (
                      <button
                        key={option.id}
                        type="button"
                        disabled={isBusy}
                        onClick={() => {
                          if (isCustom) {
                            openCustomStylePanel();
                            return;
                          }
                          setFormState((current) => ({
                            ...current,
                            assetStyleId: option.id,
                          }));
                        }}
                        className={`group relative h-[4.9rem] w-[5.85rem] shrink-0 snap-start overflow-hidden rounded-[0.95rem] border p-0 text-left transition focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-rose-200 sm:h-[5.45rem] sm:w-[6.4rem] ${
                          selected
                            ? 'border-rose-300 bg-white shadow-[0_8px_18px_rgba(190,18,60,0.10)] ring-2 ring-rose-100'
                            : 'border-[var(--platform-subpanel-border)] bg-white/70 hover:border-rose-200 hover:bg-white/95'
                        } ${isBusy ? 'cursor-not-allowed opacity-55' : ''}`}
                        aria-pressed={selected}
                        aria-label={option.label}
                      >
                        {option.imageSrc ? (
                          <img
                            src={option.imageSrc}
                            alt=""
                            className="absolute inset-0 h-full w-full object-cover transition duration-200 group-hover:scale-[1.03]"
                            loading="lazy"
                          />
                        ) : (
                          <span className="absolute inset-0 bg-[radial-gradient(circle_at_32%_24%,rgba(255,255,255,0.98),transparent_30%),linear-gradient(135deg,rgba(255,247,250,0.98),rgba(255,236,241,0.92))]" />
                        )}
                        <span className="absolute inset-0 bg-[linear-gradient(180deg,rgba(255,255,255,0.02)_0%,rgba(255,255,255,0.18)_44%,rgba(255,255,255,0.82)_100%)]" />
                        {selected ? (
                          <span className="absolute right-1.5 top-1.5 h-2.5 w-2.5 rounded-full bg-rose-400 shadow-[0_0_0_3px_rgba(255,255,255,0.84)]" />
                        ) : null}
                        {isCustom ? (
                          <span className="absolute inset-0 flex items-center justify-center text-rose-500">
                            <span className="grid h-8 w-8 place-items-center rounded-full bg-white/82 shadow-[0_6px_18px_rgba(190,18,60,0.12)]">
                              <Plus className="h-5 w-5" />
                            </span>
                          </span>
                        ) : null}
                        <span
                          className={`absolute inset-x-2 bottom-1.5 truncate rounded-full px-1.5 py-0.5 text-center text-[11px] font-black shadow-[0_3px_10px_rgba(15,23,42,0.10)] ${
                            selected
                              ? 'bg-rose-50/95 text-rose-700'
                              : 'bg-white/88 text-[var(--platform-text-strong)]'
                          }`}
                        >
                          {option.label}
                        </span>
                      </button>
                    );
                  })}
                </div>
              </div>

              <div className="shrink-0 rounded-[1.05rem] border border-[var(--platform-subpanel-border)] bg-white/44 p-2.5 shadow-[inset_0_1px_0_rgba(255,255,255,0.7)]">
                <div className="mb-1.5 text-sm font-black text-[var(--platform-text-strong)]">
                  难度
                </div>
                <div className="grid grid-cols-4 gap-1.5 sm:gap-2 lg:grid-cols-2">
                  {MATCH3D_DIFFICULTY_OPTIONS.map((option) => {
                    const selected = formState.difficultyOptionId === option.id;
                    return (
                      <button
                        key={option.id}
                        type="button"
                        disabled={isBusy}
                        onClick={() =>
                          setFormState((current) => ({
                            ...current,
                            difficultyOptionId: option.id,
                          }))
                        }
                        className={`min-h-10 rounded-[0.85rem] border px-2 text-sm font-black transition focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-rose-200 sm:min-h-11 ${
                          selected
                            ? 'border-[#ff7890] bg-[linear-gradient(180deg,#ff7890_0%,#ff4f6a_100%)] text-white shadow-[0_8px_18px_rgba(244,63,94,0.16)]'
                            : 'border-[var(--platform-subpanel-border)] bg-white/76 text-[var(--platform-text-strong)] hover:border-rose-200 hover:bg-white'
                        } ${isBusy ? 'cursor-not-allowed opacity-55' : ''}`}
                        aria-pressed={selected}
                      >
                        {option.label}
                      </button>
                    );
                  })}
                </div>
              </div>
            </div>
          </div>

          <div className="mt-2 shrink-0 space-y-3">
            {error ? (
              <div className="platform-banner platform-banner--danger rounded-2xl text-sm leading-6">
                {error}
              </div>
            ) : null}
          </div>
        </section>
      </div>

      <div className="mt-2 flex shrink-0 justify-center pb-[max(0.25rem,env(safe-area-inset-bottom))] sm:mt-3">
        <button
          type="button"
          disabled={!canSubmit}
          onClick={submitForm}
          className={`platform-button platform-button--primary min-h-10 px-4 py-2 text-sm sm:min-h-11 sm:px-5 ${!canSubmit ? 'cursor-not-allowed opacity-55' : ''}`}
        >
          <span className="inline-flex flex-wrap items-center justify-center gap-1.5 sm:gap-2">
            {isBusy ? <Loader2 className="h-4 w-4 animate-spin" /> : null}
            {session ? (
              <Sparkles className="h-4 w-4" />
            ) : (
              <WandSparkles className="h-4 w-4" />
            )}
            <span>生成抓大鹅草稿</span>
            <span className="rounded-full bg-white/24 px-2 py-0.5 text-[11px] font-bold">
              消耗10泥点
            </span>
          </span>
        </button>
      </div>

      {isCustomStylePanelOpen ? (
        <div className="platform-modal-backdrop fixed inset-0 z-[80] flex items-center justify-center px-4 py-6">
          <div
            role="dialog"
            aria-modal="true"
            aria-labelledby="match3d-custom-style-title"
            className="platform-modal-shell platform-remap-surface w-full max-w-sm rounded-[1.35rem] p-5 shadow-[0_24px_70px_rgba(15,23,42,0.22)]"
          >
            <div className="flex items-center justify-between gap-3">
              <div
                id="match3d-custom-style-title"
                className="text-base font-black text-[var(--platform-text-strong)]"
              >
                自定义风格
              </div>
              <button
                type="button"
                aria-label="关闭自定义风格"
                onClick={() => setIsCustomStylePanelOpen(false)}
                className="platform-profile-icon-button flex h-8 w-8 items-center justify-center rounded-full"
              >
                <X className="h-4 w-4" />
              </button>
            </div>
            <textarea
              value={draftCustomStylePrompt}
              onChange={(event) =>
                setDraftCustomStylePrompt(event.target.value)
              }
              rows={4}
              className="mt-4 h-[7.5rem] w-full resize-none rounded-[1rem] border border-[var(--platform-subpanel-border)] bg-white/90 px-4 py-3 text-base leading-6 text-[var(--platform-text-strong)] outline-none transition focus:border-rose-200 focus:bg-white focus:ring-2 focus:ring-rose-100"
              aria-label="自定义2D素材风格描述"
            />
            <div className="mt-5 grid grid-cols-2 gap-3">
              <button
                type="button"
                onClick={() => setIsCustomStylePanelOpen(false)}
                className="platform-button platform-button--secondary justify-center"
              >
                取消
              </button>
              <button
                type="button"
                disabled={!draftCustomStylePrompt.trim()}
                onClick={applyCustomStylePrompt}
                className={`platform-button platform-button--primary justify-center ${!draftCustomStylePrompt.trim() ? 'cursor-not-allowed opacity-55' : ''}`}
              >
                应用
              </button>
            </div>
          </div>
        </div>
      ) : null}
    </div>
  );
}

export default Match3DAgentWorkspace;
