import { ArrowLeft, ImagePlus, Loader2, Sparkles, X } from 'lucide-react';
import { type ChangeEvent, useEffect, useMemo, useRef, useState } from 'react';

import type { PuzzleAgentActionRequest } from '../../../packages/shared/src/contracts/puzzleAgentActions';
import type {
  CreatePuzzleAgentSessionRequest,
  PuzzleAgentSessionSnapshot,
  SendPuzzleAgentMessageRequest,
} from '../../../packages/shared/src/contracts/puzzleAgentSession';
import { readPuzzleReferenceImageAsDataUrl } from '../../services/puzzleReferenceImage';
import {
  normalizePuzzleImageModel,
  PUZZLE_IMAGE_MODEL_GPT_IMAGE_2,
  type PuzzleImageModelId,
} from './puzzleImageModelOptions';
import { PuzzleImageModelPicker } from './PuzzleImageModelPicker';

type PuzzleAgentWorkspaceProps = {
  session: PuzzleAgentSessionSnapshot | null;
  isBusy?: boolean;
  error?: string | null;
  onBack: () => void;
  onSubmitMessage: (payload: SendPuzzleAgentMessageRequest) => void;
  onExecuteAction: (payload: PuzzleAgentActionRequest) => void;
  onCreateFromForm?: (payload: CreatePuzzleAgentSessionRequest) => void;
  onAutoSaveForm?: (payload: CreatePuzzleAgentSessionRequest) => void;
  initialFormPayload?: CreatePuzzleAgentSessionRequest | null;
};

type PuzzleFormState = {
  workTitle: string;
  workDescription: string;
  pictureDescription: string;
  referenceImageSrc: string;
  referenceImageLabel: string;
  imageModel: PuzzleImageModelId;
};

const EMPTY_FORM_STATE: PuzzleFormState = {
  workTitle: '',
  workDescription: '',
  pictureDescription: '',
  referenceImageSrc: '',
  referenceImageLabel: '',
  imageModel: PUZZLE_IMAGE_MODEL_GPT_IMAGE_2,
};

function resolveInitialFormState(
  session: PuzzleAgentSessionSnapshot | null,
  initialFormPayload: CreatePuzzleAgentSessionRequest | null = null,
): PuzzleFormState {
  const formDraft = session?.draft?.formDraft;
  if (formDraft) {
    return {
      workTitle: formDraft.workTitle ?? '',
      workDescription: formDraft.workDescription ?? '',
      pictureDescription: formDraft.pictureDescription ?? '',
      referenceImageSrc: initialFormPayload?.referenceImageSrc ?? '',
      referenceImageLabel: initialFormPayload?.referenceImageSrc
        ? '已选择参考图'
        : '',
      imageModel: normalizePuzzleImageModel(initialFormPayload?.imageModel),
    };
  }

  if (initialFormPayload) {
    return {
      workTitle:
        initialFormPayload.workTitle ?? initialFormPayload.seedText ?? '',
      workDescription: initialFormPayload.workDescription ?? '',
      pictureDescription: initialFormPayload.pictureDescription ?? '',
      referenceImageSrc: initialFormPayload.referenceImageSrc ?? '',
      referenceImageLabel: initialFormPayload.referenceImageSrc
        ? '已选择参考图'
        : '',
      imageModel: normalizePuzzleImageModel(initialFormPayload.imageModel),
    };
  }

  if (!session) {
    return EMPTY_FORM_STATE;
  }

  return {
    workTitle:
      session.draft?.workTitle ||
      session.draft?.levelName ||
      session.seedText ||
      session.anchorPack.themePromise.value ||
      session.messages.find((message) => message.role === 'user')?.text ||
      '',
    workDescription:
      session.draft?.workDescription ||
      session.anchorPack.themePromise.value ||
      '',
    pictureDescription:
      session.draft?.summary || session.anchorPack.visualSubject.value || '',
    referenceImageSrc: '',
    referenceImageLabel: '',
    imageModel: PUZZLE_IMAGE_MODEL_GPT_IMAGE_2,
  };
}

/**
 * 拼图创作入口已从 Agent 对话改为填表式。
 * 组件名保留为 PuzzleAgentWorkspace 以兼容现有路由与草稿恢复入口。
 */
export function PuzzleAgentWorkspace({
  session,
  isBusy = false,
  error = null,
  onBack,
  onExecuteAction,
  onCreateFromForm,
  onAutoSaveForm,
  initialFormPayload = null,
}: PuzzleAgentWorkspaceProps) {
  const [formState, setFormState] = useState<PuzzleFormState>(() =>
    resolveInitialFormState(session, initialFormPayload),
  );
  const [referenceImageError, setReferenceImageError] = useState<string | null>(
    null,
  );
  const previousSessionIdRef = useRef<string | null>(
    session?.sessionId ?? null,
  );
  const appliedInitialFormKeyRef = useRef<string | null>(null);

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

    previousSessionIdRef.current = currentSessionId;
    const nextInitialFormKey =
      currentSessionId ?? JSON.stringify(initialFormPayload ?? null);
    if (appliedInitialFormKeyRef.current === nextInitialFormKey) {
      return;
    }

    appliedInitialFormKeyRef.current = nextInitialFormKey;
    setFormState(resolveInitialFormState(session, initialFormPayload));
    setReferenceImageError(null);
  }, [initialFormPayload, session?.sessionId]);

  const workTitle = formState.workTitle.trim();
  const workDescription = formState.workDescription.trim();
  const pictureDescription = formState.pictureDescription.trim();
  const canSubmit =
    Boolean(workTitle && workDescription && pictureDescription) && !isBusy;
  const autosavePayload = useMemo(
    () => ({
      seedText: workTitle,
      workTitle,
      workDescription,
      pictureDescription,
      referenceImageSrc: formState.referenceImageSrc || null,
      imageModel: formState.imageModel,
    }),
    [
      formState.referenceImageSrc,
      formState.imageModel,
      pictureDescription,
      workDescription,
      workTitle,
    ],
  );
  const autosaveSignature = JSON.stringify([
    autosavePayload.workTitle,
    autosavePayload.workDescription,
    autosavePayload.pictureDescription,
    autosavePayload.imageModel,
  ]);
  const lastAutosaveSignatureRef = useRef(autosaveSignature);
  const autosaveSessionIdRef = useRef(session?.sessionId ?? null);

  useEffect(() => {
    const currentSessionId = session?.sessionId ?? null;
    if (autosaveSessionIdRef.current === currentSessionId) {
      return;
    }

    autosaveSessionIdRef.current = currentSessionId;
    lastAutosaveSignatureRef.current = autosaveSignature;
  }, [autosaveSignature, session?.sessionId]);

  useEffect(() => {
    if (
      !session ||
      session.stage !== 'collecting_anchors' ||
      !session.draft?.formDraft ||
      !onAutoSaveForm ||
      lastAutosaveSignatureRef.current === autosaveSignature
    ) {
      return;
    }

    const timer = window.setTimeout(() => {
      lastAutosaveSignatureRef.current = autosaveSignature;
      onAutoSaveForm(autosavePayload);
    }, 700);

    return () => window.clearTimeout(timer);
  }, [
    autosavePayload,
    autosaveSignature,
    onAutoSaveForm,
    session?.draft?.formDraft,
    session?.stage,
    session?.sessionId,
  ]);

  const handleReferenceImageChange = async (
    event: ChangeEvent<HTMLInputElement>,
  ) => {
    const file = event.target.files?.[0];
    event.currentTarget.value = '';
    if (!file) {
      return;
    }

    try {
      const dataUrl = await readPuzzleReferenceImageAsDataUrl(file);
      setFormState((current) => ({
        ...current,
        referenceImageSrc: dataUrl,
        referenceImageLabel: file.name.trim() || '本地参考图',
      }));
      setReferenceImageError(null);
    } catch (uploadError) {
      setReferenceImageError(
        uploadError instanceof Error
          ? uploadError.message
          : '参考图读取失败，请重试。',
      );
    }
  };

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

    const payload = {
      seedText: workTitle,
      workTitle,
      workDescription,
      pictureDescription,
      referenceImageSrc: formState.referenceImageSrc || null,
      imageModel: formState.imageModel,
    };

    if (!session && onCreateFromForm) {
      onCreateFromForm(payload);
      return;
    }

    onExecuteAction({
      action: 'compile_puzzle_draft',
      promptText: pictureDescription,
      workTitle,
      workDescription,
      pictureDescription,
      referenceImageSrc: formState.referenceImageSrc || null,
      imageModel: formState.imageModel,
      candidateCount: 1,
    });
  };

  return (
    <div className="platform-remap-surface mx-auto flex h-full min-h-0 w-full max-w-4xl flex-col">
      <div className="mb-4 flex items-center justify-between gap-3">
        <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' : ''}`}
        >
          <span className="inline-flex items-center gap-1.5">
            <ArrowLeft className="h-3.5 w-3.5" />
            返回
          </span>
        </button>
      </div>

      <div className="min-h-0 flex-1 overflow-y-auto pr-1">
        <section className="platform-subpanel rounded-[1.5rem] p-4 sm:p-5">
          <div className="space-y-5">
            <label className="block">
              <span className="text-xs font-bold tracking-[0.18em] text-[var(--platform-text-soft)]">
                作品名称
              </span>
              <input
                value={formState.workTitle}
                disabled={isBusy}
                onChange={(event) =>
                  setFormState((current) => ({
                    ...current,
                    workTitle: event.target.value,
                  }))
                }
                className="mt-2 w-full rounded-[1rem] border border-[var(--platform-subpanel-border)] bg-white/90 px-4 py-3 text-base font-semibold text-[var(--platform-text-strong)] outline-none"
                aria-label="作品名称"
              />
            </label>

            <label className="block">
              <span className="text-xs font-bold tracking-[0.18em] text-[var(--platform-text-soft)]">
                作品描述
              </span>
              <textarea
                value={formState.workDescription}
                disabled={isBusy}
                rows={4}
                onChange={(event) =>
                  setFormState((current) => ({
                    ...current,
                    workDescription: event.target.value,
                  }))
                }
                className="mt-2 w-full resize-none rounded-[1rem] border border-[var(--platform-subpanel-border)] bg-white/90 px-4 py-3 text-sm leading-6 text-[var(--platform-text-strong)] outline-none"
                aria-label="作品描述"
              />
            </label>

            <label className="block">
              <span className="text-xs font-bold tracking-[0.18em] text-[var(--platform-text-soft)]">
                画面描述
              </span>
              <div className="relative mt-2">
                <textarea
                  value={formState.pictureDescription}
                  disabled={isBusy}
                  rows={10}
                  onChange={(event) =>
                    setFormState((current) => ({
                      ...current,
                      pictureDescription: event.target.value,
                    }))
                  }
                  className="w-full resize-none rounded-[1rem] border border-[var(--platform-subpanel-border)] bg-white/90 px-4 py-3 pb-16 text-sm leading-6 text-[var(--platform-text-strong)] outline-none"
                  aria-label="画面描述"
                />
                <PuzzleImageModelPicker
                  value={formState.imageModel}
                  disabled={isBusy}
                  onChange={(imageModel) =>
                    setFormState((current) => ({
                      ...current,
                      imageModel,
                    }))
                  }
                />
                <label
                  className={`absolute bottom-3 right-3 inline-flex h-10 w-10 cursor-pointer items-center justify-center rounded-full border border-amber-300/70 bg-white/96 text-amber-700 shadow-sm transition hover:bg-amber-50 ${isBusy ? 'cursor-not-allowed opacity-55' : ''}`}
                  title={
                    formState.referenceImageSrc ? '更换参考图' : '添加参考图'
                  }
                >
                  <ImagePlus className="h-4 w-4" />
                  <span className="sr-only">
                    {formState.referenceImageSrc ? '更换参考图' : '添加参考图'}
                  </span>
                  <input
                    type="file"
                    accept="image/png,image/jpeg,image/webp"
                    disabled={isBusy}
                    onChange={(event) => {
                      void handleReferenceImageChange(event);
                    }}
                    className="hidden"
                  />
                </label>
              </div>
            </label>

            {formState.referenceImageSrc ? (
              <div className="flex items-center gap-3 rounded-[1rem] border border-[var(--platform-subpanel-border)] bg-white/72 px-3 py-3">
                <div className="h-14 w-14 overflow-hidden rounded-[0.9rem] bg-[var(--platform-subpanel-fill)]">
                  <img
                    src={formState.referenceImageSrc}
                    alt="拼图参考图"
                    className="h-full w-full object-cover"
                  />
                </div>
                <div className="min-w-0 flex-1">
                  <div className="truncate text-sm font-semibold text-[var(--platform-text-strong)]">
                    {formState.referenceImageLabel || '已选择参考图'}
                  </div>
                </div>
                <button
                  type="button"
                  disabled={isBusy}
                  onClick={() => {
                    setFormState((current) => ({
                      ...current,
                      referenceImageSrc: '',
                      referenceImageLabel: '',
                    }));
                    setReferenceImageError(null);
                  }}
                  className="platform-icon-button h-9 w-9"
                  aria-label="移除参考图"
                  title="移除参考图"
                >
                  <X className="h-4 w-4" />
                </button>
              </div>
            ) : null}

            {referenceImageError ? (
              <div className="platform-banner platform-banner--danger rounded-2xl text-sm leading-6">
                {referenceImageError}
              </div>
            ) : null}
            {error ? (
              <div className="platform-banner platform-banner--danger rounded-2xl text-sm leading-6">
                {error}
              </div>
            ) : null}
          </div>
        </section>
      </div>

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

export default PuzzleAgentWorkspace;
