import { AnimatePresence, motion } from 'motion/react';
import { useEffect, useMemo, useState } from 'react';

import { getCharacterById } from '../data/characterPresets';
import { MAX_COMPANIONS } from '../data/npcInteractions';
import { Character, CompanionState } from '../types';
import { getNineSliceStyle, UI_CHROME } from '../uiAssets';
import { PlatformActionButton } from './common/PlatformActionButton';
import { PlatformDarkModalFooter } from './common/PlatformDarkModalFooter';
import { PlatformDarkOptionCard } from './common/PlatformDarkOptionCard';
import { PlatformEmptyState } from './common/PlatformEmptyState';
import { PlatformMediaFrame } from './common/PlatformMediaFrame';
import { PlatformPillBadge } from './common/PlatformPillBadge';
import { PlatformStatusMessage } from './common/PlatformStatusMessage';
import { PlatformSubpanel } from './common/PlatformSubpanel';
import { PixelCloseButton } from './PixelCloseButton';

interface CompanionCampModalProps {
  isOpen: boolean;
  playerCharacter: Character | null;
  companions: CompanionState[];
  roster: CompanionState[];
  inBattle: boolean;
  onClose: () => void;
  onBenchCompanion: (npcId: string) => void;
  onActivateCompanion: (npcId: string, swapNpcId?: string | null) => void;
}

type CompanionCardData = {
  companion: CompanionState;
  character: Character;
};

function StatusPill({ label, value }: { label: string; value: string }) {
  return (
    <PlatformPillBadge
      tone="darkNeutral"
      size="xxs"
      className="font-normal text-zinc-300"
    >
      {label} {value}
    </PlatformPillBadge>
  );
}

function buildCampMoments(
  playerCharacter: Character | null,
  activeCompanions: CompanionCardData[],
  reserveCompanions: CompanionCardData[],
) {
  if (!playerCharacter) {
    return ['营地尚未准备完毕。'];
  }

  const moments: string[] = [];
  if (activeCompanions.length === 0 && reserveCompanions.length === 0) {
    moments.push(`${playerCharacter.name}独自坐在营火旁，暂时还没有固定同行者。`);
  }

  if (activeCompanions.length >= 2) {
    const firstCompanion = activeCompanions[0];
    const secondCompanion = activeCompanions[1];
    if (firstCompanion && secondCompanion) {
      moments.push(`${firstCompanion.character.name}和${secondCompanion.character.name}正低声商量下一段路怎么走。`);
    }
  }

  const trustedCompanion = activeCompanions.find(item => item.companion.joinedAtAffinity >= 70);
  if (trustedCompanion) {
    moments.push(`${trustedCompanion.character.name}熟练地清点补给，看起来已经像能交托后背的同伴了。`);
  }

  if (reserveCompanions.length > 0) {
    const reserveCompanion = reserveCompanions[0];
    if (reserveCompanion) {
      moments.push(`${reserveCompanion.character.name}正在营地里待命，随时都能重新归队。`);
    }
  }

  if (moments.length === 0) {
    moments.push(`${playerCharacter.name}环视营地，确认众人都已经各就各位。`);
  }

  return moments.slice(0, 3);
}

export function CompanionCampModal({
  isOpen,
  playerCharacter,
  companions,
  roster,
  inBattle,
  onClose,
  onBenchCompanion,
  onActivateCompanion,
}: CompanionCampModalProps) {
  const [selectedSwapNpcId, setSelectedSwapNpcId] = useState<string | null>(null);

  const activeCompanionCards = useMemo<CompanionCardData[]>(
    () => companions
      .map(companion => {
        const character = getCharacterById(companion.characterId);
        return character ? { companion, character } : null;
      })
      .filter(Boolean) as CompanionCardData[],
    [companions],
  );

  const reserveCompanionCards = useMemo<CompanionCardData[]>(
    () => roster
      .map(companion => {
        const character = getCharacterById(companion.characterId);
        return character ? { companion, character } : null;
      })
      .filter(Boolean) as CompanionCardData[],
    [roster],
  );

  const campMoments = useMemo(
    () => buildCampMoments(playerCharacter, activeCompanionCards, reserveCompanionCards),
    [activeCompanionCards, playerCharacter, reserveCompanionCards],
  );

  useEffect(() => {
    if (!isOpen) return;
    if (companions.length >= MAX_COMPANIONS) {
      setSelectedSwapNpcId(companions[0]?.npcId ?? null);
      return;
    }
    setSelectedSwapNpcId(null);
  }, [companions, isOpen]);

  return (
    <AnimatePresence>
      {isOpen && (
        <motion.div
          initial={{ opacity: 0 }}
          animate={{ opacity: 1 }}
          exit={{ opacity: 0 }}
          className="fixed inset-0 z-[72] flex items-center justify-center bg-black/72 p-4 backdrop-blur-sm"
          onClick={onClose}
        >
          <motion.div
            initial={{ opacity: 0, scale: 0.96, y: 8 }}
            animate={{ opacity: 1, scale: 1, y: 0 }}
            exit={{ opacity: 0, scale: 0.96, y: 8 }}
            transition={{ duration: 0.18, ease: 'easeOut' }}
            className="pixel-nine-slice pixel-modal-shell flex max-h-[min(92vh,58rem)] w-full max-w-5xl flex-col overflow-hidden shadow-[0_24px_80px_rgba(0,0,0,0.55)]"
            style={getNineSliceStyle(UI_CHROME.modalPanel)}
            onClick={event => event.stopPropagation()}
          >
            <div className="relative border-b border-white/10 px-4 py-3 sm:px-5 sm:py-4">
              <div className="min-w-0 pr-10">
                <div className="text-sm font-semibold text-white">营地编组</div>
                <div className="mt-1 text-[11px] tracking-[0.18em] text-zinc-500">
                  {playerCharacter ? `${playerCharacter.name} / 出战 ${companions.length}/${MAX_COMPANIONS}` : '队伍调度'}
                </div>
              </div>
              <PixelCloseButton onClick={onClose} label="关闭营地编组" />
            </div>

            <div className="grid min-h-0 flex-1 gap-4 overflow-y-auto p-5 lg:grid-cols-[1.05fr_0.95fr] lg:overflow-hidden">
              <PlatformSubpanel
                as="section"
                surface="dark"
                radius="sm"
                padding="md"
                className="lg:min-h-0 lg:overflow-y-auto"
              >
                <div className="mb-3 flex items-center justify-between gap-3">
                  <div>
                    <div className="text-xs font-bold text-white">当前队伍</div>
                    <div className="mt-1 text-xs text-zinc-400">
                      可直接把同行者转入后备，或先选定替换位，再让后备成员归队。
                    </div>
                  </div>
                  <StatusPill label="出战" value={`${companions.length}/${MAX_COMPANIONS}`} />
                </div>
                {inBattle && (
                  <PlatformStatusMessage
                    tone="warning"
                    surface="editorDark"
                    size="xs"
                    className="mb-3"
                  >
                    战斗中无法调整编组。
                  </PlatformStatusMessage>
                )}

                <div className="space-y-3">
                  {activeCompanionCards.length > 0 ? activeCompanionCards.map(({ companion, character }) => {
                    const selectedForSwap = selectedSwapNpcId === companion.npcId;
                    return (
                      <PlatformSubpanel
                        as="div"
                        key={companion.npcId}
                        data-testid={`active-companion-card-${companion.npcId}`}
                        surface={selectedForSwap ? 'darkSky' : 'dark'}
                        radius="xs"
                        padding="md"
                      >
                        <div className="flex items-center gap-3">
                          <PlatformMediaFrame
                            src={character.portrait}
                            alt={character.name}
                            fallbackLabel={character.name}
                            aspect="square"
                            surface="editorDark"
                            className="h-16 w-16 shrink-0 rounded-xl"
                            imageClassName="h-full w-full scale-125 object-contain"
                            imageProps={{ style: { imageRendering: 'pixelated' } }}
                          />
                          <div className="min-w-0 flex-1">
                            <div className="text-sm font-semibold text-white">{character.name}</div>
                            <div className="text-[10px] tracking-[0.18em] text-zinc-500">{character.title}</div>
                            <div className="mt-2 flex flex-wrap gap-2">
                              <StatusPill label="生命" value={`${companion.hp}/${companion.maxHp}`} />
                              <StatusPill label="灵力" value={`${companion.mana}/${companion.maxMana}`} />
                              <StatusPill label="好感" value={`${companion.joinedAtAffinity}`} />
                            </div>
                          </div>
                        </div>
                        <div className="mt-3 flex flex-wrap gap-2">
                          <PlatformDarkOptionCard
                            disabled={inBattle}
                            onClick={() => setSelectedSwapNpcId(companion.npcId)}
                            selected={selectedForSwap}
                            tone="sky"
                            radius="sm"
                            padding="sm"
                            className="text-xs"
                          >
                            设为替换位
                          </PlatformDarkOptionCard>
                          <PlatformActionButton
                            surface="editorDark"
                            tone="secondary"
                            size="xs"
                            disabled={inBattle}
                            onClick={() => onBenchCompanion(companion.npcId)}
                          >
                            转入后备
                          </PlatformActionButton>
                        </div>
                      </PlatformSubpanel>
                    );
                  }) : (
                    <PlatformEmptyState
                      surface="editorDark"
                      size="inline"
                      className="rounded-xl py-6 font-normal text-zinc-400"
                    >
                      当前没有已出战的同行者。
                    </PlatformEmptyState>
                  )}
                </div>
              </PlatformSubpanel>

              <PlatformSubpanel
                as="section"
                surface="dark"
                radius="sm"
                padding="md"
                className="lg:min-h-0 lg:overflow-y-auto"
              >
                <div className="mb-3 flex items-center justify-between gap-3">
                  <div>
                    <div className="text-xs font-bold text-white">后备队伍</div>
                    <div className="mt-1 text-xs text-zinc-400">
                      后备同行者会在营地待命，随时可以重新召回。
                    </div>
                  </div>
                  <StatusPill label="后备" value={`${reserveCompanionCards.length}`} />
                </div>

                <div className="space-y-3">
                  {reserveCompanionCards.length > 0 ? reserveCompanionCards.map(({ companion, character }) => {
                    const needsSwap = companions.length >= MAX_COMPANIONS;
                    return (
                      <PlatformSubpanel
                        as="div"
                        key={companion.npcId}
                        data-testid={`reserve-companion-card-${companion.npcId}`}
                        surface="dark"
                        radius="xs"
                        padding="md"
                      >
                        <div className="flex items-center gap-3">
                          <PlatformMediaFrame
                            src={character.portrait}
                            alt={character.name}
                            fallbackLabel={character.name}
                            aspect="square"
                            surface="editorDark"
                            className="h-16 w-16 shrink-0 rounded-xl"
                            imageClassName="h-full w-full scale-125 object-contain"
                            imageProps={{ style: { imageRendering: 'pixelated' } }}
                          />
                          <div className="min-w-0 flex-1">
                            <div className="text-sm font-semibold text-white">{character.name}</div>
                            <div className="text-[10px] tracking-[0.18em] text-zinc-500">{character.title}</div>
                            <div className="mt-2 flex flex-wrap gap-2">
                              <StatusPill label="生命" value={`${companion.hp}/${companion.maxHp}`} />
                              <StatusPill label="灵力" value={`${companion.mana}/${companion.maxMana}`} />
                              <StatusPill label="好感" value={`${companion.joinedAtAffinity}`} />
                            </div>
                          </div>
                        </div>
                        <PlatformActionButton
                          surface="editorDark"
                          tone={inBattle || (needsSwap && !selectedSwapNpcId) ? 'ghost' : 'success'}
                          size="xs"
                          fullWidth
                          disabled={inBattle || (needsSwap && !selectedSwapNpcId)}
                          onClick={() => onActivateCompanion(companion.npcId, needsSwap ? selectedSwapNpcId : null)}
                          className="mt-3"
                        >
                          {needsSwap ? '换入队伍' : '编入队伍'}
                        </PlatformActionButton>
                      </PlatformSubpanel>
                    );
                  }) : (
                    <PlatformEmptyState
                      surface="editorDark"
                      size="inline"
                      className="rounded-xl py-6 font-normal text-zinc-400"
                    >
                      当前还没有后备同行者。
                    </PlatformEmptyState>
                  )}
                </div>
              </PlatformSubpanel>
            </div>

            <PlatformDarkModalFooter layout="content" padding="roomy">
              <div className="mb-3 text-xs font-bold text-white">营地气氛</div>
              <div className="grid gap-3 md:grid-cols-3">
                {campMoments.map((moment, index) => (
                  <PlatformSubpanel
                    as="div"
                    key={`camp-moment-${index}-${moment}`}
                    surface="dark"
                    radius="xs"
                    padding="md"
                    className="text-sm leading-relaxed text-zinc-300"
                  >
                    {moment}
                  </PlatformSubpanel>
                ))}
              </div>
            </PlatformDarkModalFooter>
          </motion.div>
        </motion.div>
      )}
    </AnimatePresence>
  );
}
