import { motion } from 'motion/react';
import type { CSSProperties } from 'react';
import { useEffect, useState } from 'react';

import type { CustomWorldGenerationProgress } from '../../packages/shared/src/contracts/runtime';
import type { CustomWorldStructuredAnchorEntry } from '../services/customWorldAgentGenerationProgress';

interface CustomWorldGenerationViewProps {
  settingText: string;
  anchorEntries?: CustomWorldStructuredAnchorEntry[];
  progress: CustomWorldGenerationProgress | null;
  isGenerating: boolean;
  error: string | null;
  onBack: () => void;
  onEditSetting: () => void;
  onRetry: () => void;
  onInterrupt?: () => void;
  backLabel?: string;
  settingActionLabel?: string | null;
  retryLabel?: string;
  interruptLabel?: string;
  settingTitle?: string;
  settingDescription?: string | null;
  progressTitle?: string;
  activeBadgeLabel?: string;
  pausedBadgeLabel?: string;
  idleBadgeLabel?: string;
  structuredEmptyText?: string;
  hideBatchModule?: boolean;
}

function formatDuration(ms: number) {
  const safeMs = Math.max(0, Math.round(ms));
  const totalSeconds = Math.ceil(safeMs / 1000);
  const minutes = Math.floor(totalSeconds / 60);
  const seconds = totalSeconds % 60;

  if (minutes <= 0) {
    return `${Math.max(1, seconds)} 秒`;
  }

  if (seconds === 0) {
    return `${minutes} 分钟`;
  }

  return `${minutes} 分 ${seconds} 秒`;
}

function getProgressPercentage(progress: CustomWorldGenerationProgress | null) {
  return Math.max(0, Math.min(100, progress?.overallProgress ?? 0));
}

function getStepProgressPercentage(step: {
  completed: number;
  total: number;
  status: string;
}) {
  if (step.status === 'completed') {
    return 100;
  }

  if (step.total <= 0) {
    return 0;
  }

  return Math.max(
    0,
    Math.min(100, Math.round((step.completed / step.total) * 100)),
  );
}

function getStepStatusLabel(step: { status: string }) {
  if (step.status === 'completed') {
    return '完成';
  }

  if (step.status === 'active') {
    return '进行中';
  }

  return '待处理';
}

function buildFallbackRenderKey(
  value: string | null | undefined,
  fallback: string,
) {
  const normalizedValue = value?.trim();
  return normalizedValue ? normalizedValue : fallback;
}

function useIsMobileGenerationLayout() {
  const [isMobile, setIsMobile] = useState(() => {
    if (
      typeof window === 'undefined' ||
      typeof window.matchMedia !== 'function'
    ) {
      return false;
    }

    return window.matchMedia('(max-width: 639px)').matches;
  });

  useEffect(() => {
    if (
      typeof window === 'undefined' ||
      typeof window.matchMedia !== 'function'
    ) {
      return undefined;
    }

    const mediaQuery = window.matchMedia('(max-width: 639px)');
    const syncMobileLayout = () => {
      setIsMobile(mediaQuery.matches);
    };

    syncMobileLayout();

    if (typeof mediaQuery.addEventListener === 'function') {
      mediaQuery.addEventListener('change', syncMobileLayout);
      return () => {
        mediaQuery.removeEventListener('change', syncMobileLayout);
      };
    }

    mediaQuery.addListener(syncMobileLayout);
    return () => {
      mediaQuery.removeListener(syncMobileLayout);
    };
  }, []);

  return isMobile;
}

export function CustomWorldGenerationView({
  settingText,
  anchorEntries = [],
  progress,
  isGenerating,
  error,
  onBack,
  onEditSetting,
  onRetry,
  onInterrupt,
  backLabel = '返回',
  settingActionLabel = '修改设定',
  retryLabel = '重新开始生成',
  interruptLabel = '中断世界生成',
  settingTitle = '玩家设定',
  settingDescription = '这段文本会直接驱动本轮世界框架、角色与场景生成。',
  progressTitle = '生成进度',
  activeBadgeLabel = '世界建设中',
  pausedBadgeLabel = '生成已暂停',
  idleBadgeLabel = '等待操作',
  structuredEmptyText = '正在整理当前设定结构，请稍后。',
  hideBatchModule = false,
}: CustomWorldGenerationViewProps) {
  const isMobileGenerationLayout = useIsMobileGenerationLayout();
  const progressValue = getProgressPercentage(progress);
  const steps = progress?.steps ?? [];
  const hasStructuredAnchors = anchorEntries.length > 0;
  // 允许不同生成场景按需隐藏第二模块的说明和次级返回动作。
  const normalizedSettingActionLabel = settingActionLabel?.trim() ?? '';
  const normalizedSettingDescription = settingDescription?.trim() ?? '';
  const hasSettingActionLabel = normalizedSettingActionLabel.length > 0;
  const hasSettingDescription = normalizedSettingDescription.length > 0;
  const shouldHideBatchModule =
    hideBatchModule ||
    progressTitle === '拼图草稿生成进度' ||
    progressTitle === '抓大鹅草稿生成进度';
  const estimatedWaitText =
    progress?.estimatedRemainingMs != null
      ? `预计还需 ${formatDuration(progress.estimatedRemainingMs)}`
      : '正在校准预计等待时间';
  const elapsedText =
    progress != null
      ? `已耗时 ${formatDuration(progress.elapsedMs)}`
      : '正在启动世界生成';

  return (
    <div
      className="flex h-full min-h-0 flex-col overflow-y-auto overscroll-y-contain pr-1 pb-[max(1rem,env(safe-area-inset-bottom))]"
      style={{ WebkitOverflowScrolling: 'touch' }}
    >
      <div className="platform-sticky-fade sticky top-0 z-20 -mx-3 mb-4 flex items-center justify-between gap-3 px-3 pb-3 pt-1 backdrop-blur-sm sm:static sm:mx-0 sm:bg-none sm:px-0 sm:pb-0 sm:pt-0 sm:backdrop-blur-none">
        <button
          type="button"
          onClick={onBack}
          className="platform-button platform-button--ghost min-h-0 px-3 py-1.5 text-[11px]"
        >
          {backLabel}
        </button>
        <div className="platform-pill platform-pill--cool px-3 py-1 text-[10px] tracking-[0.2em]">
          {isGenerating
            ? activeBadgeLabel
            : error
              ? pausedBadgeLabel
              : idleBadgeLabel}
        </div>
      </div>

      <div className="flex flex-none flex-col gap-4 xl:grid xl:min-h-0 xl:flex-1 xl:grid-cols-[minmax(0,1.35fr)_minmax(22rem,0.65fr)] xl:items-stretch">
        <section className="platform-surface platform-surface--soft flex flex-col px-4 py-3.5 xl:min-h-0 xl:flex-1 xl:px-5 xl:py-4">
          <div className="flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between xl:gap-6">
            <div className="min-w-0">
              <div className="text-[11px] font-bold tracking-[0.2em] text-zinc-400">
                {progressTitle}
              </div>
              <div className="mt-1 text-xl font-black leading-tight text-[var(--platform-text-strong)] sm:text-[2rem] xl:text-[2.4rem]">
                {progress?.phaseLabel ?? '正在启动世界生成'}
              </div>
              <div className="mt-2 max-w-[36rem] text-sm leading-6 text-zinc-300">
                {progress?.phaseDetail ?? '正在初始化世界生成链路与阶段监控。'}
              </div>
            </div>
            <div className="shrink-0 sm:text-right">
              <div className="text-[11px] tracking-[0.16em] text-zinc-500">
                总进度
              </div>
              <div className="mt-1 text-3xl font-black text-[var(--platform-cool-text)] sm:text-4xl">
                {progressValue}%
              </div>
            </div>
          </div>

          <div className="platform-progress-track mt-4 h-4 overflow-hidden rounded-full xl:mt-5 xl:h-5">
            <motion.div
              className="h-full bg-[linear-gradient(90deg,#ff4f8b_0%,#ff8a73_52%,#ffd2a6_100%)]"
              animate={{ width: `${progressValue}%` }}
              transition={{ duration: 0.35, ease: 'easeOut' }}
            />
          </div>

          <div
            className={`custom-world-generation-stats mt-4 grid gap-2 xl:gap-3 ${
              shouldHideBatchModule
                ? 'custom-world-generation-stats--two-column grid-cols-2'
                : 'sm:grid-cols-3'
            }`}
            style={
              shouldHideBatchModule
                ? { gridTemplateColumns: 'repeat(2, minmax(0, 1fr))' }
                : undefined
            }
          >
            {shouldHideBatchModule ? null : (
              <div className="platform-subpanel min-w-0 rounded-2xl px-4 py-3">
                <div className="text-[11px] tracking-[0.16em] text-zinc-500">
                  当前批次
                </div>
                <div className="mt-1 text-sm font-semibold text-white">
                  {progress?.batchLabel ?? '准备中'}
                </div>
              </div>
            )}
            <div className="platform-subpanel min-w-0 rounded-2xl px-3 py-3 sm:px-4">
              <div className="text-[11px] tracking-[0.16em] text-zinc-500">
                预计等待
              </div>
              <div className="mt-1 break-keep text-xs font-semibold text-white sm:text-sm">
                {estimatedWaitText}
              </div>
            </div>
            <div className="platform-subpanel min-w-0 rounded-2xl px-3 py-3 sm:px-4">
              <div className="text-[11px] tracking-[0.16em] text-zinc-500">
                计时
              </div>
              <div className="mt-1 break-keep text-xs font-semibold text-white sm:text-sm">
                {elapsedText}
              </div>
            </div>
          </div>

          <div className="mt-4 space-y-2 xl:grid xl:min-h-0 xl:flex-1 xl:grid-cols-2 xl:content-start xl:gap-2 xl:space-y-0 xl:overflow-y-auto xl:pr-1">
            {steps.map((step, index) => {
              const stepProgress = getStepProgressPercentage(step);

              return (
                <motion.div
                  key={buildFallbackRenderKey(
                    step.id,
                    `progress-step-${index}`,
                  )}
                  className={`rounded-2xl border px-4 py-3 transition-colors ${
                    step.status === 'completed'
                      ? 'border-emerald-400/16 bg-emerald-500/8'
                      : step.status === 'active'
                        ? 'border-sky-300/22 bg-sky-500/10'
                        : 'platform-subpanel'
                  } custom-world-generation-step`}
                  initial={
                    isMobileGenerationLayout
                      ? { opacity: 0, x: '-110vw' }
                      : false
                  }
                  animate={{ opacity: 1, x: 0 }}
                  transition={{
                    duration: 0.34,
                    ease: 'easeOut',
                    delay: isMobileGenerationLayout ? index * 0.09 : 0,
                  }}
                  style={
                    {
                      '--generation-step-delay': `${index * 90}ms`,
                    } as CSSProperties
                  }
                >
                  <div className="flex items-center justify-between gap-3">
                    <div className="min-w-0 text-sm font-semibold text-white">
                      {step.label}
                    </div>
                    <div className="shrink-0 text-xs font-semibold text-zinc-300">
                      {getStepStatusLabel(step)} {stepProgress}%
                    </div>
                  </div>
                  <div className="mt-2 h-2 overflow-hidden rounded-full bg-white/8">
                    <motion.div
                      className={`h-full rounded-full ${
                        step.status === 'completed'
                          ? 'bg-emerald-300'
                          : step.status === 'active'
                            ? 'bg-[linear-gradient(90deg,#7dd3fc_0%,#fcd34d_100%)]'
                            : 'bg-white/18'
                      }`}
                      animate={{ width: `${stepProgress}%` }}
                      transition={{ duration: 0.45, ease: 'easeOut' }}
                    />
                  </div>
                  <div className="mt-2 text-xs leading-6 text-zinc-400">
                    {step.detail}
                  </div>
                </motion.div>
              );
            })}
          </div>

          {error ? (
            <div className="mt-4 rounded-2xl border border-rose-400/18 bg-rose-500/10 px-4 py-3 text-sm leading-6 text-rose-100">
              {error}
            </div>
          ) : null}

          <div className="mt-4 flex flex-col gap-3 sm:flex-row sm:flex-wrap sm:justify-end">
            {!isGenerating ? (
              <>
                {hasSettingActionLabel ? (
                  <button
                    type="button"
                    onClick={onEditSetting}
                    className="platform-button platform-button--ghost min-h-0 rounded-full px-4 py-2 text-sm"
                  >
                    {normalizedSettingActionLabel}
                  </button>
                ) : null}
                <button
                  type="button"
                  onClick={onRetry}
                  className="platform-button platform-button--primary w-full sm:w-auto"
                >
                  {retryLabel}
                </button>
              </>
            ) : onInterrupt ? (
              <button
                type="button"
                onClick={onInterrupt}
                className="rounded-full border border-rose-300/18 bg-rose-500/10 px-4 py-2 text-sm text-rose-100 transition-colors hover:text-white"
              >
                {interruptLabel}
              </button>
            ) : null}
          </div>
        </section>

        <section className="platform-surface platform-surface--soft overflow-hidden px-4 py-3.5 xl:flex xl:min-h-0 xl:flex-col xl:px-5 xl:py-4">
          <div className="mb-3 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between xl:flex-col xl:items-start xl:gap-2">
            <div className="min-w-0">
              <div className="text-[11px] font-bold tracking-[0.2em] text-[var(--platform-cool-text)]">
                {settingTitle}
              </div>
              {hasSettingDescription ? (
                <div className="mt-1 text-sm text-zinc-400">
                  {normalizedSettingDescription}
                </div>
              ) : null}
            </div>
            {hasSettingActionLabel ? (
              <button
                type="button"
                onClick={onEditSetting}
                disabled={isGenerating}
                className={`platform-button platform-button--ghost min-h-0 px-3 py-1.5 text-[11px] ${isGenerating ? 'cursor-not-allowed opacity-40' : ''}`}
              >
                {normalizedSettingActionLabel}
              </button>
            ) : null}
          </div>
          {hasStructuredAnchors ? (
            <div className="grid grid-cols-1 gap-3 sm:grid-cols-2 xl:min-h-0 xl:flex-1 xl:grid-cols-1 xl:overflow-y-auto xl:pr-1">
              {anchorEntries.map((entry, index) => (
                <div
                  key={buildFallbackRenderKey(
                    entry.id,
                    `anchor-entry-${index}`,
                  )}
                  className="platform-subpanel rounded-2xl px-4 py-4 xl:py-3"
                >
                  <div className="text-[11px] font-bold tracking-[0.18em] text-zinc-500">
                    {entry.label}
                  </div>
                  <div className="mt-2 whitespace-pre-line text-sm leading-7 text-zinc-100">
                    {entry.value}
                  </div>
                </div>
              ))}
            </div>
          ) : (
            <div className="platform-subpanel whitespace-pre-line rounded-2xl px-4 py-4 text-sm leading-7 text-zinc-200 md:max-h-[16rem] md:overflow-y-auto xl:max-h-none xl:min-h-0 xl:flex-1">
              {settingText || structuredEmptyText}
            </div>
          )}
        </section>
      </div>
    </div>
  );
}
