import {
  ArrowLeft,
  Loader2,
  Play,
  Send,
  Shuffle,
} from 'lucide-react';
import { type CSSProperties, useState } from 'react';

import type {
  JumpHopDraftResponse,
  JumpHopPath,
  JumpHopTileAsset,
  JumpHopWorkProfileResponse,
} from '../../../packages/shared/src/contracts/jumpHop';
import {
  formatJumpHopDurationLabel,
  selectJumpHopTileAsset,
} from '../../services/jump-hop/jumpHopRuntimeModel';
import { useJumpHopLeaderboard } from '../../services/jump-hop/useJumpHopLeaderboard';
import { ResolvedAssetImage } from '../ResolvedAssetImage';

type JumpHopResultViewProps = {
  profile:
    | (JumpHopDraftResponse & {
        characterImageSrc?: string | null;
        tileAtlasImageSrc?: string | null;
        pathPreviewImageSrc?: string | null;
      })
    | (JumpHopWorkProfileResponse & {
        characterImageSrc?: string | null;
        tileAtlasImageSrc?: string | null;
        pathPreviewImageSrc?: string | null;
      });
  isBusy?: boolean;
  error?: string | null;
  onBack: () => void;
  onEdit: () => void;
  onStartTestRun: () => void;
  onPublish: () => void;
  onRegenerateTiles: () => void;
};

function isJumpHopWorkProfile(
  profile: JumpHopResultViewProps['profile'],
): profile is JumpHopWorkProfileResponse {
  return 'summary' in profile;
}

const tileToneByType: Record<string, string> = {
  accent: '#c4b5fd',
  bonus: '#fde68a',
  finish: '#86efac',
  normal: '#e0f2fe',
  start: '#bae6fd',
  target: '#fecdd3',
};

const JUMP_HOP_TAONIER_CHARACTER_IMAGE_SRC =
  '/branding/jump-hop-taonier-character.png';

function JumpHopDefaultCharacterPreview() {
  return (
    <div className="relative grid aspect-[1/1] place-items-center overflow-hidden bg-[linear-gradient(180deg,#eff6ff_0%,#fff7ed_100%)]">
      <div className="absolute inset-x-[18%] bottom-[14%] h-[14%] rounded-full bg-slate-900/12 blur-[2px]" />
      <img
        src={JUMP_HOP_TAONIER_CHARACTER_IMAGE_SRC}
        alt=""
        draggable={false}
        className="relative z-10 h-[78%] w-[78%] object-contain drop-shadow-[0_12px_18px_rgba(146,64,14,0.2)]"
        data-testid="jump-hop-result-character-logo"
      />
    </div>
  );
}

function JumpHopTilePoolPreview({
  tileAssets,
  tileAtlasAsset,
  tileAtlasFallbackSrc,
}: {
  tileAssets: JumpHopTileAsset[];
  tileAtlasAsset?: JumpHopDraftResponse['tileAtlasAsset'] | null;
  tileAtlasFallbackSrc?: string | null;
}) {
  const visibleTiles = tileAssets.slice(0, 25);
  const atlasSrc =
    tileAtlasAsset?.imageSrc?.trim() || tileAtlasFallbackSrc?.trim() || '';
  const atlasRefreshKey = tileAtlasAsset?.assetObjectId || atlasSrc;
  if (visibleTiles.length > 0) {
    return (
      <div className="grid aspect-[1/1] grid-cols-5 gap-1 bg-white/78 p-2">
        {visibleTiles.map((tile, index) => (
          <div
            key={tile.tileId ?? `${tile.sourceAtlasCell}-${index}`}
            className="grid min-h-0 place-items-center overflow-hidden rounded-[0.45rem] border border-white/80 bg-slate-50"
          >
            {tile.imageSrc ? (
              <ResolvedAssetImage
                src={tile.imageSrc}
                refreshKey={tile.assetObjectId}
                alt=""
                className="h-full w-full object-contain"
              />
            ) : (
              <span
                className="h-4 w-4 rounded-full"
                style={{
                  background:
                    tileToneByType[tile.tileType] ?? tileToneByType.normal,
                }}
              />
            )}
          </div>
        ))}
      </div>
    );
  }

  if (atlasSrc) {
    return (
      <ResolvedAssetImage
        src={atlasSrc}
        refreshKey={atlasRefreshKey}
        alt=""
        className="aspect-[1/1] w-full object-cover"
      />
    );
  }

  return (
    <div className="grid aspect-[1/1] grid-cols-5 gap-1 bg-white/78 p-2">
      {Array.from({ length: 25 }).map((_, index) => (
        <span
          key={index}
          className="rounded-[0.45rem] border border-white/80"
          style={{
            background:
              Object.values(tileToneByType)[index % Object.values(tileToneByType).length],
          }}
        />
      ))}
    </div>
  );
}

function JumpHopFirstPlatformsPreview({
  path,
  tileAssets,
}: {
  path: JumpHopPath | null | undefined;
  tileAssets: JumpHopTileAsset[];
}) {
  const platforms = (path?.platforms ?? []).slice(0, 3);

  return (
    <div className="relative aspect-[1/1] overflow-hidden bg-[linear-gradient(180deg,#f8fbff_0%,#eef8ff_100%)]">
      <div className="absolute inset-0 bg-[radial-gradient(circle_at_50%_30%,rgba(255,255,255,0.92),transparent_34%)]" />
      {platforms.map((platform, index) => {
        const asset = selectJumpHopTileAsset(
          tileAssets,
          path?.seed,
          index,
          platform.platformId,
        );
        const style = {
          left: `${50 + (index - 1) * 24}%`,
          top: `${68 - index * 22}%`,
          width: `${34 - index * 3}%`,
          zIndex: 10 + index,
        } as CSSProperties;
        return (
          <div
            key={platform.platformId || index}
            className="absolute aspect-[1.16/1] -translate-x-1/2 -translate-y-1/2"
            style={style}
          >
            <div className="absolute inset-x-[12%] bottom-[-6%] h-[22%] rounded-full bg-slate-900/14 blur-[3px]" />
            {asset?.imageSrc ? (
              <ResolvedAssetImage
                src={asset.imageSrc}
                refreshKey={asset.assetObjectId}
                alt=""
                className="relative h-full w-full object-contain"
              />
            ) : (
              <div
                className="relative h-full w-full rounded-[18%] border-2 border-white/90 shadow-[0_10px_22px_rgba(15,23,42,0.14)]"
                style={{
                  background:
                    tileToneByType[platform.tileType] ?? tileToneByType.normal,
                }}
              />
            )}
          </div>
        );
      })}
      {platforms.length === 0 ? (
        <div className="absolute inset-0 grid place-items-center text-sm font-bold text-[var(--platform-text-soft)]">
          路径
        </div>
      ) : null}
    </div>
  );
}

function JumpHopResultLeaderboard({
  profileId,
}: {
  profileId?: string | null;
}) {
  const { leaderboard, isLoading, error } = useJumpHopLeaderboard(profileId);
  const items = leaderboard?.items ?? [];

  return (
    <div className="mt-4 rounded-[1rem] border border-[var(--platform-subpanel-border)] bg-white/70 p-3">
      <div className="flex items-center justify-between gap-2">
        <div className="text-sm font-black text-[var(--platform-text-strong)]">
          排行榜
        </div>
        {isLoading ? (
          <Loader2 className="h-4 w-4 animate-spin text-[var(--platform-text-soft)]" />
        ) : null}
      </div>
      <div className="mt-3 grid gap-2">
        {items.slice(0, 5).map((entry) => (
          <div
            key={`${entry.rank}-${entry.playerId}`}
            className="grid grid-cols-[1.8rem_minmax(0,1fr)_auto_auto] items-center gap-2 rounded-[0.75rem] bg-white/70 px-2 py-2 text-xs font-bold text-[var(--platform-text-base)]"
          >
            <span className="text-[var(--platform-text-soft)]">
              {entry.rank}
            </span>
            <span className="truncate">{entry.playerId}</span>
            <span>{entry.successfulJumpCount} 跳</span>
            <span>{formatJumpHopDurationLabel(entry.durationMs)}</span>
          </div>
        ))}
        {items.length === 0 ? (
          <div className="rounded-[0.75rem] bg-white/60 px-2 py-2 text-xs font-bold text-[var(--platform-text-soft)]">
            {error ?? '暂无成绩'}
          </div>
        ) : null}
      </div>
    </div>
  );
}

export function JumpHopResultView({
  profile,
  isBusy = false,
  error = null,
  onBack,
  onEdit,
  onStartTestRun,
  onPublish,
  onRegenerateTiles,
}: JumpHopResultViewProps) {
  const [isPublishing, setIsPublishing] = useState(false);
  const isWorkProfile = isJumpHopWorkProfile(profile);
  const draft = isWorkProfile ? profile.draft : profile;
  const safeDraft = draft as JumpHopDraftResponse & {
    characterAsset: NonNullable<JumpHopDraftResponse['characterAsset']>;
    tileAtlasAsset: NonNullable<JumpHopDraftResponse['tileAtlasAsset']>;
    path: NonNullable<JumpHopDraftResponse['path']>;
  };
  const path = isWorkProfile ? profile.path : safeDraft.path;
  const tileAtlasAsset = isWorkProfile
    ? profile.tileAtlasAsset
    : safeDraft.tileAtlasAsset;
  const tileAssets = isWorkProfile ? profile.tileAssets : safeDraft.tileAssets;
  const profileId = isWorkProfile
    ? profile.summary.profileId
    : safeDraft.profileId;
  const canShowLeaderboard =
    isWorkProfile && profile.summary.publicationStatus === 'published';
  const titleSource = isWorkProfile
    ? profile.summary.workTitle
    : profile.workTitle;
  const summarySource = isWorkProfile
    ? profile.summary.workDescription
    : profile.workDescription;
  const title = titleSource?.trim() || safeDraft.workTitle.trim() || '跳一跳';
  const summary = summarySource?.trim() || safeDraft.workDescription.trim();
  const hasAssets = Boolean(
    profile.tileAtlasImageSrc?.trim() ||
      profile.pathPreviewImageSrc?.trim() ||
      tileAtlasAsset?.imageSrc?.trim() ||
      tileAssets.length > 0 ||
      path?.platforms.length,
  );

  const handlePublish = async () => {
    setIsPublishing(true);
    try {
      await Promise.resolve(onPublish());
    } finally {
      setIsPublishing(false);
    }
  };

  return (
    <div className="platform-remap-surface mx-auto flex h-full min-h-0 w-full max-w-5xl flex-col px-3 pb-3 pt-3 sm:px-4 sm:pt-4">
      <div className="mb-3 flex items-center justify-between gap-3">
        <button
          type="button"
          onClick={onBack}
          className="platform-button platform-button--ghost min-h-0 px-3 py-2 text-sm"
        >
          <ArrowLeft className="h-4 w-4" />
          返回
        </button>
        <div className="flex gap-2">
          <button
            type="button"
            onClick={onRegenerateTiles}
            disabled={isBusy}
            className="platform-button platform-button--ghost min-h-0 px-3 py-2 text-sm"
          >
            <Shuffle className="h-4 w-4" />
            地块
          </button>
        </div>
      </div>

      <div className="grid min-h-0 flex-1 gap-3 lg:grid-cols-[minmax(0,1.05fr)_minmax(0,0.95fr)]">
        <section className="platform-subpanel rounded-[1.25rem] p-4">
          <div className="text-2xl font-black text-[var(--platform-text-strong)]">
            {title}
          </div>
          {summary ? (
            <div className="mt-2 text-sm leading-6 text-[var(--platform-text-base)]">
              {summary}
            </div>
          ) : null}
          <div className="mt-4 grid gap-3 sm:grid-cols-3">
            <div className="overflow-hidden rounded-[1rem] border border-[var(--platform-subpanel-border)] bg-white/80">
              <JumpHopDefaultCharacterPreview />
            </div>
            <div className="overflow-hidden rounded-[1rem] border border-[var(--platform-subpanel-border)] bg-white/80">
              <JumpHopTilePoolPreview
                tileAssets={tileAssets}
                tileAtlasAsset={tileAtlasAsset}
                tileAtlasFallbackSrc={
                  ('tileAtlasImageSrc' in profile
                    ? profile.tileAtlasImageSrc
                    : null) ??
                  null
                }
              />
            </div>
            <div className="overflow-hidden rounded-[1rem] border border-[var(--platform-subpanel-border)] bg-white/80">
              <JumpHopFirstPlatformsPreview
                path={path}
                tileAssets={tileAssets}
              />
            </div>
          </div>
          {!hasAssets ? (
            <div className="platform-banner platform-banner--neutral mt-3 rounded-2xl text-sm leading-6">
              生成资源尚未准备完成。
            </div>
          ) : null}
        </section>

        <section className="platform-subpanel flex flex-col rounded-[1.25rem] p-4">
          <div className="text-xs font-bold tracking-[0.18em] text-[var(--platform-text-soft)]">
            结果操作
          </div>
          {canShowLeaderboard ? (
            <JumpHopResultLeaderboard profileId={profileId} />
          ) : null}
          {error ? (
            <div className="platform-banner platform-banner--danger mt-3 rounded-2xl text-sm leading-6">
              {error}
            </div>
          ) : null}
          <div className="mt-auto grid gap-2 pt-3">
            <button
              type="button"
              onClick={onEdit}
              disabled={isBusy}
              className="platform-button platform-button--ghost min-h-11 justify-center gap-2 px-4 py-3 text-sm"
            >
              <ArrowLeft className="h-4 w-4" />
              返回编辑
            </button>
            <button
              type="button"
              onClick={onStartTestRun}
              disabled={isBusy}
              className="platform-button platform-button--secondary min-h-11 justify-center gap-2 px-4 py-3 text-sm"
            >
              <Play className="h-4 w-4" />
              试玩
            </button>
            <button
              type="button"
              onClick={() => {
                void handlePublish();
              }}
              disabled={isBusy || isPublishing}
              className="platform-button platform-button--primary min-h-11 justify-center gap-2 px-4 py-3 text-sm"
            >
              {isPublishing ? (
                <Loader2 className="h-4 w-4 animate-spin" />
              ) : (
                <Send className="h-4 w-4" />
              )}
              发布
            </button>
          </div>
        </section>
      </div>
    </div>
  );
}

export default JumpHopResultView;
