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 { PixelCloseButton } from './PixelCloseButton';
import { ResolvedAssetImage } from './ResolvedAssetImage';

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 (
    <div className="rounded-full border border-white/10 bg-black/20 px-2 py-1 text-[10px] text-zinc-300">
      {label} {value}
    </div>
  );
}

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">
              <section className="rounded-2xl border border-white/10 bg-black/18 p-4 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 && (
                  <div className="mb-3 rounded-xl border border-amber-400/20 bg-amber-500/10 px-3 py-2 text-xs text-amber-100">
                    战斗中无法调整编组。
                  </div>
                )}

                <div className="space-y-3">
                  {activeCompanionCards.length > 0 ? activeCompanionCards.map(({ companion, character }) => {
                    const selectedForSwap = selectedSwapNpcId === companion.npcId;
                    return (
                      <div
                        key={companion.npcId}
                        className={`rounded-xl border px-3 py-3 ${selectedForSwap ? 'border-sky-400/40 bg-sky-500/10' : 'border-white/8 bg-black/20'}`}
                      >
                        <div className="flex items-center gap-3">
                          <div className="flex h-16 w-16 shrink-0 items-center justify-center overflow-hidden rounded-xl border border-white/10 bg-black/25">
                            <ResolvedAssetImage
                              src={character.portrait}
                              alt={character.name}
                              className="h-full w-full scale-125 object-contain"
                              style={{ imageRendering: 'pixelated' }}
                            />
                          </div>
                          <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">
                          <button
                            type="button"
                            disabled={inBattle}
                            onClick={() => setSelectedSwapNpcId(companion.npcId)}
                            className={`rounded-lg border px-3 py-2 text-xs ${selectedForSwap ? 'border-sky-400/30 bg-sky-500/15 text-sky-100' : 'border-white/10 bg-white/5 text-zinc-200'} ${inBattle ? 'opacity-50' : ''}`}
                          >
                            设为替换位
                          </button>
                          <button
                            type="button"
                            disabled={inBattle}
                            onClick={() => onBenchCompanion(companion.npcId)}
                            className={`rounded-lg border border-white/10 bg-white/5 px-3 py-2 text-xs text-zinc-200 ${inBattle ? 'opacity-50' : ''}`}
                          >
                            转入后备
                          </button>
                        </div>
                      </div>
                    );
                  }) : (
                    <div className="rounded-xl border border-dashed border-white/10 bg-black/20 px-4 py-6 text-sm text-zinc-400">
                      当前没有已出战的同行者。
                    </div>
                  )}
                </div>
              </section>

              <section className="rounded-2xl border border-white/10 bg-black/18 p-4 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 (
                      <div key={companion.npcId} className="rounded-xl border border-white/8 bg-black/20 px-3 py-3">
                        <div className="flex items-center gap-3">
                          <div className="flex h-16 w-16 shrink-0 items-center justify-center overflow-hidden rounded-xl border border-white/10 bg-black/25">
                            <ResolvedAssetImage
                              src={character.portrait}
                              alt={character.name}
                              className="h-full w-full scale-125 object-contain"
                              style={{ imageRendering: 'pixelated' }}
                            />
                          </div>
                          <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>
                        <button
                          type="button"
                          disabled={inBattle || (needsSwap && !selectedSwapNpcId)}
                          onClick={() => onActivateCompanion(companion.npcId, needsSwap ? selectedSwapNpcId : null)}
                          className={`mt-3 w-full rounded-lg border px-3 py-2 text-xs ${
                            inBattle || (needsSwap && !selectedSwapNpcId)
                              ? 'border-white/6 bg-black/20 text-zinc-500'
                              : 'border-emerald-400/20 bg-emerald-500/10 text-emerald-100'
                          }`}
                        >
                          {needsSwap ? '换入队伍' : '编入队伍'}
                        </button>
                      </div>
                    );
                  }) : (
                    <div className="rounded-xl border border-dashed border-white/10 bg-black/20 px-4 py-6 text-sm text-zinc-400">
                      当前还没有后备同行者。
                    </div>
                  )}
                </div>
              </section>
            </div>

            <div className="border-t border-white/10 px-5 py-4">
              <div className="mb-3 text-xs font-bold text-white">营地气氛</div>
              <div className="grid gap-3 md:grid-cols-3">
                {campMoments.map((moment, index) => (
                  <div
                    key={`camp-moment-${index}-${moment}`}
                    className="rounded-xl border border-white/8 bg-black/18 px-4 py-3 text-sm leading-relaxed text-zinc-300"
                  >
                    {moment}
                  </div>
                ))}
              </div>
            </div>
          </motion.div>
        </motion.div>
      )}
    </AnimatePresence>
  );
}
