import {
  ArrowLeft,
  CheckCircle2,
  ImagePlus,
  Loader2,
  Play,
  RefreshCw,
  Upload,
} from 'lucide-react';
import {
  type ChangeEvent,
  type ReactNode,
  useMemo,
  useRef,
  useState,
} from 'react';

import type {
  BarkBattleConfigEditorPayload,
  BarkBattleDraftConfig,
} from '../../../packages/shared/src/contracts/barkBattle';
import {
  type BarkBattleAssetSlot,
  regenerateBarkBattleImageAsset,
  uploadBarkBattleAsset,
} from '../../services/bark-battle-creation';
import { PlatformActionButton } from '../common/PlatformActionButton';
import { PlatformPillBadge } from '../common/PlatformPillBadge';
import { PlatformStatusMessage } from '../common/PlatformStatusMessage';
import { PlatformSubpanel } from '../common/PlatformSubpanel';
import { BarkBattlePreviewCard } from './BarkBattlePreviewCard';

type BarkBattleResultViewProps = {
  draft: BarkBattleDraftConfig;
  isBusy?: boolean;
  error?: string | null;
  onBack: () => void;
  onDraftChange: (draft: BarkBattleDraftConfig) => void;
  onStartTestRun: (draft: BarkBattleDraftConfig) => void;
  onPublish: (draft: BarkBattleDraftConfig) => void;
};

const SLOT_LABELS = {
  'player-character': '玩家形象',
  'opponent-character': '对手形象',
  'ui-background': 'UI背景',
} satisfies Record<BarkBattleAssetSlot, string>;

function mapDraftToConfig(
  draft: BarkBattleDraftConfig,
): BarkBattleConfigEditorPayload {
  return {
    title: draft.title,
    description: draft.description,
    themeDescription: draft.themeDescription,
    playerImageDescription: draft.playerImageDescription,
    opponentImageDescription: draft.opponentImageDescription,
    onomatopoeia: draft.onomatopoeia,
    ...(draft.playerCharacterImageSrc
      ? { playerCharacterImageSrc: draft.playerCharacterImageSrc }
      : {}),
    ...(draft.opponentCharacterImageSrc
      ? { opponentCharacterImageSrc: draft.opponentCharacterImageSrc }
      : {}),
    ...(draft.uiBackgroundImageSrc
      ? { uiBackgroundImageSrc: draft.uiBackgroundImageSrc }
      : {}),
    difficultyPreset: draft.difficultyPreset,
  };
}

function applyAssetToDraft(
  draft: BarkBattleDraftConfig,
  slot: BarkBattleAssetSlot,
  assetSrc: string,
): BarkBattleDraftConfig {
  const updatedAt = new Date().toISOString();
  if (slot === 'player-character') {
    return { ...draft, playerCharacterImageSrc: assetSrc, updatedAt };
  }
  if (slot === 'opponent-character') {
    return { ...draft, opponentCharacterImageSrc: assetSrc, updatedAt };
  }
  if (slot === 'ui-background') {
    return { ...draft, uiBackgroundImageSrc: assetSrc, updatedAt };
  }
  return { ...draft, updatedAt };
}

function getSlotAssetSrc(
  draft: BarkBattleDraftConfig,
  slot: BarkBattleAssetSlot,
) {
  if (slot === 'player-character') {
    return draft.playerCharacterImageSrc ?? '';
  }
  if (slot === 'opponent-character') {
    return draft.opponentCharacterImageSrc ?? '';
  }
  if (slot === 'ui-background') {
    return draft.uiBackgroundImageSrc ?? '';
  }
  return '';
}

function ResultActionButton({
  children,
  disabled,
  onClick,
  tone = 'secondary',
}: {
  children: ReactNode;
  disabled?: boolean;
  onClick: () => void;
  tone?: 'primary' | 'secondary';
}) {
  return (
    <PlatformActionButton
      disabled={disabled}
      onClick={onClick}
      tone={tone}
      className="min-h-10 gap-2 text-sm sm:min-h-11"
    >
      {children}
    </PlatformActionButton>
  );
}

function BarkBattleAssetSlotControl({
  draft,
  slot,
  disabled,
  onChange,
  onError,
}: {
  draft: BarkBattleDraftConfig;
  slot: BarkBattleAssetSlot;
  disabled: boolean;
  onChange: (draft: BarkBattleDraftConfig) => void;
  onError: (message: string | null) => void;
}) {
  const fileInputRef = useRef<HTMLInputElement | null>(null);
  const [isUploading, setIsUploading] = useState(false);
  const [isRegenerating, setIsRegenerating] = useState(false);
  const assetSrc = getSlotAssetSrc(draft, slot);
  const assetStatus = assetSrc ? '已替换' : '未替换';

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

    setIsUploading(true);
    onError(null);
    try {
      const asset = await uploadBarkBattleAsset({
        slot,
        file,
        draftId: draft.draftId,
      });
      const nextDraft = applyAssetToDraft(draft, slot, asset.assetSrc);
      onChange(nextDraft);
    } catch (error) {
      onError(error instanceof Error ? error.message : '上传素材失败。');
    } finally {
      setIsUploading(false);
    }
  };

  const handleRegenerate = async () => {
    setIsRegenerating(true);
    onError(null);
    try {
      const result = await regenerateBarkBattleImageAsset({
        slot,
        config: mapDraftToConfig(draft),
        draftId: draft.draftId,
      });
      const nextDraft = applyAssetToDraft(draft, slot, result.imageSrc);
      onChange(nextDraft);
    } catch (error) {
      onError(error instanceof Error ? error.message : '重新生成素材失败。');
    } finally {
      setIsRegenerating(false);
    }
  };

  const isSlotBusy = isUploading || isRegenerating;

  return (
    <PlatformSubpanel
      as="article"
      surface="flat"
      radius="sm"
      padding="none"
      className="p-2.5 shadow-[inset_0_1px_0_rgba(255,255,255,0.74)] sm:p-3"
    >
      <div className="flex items-center justify-between gap-2 sm:gap-3">
        <div className="min-w-0">
          <h3 className="m-0 text-xs font-black text-[var(--platform-text-strong)] sm:text-sm">
            {SLOT_LABELS[slot]}
          </h3>
          <div className="mt-0.5 truncate text-[11px] font-semibold text-[var(--platform-text-soft)] sm:mt-1 sm:text-xs">
            {assetStatus}
          </div>
        </div>
        {isSlotBusy ? (
          <Loader2 className="h-4 w-4 shrink-0 animate-spin text-[var(--platform-text-soft)]" />
        ) : (
          <ImagePlus className="h-4 w-4 shrink-0 text-[var(--platform-text-soft)]" />
        )}
      </div>
      <div className="mt-2 grid grid-cols-2 gap-1.5 sm:mt-3 sm:gap-2">
        <input
          ref={fileInputRef}
          type="file"
          accept="image/png,image/jpeg,image/webp"
          className="hidden"
          aria-label={`上传${SLOT_LABELS[slot]}文件`}
          onChange={handleUpload}
        />
        <PlatformActionButton
          disabled={disabled || isSlotBusy}
          onClick={() => fileInputRef.current?.click()}
          tone="secondary"
          size="xs"
          shape="pill"
          className="min-h-8 gap-1.5 px-2.5 py-1 text-[11px] sm:min-h-9 sm:px-3 sm:py-1.5 sm:text-xs"
        >
          <Upload className="h-3.5 w-3.5" />
          上传
        </PlatformActionButton>
        <PlatformActionButton
          disabled={disabled || isSlotBusy}
          onClick={handleRegenerate}
          tone="secondary"
          size="xs"
          shape="pill"
          className="min-h-8 gap-1.5 px-2.5 py-1 text-[11px] sm:min-h-9 sm:px-3 sm:py-1.5 sm:text-xs"
        >
          <RefreshCw className="h-3.5 w-3.5" />
          重新生成
        </PlatformActionButton>
      </div>
    </PlatformSubpanel>
  );
}

export function BarkBattleResultView({
  draft,
  isBusy = false,
  error = null,
  onBack,
  onDraftChange,
  onStartTestRun,
  onPublish,
}: BarkBattleResultViewProps) {
  const [localError, setLocalError] = useState<string | null>(null);
  const previewConfig = useMemo(() => mapDraftToConfig(draft), [draft]);
  const visibleError = localError ?? error;
  const isActionBusy = isBusy;

  return (
    <div className="platform-page-stage platform-remap-surface flex h-full min-h-0 flex-col overflow-hidden px-2 pb-2 pt-2 sm:px-4 sm:pt-4 xl:px-5 xl:pb-4 xl:pt-4">
      <div className="mx-auto flex h-full min-h-0 w-full max-w-4xl flex-col">
        <div className="mb-2 flex shrink-0 items-center justify-between gap-2 sm:mb-3 sm:gap-3">
          <PlatformActionButton
            onClick={onBack}
            disabled={isActionBusy}
            tone="ghost"
            size="xs"
            className="min-h-0 gap-1.5 px-3 py-1.5 text-[11px]"
          >
            <ArrowLeft className="h-3.5 w-3.5" />
            返回编辑
          </PlatformActionButton>
          <PlatformPillBadge
            tone="success"
            size="xs"
            className="sm:px-3 sm:py-1"
          >
            草稿
          </PlatformPillBadge>
        </div>

        <div className="min-h-0 flex-1 overflow-y-auto pr-0.5">
          <section className="grid gap-2.5 lg:grid-cols-[minmax(0,0.94fr)_minmax(18rem,0.86fr)] lg:gap-3">
            <div className="grid gap-2.5 lg:gap-3">
              <PlatformSubpanel
                as="div"
                surface="flat"
                radius="md"
                padding="sm"
                className="shadow-[inset_0_1px_0_rgba(255,255,255,0.74)]"
                data-testid="bark-battle-draft-summary-panel"
              >
                <div className="text-xs font-black text-[var(--platform-text-soft)] sm:text-sm">
                  草稿编译
                </div>
                <h1 className="m-0 mt-1 text-2xl font-black leading-tight tracking-normal text-[var(--platform-text-strong)] sm:mt-2 sm:text-4xl lg:text-5xl">
                  {draft.title || '未命名声浪竞技场'}
                </h1>
              </PlatformSubpanel>
              <div className="grid gap-2 sm:grid-cols-2">
                {(
                  [
                    'player-character',
                    'opponent-character',
                    'ui-background',
                  ] as const
                ).map((slot) => (
                  <BarkBattleAssetSlotControl
                    key={slot}
                    draft={draft}
                    slot={slot}
                    disabled={isActionBusy}
                    onChange={(nextDraft) => {
                      setLocalError(null);
                      onDraftChange(nextDraft);
                    }}
                    onError={setLocalError}
                  />
                ))}
              </div>
            </div>
            <BarkBattlePreviewCard config={previewConfig} />
          </section>

          {visibleError ? (
            <PlatformStatusMessage
              tone="error"
              surface="platform"
              size="md"
              className="mt-3 rounded-2xl"
            >
              {visibleError}
            </PlatformStatusMessage>
          ) : null}
        </div>

        <div className="mt-3 grid shrink-0 gap-2 pb-[max(0.25rem,env(safe-area-inset-bottom))] sm:grid-cols-2">
          <ResultActionButton
            disabled={isActionBusy}
            onClick={() => onStartTestRun(draft)}
          >
            <Play className="h-4 w-4" />
            试玩
          </ResultActionButton>
          <ResultActionButton
            tone="primary"
            disabled={isActionBusy}
            onClick={() => onPublish(draft)}
          >
            {isBusy ? (
              <Loader2 className="h-4 w-4 animate-spin" />
            ) : (
              <CheckCircle2 className="h-4 w-4" />
            )}
            发布
          </ResultActionButton>
        </div>
      </div>
    </div>
  );
}

export default BarkBattleResultView;
