import {useCallback, useEffect, useMemo, useRef, useState} from 'react';

import {
  buildCustomWorldPlayableCharacters,
  PRESET_CHARACTERS,
} from '../../data/characterPresets';
import {AnimationState, type Character, type CustomWorldProfile, WorldType} from '../../types';
import {getNineSliceStyle, UI_CHROME} from '../../uiAssets';
import {CharacterAnimator} from '../CharacterAnimator';
import {CharacterDetailModal} from '../CharacterDetailModal';
import {CharacterDraftModal} from '../SelectionCustomizationModals';

type CharacterSelectionDraft = {
  name: string;
  backstory: string;
};

type CarouselOrientation = 'horizontal' | 'vertical';

type CharacterSelectionFlowProps = {
  worldType: WorldType;
  customWorldProfile: CustomWorldProfile | null;
  onBack: () => void;
  onConfirm: (character: Character) => void;
};

const CHARACTER_DISPLAY: Record<string, {name: string; title: string; role: string; tags: string[]}> = {
  'sword-princess': {name: '剑姬', title: '皇家之刃', role: '先锋', tags: ['剑术', '压制', '突进']},
  'archer-hero': {name: '弓手英雄', title: '风之射手', role: '远程', tags: ['射程', '齐射', '风筝']},
  'girl-hero': {name: '双刃刺客', title: '暗影之牙', role: '刺客', tags: ['连击', '冲锋', '机动']},
  'punch-hero': {name: '战拳', title: '近战大师', role: '战士', tags: ['爆发', '格斗', '仇恨']},
  'fighter-4': {name: '装甲长矛手', title: '重装先锋', role: '前线', tags: ['守护', '稳定', '突破']},
};

const ATTRIBUTE_LABELS: Record<keyof Character['attributes'], string> = {
  strength: '力量',
  agility: '敏捷',
  intelligence: '智力',
  spirit: '精神',
};

function getGenderLabel(gender: Character['gender']) {
  if (gender === 'female') return '女性';
  if (gender === 'male') return '男性';
  return '未知';
}

function clampIndex(value: number, length: number) {
  if (length <= 0) return 0;
  return Math.max(0, Math.min(length - 1, value));
}

function getCharacterMeta(
  character: Character,
  overrides: Partial<Pick<Character, 'name' | 'title'>> = {},
) {
  const preset = CHARACTER_DISPLAY[character.id];
  return {
    name: overrides.name ?? character.name ?? preset?.name,
    title: overrides.title ?? character.title ?? preset?.title,
    role: preset?.role ?? '角色',
    tags: preset?.tags ?? [],
  };
}

function applyCharacterSelectionDraft(
  character: Character | null,
  draft?: CharacterSelectionDraft | null,
) {
  if (!character || !draft) return character;
  return {
    ...character,
    name: draft.name,
    backstory: draft.backstory,
  } satisfies Character;
}

function getPersonalityTags(personality: string) {
  const tags = personality
    .split(/[,.!?/\\\s]+/u)
    .map(tag => tag.trim())
    .filter(Boolean);

  return tags.length > 0 ? [...new Set(tags)] : [personality.trim()].filter(Boolean);
}

function readCarouselProgress(container: HTMLDivElement, orientation: CarouselOrientation) {
  const firstCard = container.querySelector<HTMLElement>('[data-carousel-card="true"]');
  if (!firstCard) return 0;

  const styles = window.getComputedStyle(container);
  const gap = parseFloat(
    orientation === 'vertical'
      ? styles.rowGap || styles.gap || '0'
      : styles.columnGap || styles.gap || '0',
  );
  const stride = orientation === 'vertical'
    ? firstCard.getBoundingClientRect().height + gap
    : firstCard.getBoundingClientRect().width + gap;

  if (stride <= 0) return 0;
  return orientation === 'vertical' ? container.scrollTop / stride : container.scrollLeft / stride;
}

function scrollCarouselToIndex(container: HTMLDivElement | null, index: number, orientation: CarouselOrientation) {
  if (!container) return;
  const firstCard = container.querySelector<HTMLElement>('[data-carousel-card="true"]');
  if (!firstCard) return;

  const styles = window.getComputedStyle(container);
  const gap = parseFloat(
    orientation === 'vertical'
      ? styles.rowGap || styles.gap || '0'
      : styles.columnGap || styles.gap || '0',
  );
  const stride = orientation === 'vertical'
    ? firstCard.getBoundingClientRect().height + gap
    : firstCard.getBoundingClientRect().width + gap;

  const behavior: ScrollBehavior = 'smooth';
  if (orientation === 'vertical') {
    container.scrollTo({top: stride * index, behavior});
  } else {
    container.scrollTo({left: stride * index, behavior});
  }
}

function getCharacterCardStyle(index: number, progress: number) {
  const delta = index - progress;
  const distance = Math.min(Math.abs(delta), 2.4);

  if (distance < 0.08) {
    return {
      opacity: 1,
      zIndex: 30,
      transform: 'none',
      filter: 'none',
      willChange: 'auto' as const,
    };
  }

  const scale = 1 - distance * 0.12;
  const opacity = 1 - distance * 0.28;
  const rotate = delta * 8;
  const translateY = distance * 12;
  const translateX = delta * -12;

  return {
    opacity,
    zIndex: 30 - Math.round(distance * 10),
    transform: `translate3d(${translateX}px, ${translateY}px, 0) scale(${scale}) rotate(${rotate}deg)`,
    filter: distance < 0.08 ? 'none' : `saturate(${1 - distance * 0.08})`,
  };
}

export function CharacterSelectionFlow({
  worldType,
  customWorldProfile,
  onBack,
  onConfirm,
}: CharacterSelectionFlowProps) {
  const selectionCharacters = useMemo(
    () => (customWorldProfile ? buildCustomWorldPlayableCharacters(customWorldProfile) : PRESET_CHARACTERS),
    [customWorldProfile],
  );
  const [selectedCharacterId, setSelectedCharacterId] = useState(selectionCharacters[0]?.id ?? '');
  const [detailCharacter, setDetailCharacter] = useState<Character | null>(null);
  const characterCarouselRef = useRef<HTMLDivElement | null>(null);
  const [characterCarouselProgress, setCharacterCarouselProgress] = useState(0);
  const [showCharacterDraftModal, setShowCharacterDraftModal] = useState(false);
  const [characterDraftName, setCharacterDraftName] = useState('');
  const [characterDraftBackstory, setCharacterDraftBackstory] = useState('');
  const [characterDraftError, setCharacterDraftError] = useState<string | null>(null);
  const [characterSelectionDrafts, setCharacterSelectionDrafts] = useState<Record<string, CharacterSelectionDraft>>({});

  const selectedCharacter = useMemo(
    () => selectionCharacters.find(character => character.id === selectedCharacterId) ?? selectionCharacters[0] ?? null,
    [selectedCharacterId, selectionCharacters],
  );
  const selectedCharacterDraft = selectedCharacter ? characterSelectionDrafts[selectedCharacter.id] ?? null : null;
  const selectedCharacterPreview = useMemo(
    () => applyCharacterSelectionDraft(selectedCharacter, selectedCharacterDraft),
    [selectedCharacter, selectedCharacterDraft],
  );
  const selectedCharacterMeta = selectedCharacter
    ? getCharacterMeta(selectedCharacter, {name: selectedCharacterDraft?.name})
    : null;
  const selectedCharacterPersonalityTags = useMemo(
    () => (selectedCharacterPreview ? getPersonalityTags(selectedCharacterPreview.personality) : []),
    [selectedCharacterPreview],
  );
  const focusedCharacterIndex = clampIndex(Math.round(characterCarouselProgress), selectionCharacters.length);

  const syncCharacterCarousel = useCallback(() => {
    if (!characterCarouselRef.current) return;
    setCharacterCarouselProgress(readCarouselProgress(characterCarouselRef.current, 'horizontal'));
  }, []);

  useEffect(() => {
    syncCharacterCarousel();
    window.addEventListener('resize', syncCharacterCarousel);
    return () => window.removeEventListener('resize', syncCharacterCarousel);
  }, [syncCharacterCarousel]);

  useEffect(() => {
    const focusedCharacter = selectionCharacters[focusedCharacterIndex];
    if (focusedCharacter && focusedCharacter.id !== selectedCharacterId) {
      setSelectedCharacterId(focusedCharacter.id);
    }
  }, [focusedCharacterIndex, selectedCharacterId, selectionCharacters]);

  useEffect(() => {
    if (selectionCharacters.length === 0) return;
    if (!selectionCharacters.some(character => character.id === selectedCharacterId)) {
      const firstCharacter = selectionCharacters[0];
      if (firstCharacter) {
        setSelectedCharacterId(firstCharacter.id);
      }
    }
  }, [selectedCharacterId, selectionCharacters]);

  const openCharacterDraftEditor = () => {
    if (!selectedCharacterPreview) return;
    setCharacterDraftName(selectedCharacterPreview.name);
    setCharacterDraftBackstory(selectedCharacterPreview.backstory);
    setCharacterDraftError(null);
    setShowCharacterDraftModal(true);
  };

  const saveCharacterDraft = () => {
    if (!selectedCharacter) return;

    const nextName = characterDraftName.trim();
    const nextBackstory = characterDraftBackstory.trim();
    if (!nextName) {
      setCharacterDraftError('请输入角色名称。');
      return;
    }
    if (!nextBackstory) {
      setCharacterDraftError('请输入角色背景故事。');
      return;
    }

    setCharacterSelectionDrafts(current => ({
      ...current,
      [selectedCharacter.id]: {
        name: nextName,
        backstory: nextBackstory,
      },
    }));
    setCharacterDraftError(null);
    setShowCharacterDraftModal(false);
  };

  if (!selectedCharacter || !selectedCharacterMeta) {
    return null;
  }

  return (
    <>
      <div className="flex h-full min-h-0 flex-col">
        <div className="mb-3 flex justify-start">
          <button
            type="button"
            onClick={onBack}
            className="rounded-full border border-white/10 bg-black/18 px-3 py-1.5 text-[11px] text-zinc-300 transition-colors hover:text-white"
          >
            返回
          </button>
        </div>
        <div className="mb-4 text-center">
          <div className="text-2xl font-black text-white sm:text-[2rem]">选择你的角色</div>
          <div className="mt-1 text-[11px] tracking-[0.14em] text-zinc-500">左右滑动浏览角色</div>
        </div>

        <div
          ref={characterCarouselRef}
          onScroll={syncCharacterCarousel}
          className="character-carousel scrollbar-hide flex-[1_1_auto]"
        >
          {selectionCharacters.map((character, index) => {
            const characterDraft = characterSelectionDrafts[character.id];
            const meta = getCharacterMeta(character, {name: characterDraft?.name});
            const selected = character.id === selectedCharacter.id;

            return (
              <button
                key={character.id}
                type="button"
                onClick={() => {
                  setSelectedCharacterId(character.id);
                  scrollCarouselToIndex(characterCarouselRef.current, index, 'horizontal');
                }}
                data-carousel-card="true"
                className={`character-carousel__card ${selected ? 'character-carousel__card--active' : ''}`}
                style={getCharacterCardStyle(index, characterCarouselProgress)}
              >
                <span className={`character-carousel__surface ${selected ? 'character-carousel__surface--active' : ''}`}>
                  <span className="character-carousel__cover">
                    {selected ? (
                      <CharacterAnimator
                        state={AnimationState.RUN}
                        character={character}
                        className="character-carousel__portrait character-carousel__portrait--animated"
                      />
                    ) : (
                      <img src={character.portrait} alt={meta.name} className="character-carousel__portrait" style={{imageRendering: 'pixelated'}} />
                    )}
                  </span>
                  {selected ? (
                    <>
                      <span className="character-carousel__selected-name">{meta.name}</span>
                      <span className="character-carousel__meta character-carousel__meta--selected">
                        <span className="character-carousel__title character-carousel__title--selected">{meta.title}</span>
                      </span>
                    </>
                  ) : (
                    <span className="character-carousel__meta">
                      <span className="character-carousel__name">{meta.name}</span>
                      <span className="character-carousel__title">{meta.title}</span>
                    </span>
                  )}
                </span>
              </button>
            );
          })}
        </div>

        <div className="mt-3 grid gap-2 md:grid-cols-[0.85fr_1.15fr]">
          <div className="pixel-nine-slice pixel-panel" style={getNineSliceStyle(UI_CHROME.statsPanel, {paddingX: 12, paddingY: 10})}>
            <div className="mb-2 flex items-center justify-between gap-3">
              <div className="text-xs font-bold text-white">角色属性</div>
              <div className="flex items-center gap-2 text-[10px] text-zinc-500">
                <span>{selectedCharacterMeta.title}</span>
                <span className="rounded-full border border-white/10 bg-black/20 px-2 py-0.5 text-[9px] text-zinc-200">
                  性别: {getGenderLabel(selectedCharacter.gender)}
                </span>
              </div>
            </div>
            <div className="grid grid-cols-4 gap-1 text-[11px] text-zinc-300 sm:gap-1.5 sm:text-[13px]">
              {Object.entries(selectedCharacter.attributes).map(([key, value]) => (
                <div key={key} className="rounded-lg border border-white/6 bg-black/20 px-2 py-1.5 text-center sm:px-2.5">
                  {ATTRIBUTE_LABELS[key as keyof Character['attributes']]}: {value}
                </div>
              ))}
            </div>
          </div>

          <div
            className="pixel-nine-slice pixel-panel character-backstory-panel flex flex-col"
            style={getNineSliceStyle(UI_CHROME.panel, {paddingX: 12, paddingY: 10})}
          >
            <div className="mb-2 flex items-start justify-between gap-3">
              <div className="character-backstory-title text-xs font-bold text-white">背景故事</div>
              <button
                type="button"
                onClick={openCharacterDraftEditor}
                className="rounded-full border border-sky-300/20 bg-sky-500/10 px-3 py-1 text-[10px] text-sky-100 transition-colors hover:text-white"
              >
                自定义
              </button>
            </div>
            <div className="flex flex-1 flex-col text-[13px] leading-6 text-zinc-300">
              <div>{selectedCharacterPreview?.backstory ?? selectedCharacter.backstory}</div>
              <div className="mt-auto flex items-end justify-between gap-3 pt-3">
                <div className="min-w-0 flex flex-wrap gap-1.5">
                  {selectedCharacterPersonalityTags.map(tag => (
                    <span key={tag} className="rounded-full border border-white/10 bg-black/20 px-2 py-0.5 text-[10px] text-zinc-300">
                      {tag}
                    </span>
                  ))}
                </div>
                <button
                  type="button"
                  onClick={() => setDetailCharacter(selectedCharacterPreview)}
                  aria-label={`查看${selectedCharacterPreview?.name ?? selectedCharacter.name}的详情`}
                  className="shrink-0 text-[11px] font-medium text-sky-200 transition-colors hover:text-white"
                >
                  详情
                </button>
              </div>
            </div>
          </div>
        </div>

        <div className="mt-3">
          <button
            type="button"
            onClick={() => onConfirm(selectedCharacterPreview ?? selectedCharacter)}
            className="pixel-nine-slice pixel-pressable mx-auto block w-full max-w-[16rem] text-left"
            style={getNineSliceStyle(UI_CHROME.choiceButton, {paddingX: 14, paddingY: 9})}
          >
            <div className="flex items-center justify-between gap-4">
              <span className="text-sm font-semibold text-white">进入营地</span>
              <span className="text-white/60">开始</span>
            </div>
          </button>
        </div>
      </div>

      <CharacterDetailModal
        character={detailCharacter}
        worldType={worldType}
        customWorldProfile={customWorldProfile}
        subtitle="角色详情"
        onClose={() => setDetailCharacter(null)}
      />
      <CharacterDraftModal
        isOpen={showCharacterDraftModal}
        characterLabel={selectedCharacterMeta ? `${selectedCharacterMeta.name} / ${selectedCharacterMeta.title}` : '当前角色'}
        draftName={characterDraftName}
        draftBackstory={characterDraftBackstory}
        onNameChange={value => {
          setCharacterDraftName(value);
          if (characterDraftError) setCharacterDraftError(null);
        }}
        onBackstoryChange={value => {
          setCharacterDraftBackstory(value);
          if (characterDraftError) setCharacterDraftError(null);
        }}
        onClose={() => setShowCharacterDraftModal(false)}
        onConfirm={saveCharacterDraft}
        error={characterDraftError}
      />
    </>
  );
}
