import React, { useState, useEffect, useRef } from 'react';
import { Eye, Sword, Shield, Zap, Loader } from 'lucide-react';
import { getTypeColor } from '../utils/pokemon';
import { enhancedAlgoliaService } from '../services/algolia-enhanced';
import { algoliasearch } from 'algoliasearch';
import { useGSAPAnimations } from '../hooks/useGSAPAnimations';
import type { PokemonData, MoveData } from '../types/pokemon';
interface PokemonAnalysisProps {
pokemon: PokemonData;
}
const PokemonAnalysis: React.FC<PokemonAnalysisProps> = ({ pokemon }) => {
const [strongAgainst, setStrongAgainst] = useState<PokemonData[]>([]);
const [weakAgainst, setWeakAgainst] = useState<PokemonData[]>([]);
const [counterMoves, setCounterMoves] = useState<MoveData[]>([]);
const [loading, setLoading] = useState(true);
const statBarRefs = useRef<HTMLDivElement[]>([]);
const loadingSpinnerRef = useRef<HTMLDivElement>(null);
const { animateStatBars, createLoadingAnimation } = useGSAPAnimations();
useEffect(() => {
const loadBattleData = async () => {
setLoading(true);
try {
// Get Pokemon that this Pokemon is strong against
if (pokemon.types && pokemon.types.length > 0) {
// Use direct Algolia search to find Pokemon weak to this Pokemon's types
const appId = import.meta.env.VITE_ALGOLIA_APP_ID || 'demo_app_id';
const apiKey = import.meta.env.VITE_ALGOLIA_API_KEY || 'demo_api_key';
const client = algoliasearch(appId, apiKey);
const weaknessFilters = pokemon.types.map(type => `typeEffectiveness.weakTo:"${type}"`).join(' OR ');
console.log('Searching for Pokemon weak to:', pokemon.types, 'Filter:', weaknessFilters);
const strongResults = await client.searchSingleIndex({
indexName: 'pokemon',
searchParams: {
query: '',
filters: `(${weaknessFilters})`,
hitsPerPage: 4
}
});
console.log('Strong against results:', strongResults.hits);
setStrongAgainst(strongResults.hits as PokemonData[]);
}
// Get Pokemon that counter this Pokemon (weak against)
const weakAgainstQuery = `what counters ${pokemon.name}`;
const weakResults = await enhancedAlgoliaService.processBattleQuery(weakAgainstQuery);
setWeakAgainst(weakResults.recommendations.slice(0, 4).map(rec => ({
name: rec.pokemon,
types: rec.types,
stats: rec.stats,
abilities: rec.abilities,
competitiveTier: rec.tier,
battleRole: rec.battleRole
} as PokemonData)));
// Get counter moves (moves that are effective against this Pokemon's types)
setCounterMoves(weakResults.moves.slice(0, 4));
} catch (error) {
console.error('Error loading battle data:', error);
} finally {
setLoading(false);
}
};
loadBattleData();
}, [pokemon]);
// Animate stat bars when data loads
useEffect(() => {
if (!loading && statBarRefs.current.length > 0) {
const maxStat = 255; // Max base stat for Pokemon
const statData = [
{ ref: statBarRefs.current[0], value: pokemon.stats.hp, max: maxStat },
{ ref: statBarRefs.current[1], value: pokemon.stats.attack, max: maxStat },
{ ref: statBarRefs.current[2], value: pokemon.stats.defense, max: maxStat },
{ ref: statBarRefs.current[3], value: pokemon.stats.specialAttack, max: maxStat },
{ ref: statBarRefs.current[4], value: pokemon.stats.specialDefense, max: maxStat },
{ ref: statBarRefs.current[5], value: pokemon.stats.speed, max: maxStat }
].filter(stat => stat.ref); // Filter out undefined refs
animateStatBars(statData);
}
}, [loading, pokemon.stats, animateStatBars]);
// Create loading animation
useEffect(() => {
let loadingAnimation: gsap.core.Tween | undefined;
if (loading && loadingSpinnerRef.current) {
loadingAnimation = createLoadingAnimation(loadingSpinnerRef.current);
}
return () => {
if (loadingAnimation) {
loadingAnimation.kill();
}
};
}, [loading, createLoadingAnimation]);
return (
<div className="space-y-8">
{/* Main Pokemon Info */}
<div className="bg-white/10 backdrop-blur-lg rounded-2xl p-8 border border-white/20">
<h2 className="text-3xl font-bold mb-6 flex items-center justify-between">
<div className="flex items-center">
<Eye className="mr-3" />
Analyzing: {pokemon.name}
</div>
{pokemon.image && (
<div className="pokemon-image-container transform-gpu will-change-transform">
<img
src={pokemon.image}
alt={pokemon.name}
className="w-32 h-32 object-contain rounded-lg shadow-2xl transform-gpu will-change-transform hover:scale-110 transition-transform duration-300"
/>
</div>
)}
</h2>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
<div>
<div className="flex items-center space-x-4 mb-4">
<div className="flex space-x-2">
{pokemon.types.map((type: string) => (
<span key={type} className={`px-3 py-1 rounded-full text-white text-sm font-semibold ${getTypeColor(type)}`}>
{type}
</span>
))}
</div>
<span className="bg-purple-600 px-3 py-1 rounded-full text-sm font-semibold">
{pokemon.competitiveTier || 'Untiered'}
</span>
</div>
<div className="space-y-3">
<div className="flex">
<span className="text-gray-300">Battle Role: </span>
{pokemon.battleRole || 'Unknown'}
</div>
<div className="flex">
<span className="text-gray-300">Base Stat Total: </span>
{pokemon.stats.total}
</div>
{pokemon.number && (
<div className="flex">
<span className="text-gray-300">Number: </span>
#{pokemon.number}
</div>
)}
</div>
{/* Key Moves Section */}
{pokemon.keyMoves && pokemon.keyMoves.length > 0 && (
<div className="mt-6">
<h4 className="font-semibold mb-3 flex items-center">
<Zap className="mr-2" size={18} />
Key Moves
</h4>
<div className="grid grid-cols-2 gap-2">
{pokemon.keyMoves.slice(0, 4).map((move: string, index: number) => (
<span key={index} className="bg-gray-700 px-3 py-1 rounded text-sm">
{move}
</span>
))}
</div>
</div>
)}
</div>
<div>
<h4 className="font-semibold mb-3">Type Effectiveness</h4>
<div className="space-y-2">
{pokemon.typeEffectiveness?.weakTo && pokemon.typeEffectiveness.weakTo.length > 0 && (
<div>
<span className="text-red-400 font-semibold">Weak to: </span>
{pokemon.typeEffectiveness.weakTo.join(', ')}
</div>
)}
{pokemon.typeEffectiveness?.resistantTo && pokemon.typeEffectiveness.resistantTo.length > 0 && (
<div>
<span className="text-green-400 font-semibold">Resists: </span>
{pokemon.typeEffectiveness.resistantTo.join(', ')}
</div>
)}
{pokemon.typeEffectiveness?.immuneTo && pokemon.typeEffectiveness.immuneTo.length > 0 && (
<div>
<span className="text-blue-400 font-semibold">Immune to: </span>
{pokemon.typeEffectiveness.immuneTo.join(', ')}
</div>
)}
</div>
{/* Animated Stats Grid */}
<div className="mt-6">
<h4 className="font-semibold mb-3">Base Stats</h4>
<div className="space-y-3 text-sm">
{[
{ name: 'HP', value: pokemon.stats.hp, color: 'bg-red-500' },
{ name: 'Attack', value: pokemon.stats.attack, color: 'bg-orange-500' },
{ name: 'Defense', value: pokemon.stats.defense, color: 'bg-yellow-500' },
{ name: 'Sp. Attack', value: pokemon.stats.specialAttack, color: 'bg-blue-500' },
{ name: 'Sp. Defense', value: pokemon.stats.specialDefense, color: 'bg-green-500' },
{ name: 'Speed', value: pokemon.stats.speed, color: 'bg-pink-500' }
].map((stat, index) => (
<div key={stat.name} className="flex items-center space-x-3">
<span className="w-20 text-right">{stat.name}:</span>
<div className="flex-1 bg-gray-700 rounded-full h-3 overflow-hidden">
<div
ref={el => {
if (el) statBarRefs.current[index] = el;
}}
className={`h-full ${stat.color} rounded-full transform-gpu will-change-transform`}
style={{ width: '0%' }}
/>
</div>
<span className="font-mono w-8 text-right">{stat.value}</span>
</div>
))}
</div>
</div>
</div>
</div>
</div>
{/* Strong Against Section */}
<div className="bg-white/10 backdrop-blur-lg rounded-2xl p-8 border border-white/20">
<h3 className="text-2xl font-bold mb-6 flex items-center text-green-400">
<Sword className="mr-3" />
Strong Against
</h3>
{loading ? (
<div className="flex items-center space-x-3 text-gray-400">
<div ref={loadingSpinnerRef} className="transform-gpu will-change-transform">
<Loader size={20} />
</div>
<span>Loading Pokemon that {pokemon.name} is strong against...</span>
</div>
) : strongAgainst.length > 0 ? (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
{strongAgainst.map((target, index) => (
<div key={index} className="bg-white/5 rounded-lg p-4 border border-green-400/20">
<h4 className="font-semibold mb-2">{target.name}</h4>
<div className="flex flex-wrap gap-1 mb-2">
{target.types?.map((type: string) => (
<span key={type} className={`px-2 py-1 rounded text-xs ${getTypeColor(type)}`}>
{type}
</span>
))}
</div>
<div className="text-sm text-gray-300">
{target.competitiveTier && (
<div>Tier: {target.competitiveTier}</div>
)}
</div>
</div>
))}
</div>
) : (
<div className="text-gray-400">No specific type advantages found.</div>
)}
</div>
{/* Weak Against Section */}
<div className="bg-white/10 backdrop-blur-lg rounded-2xl p-8 border border-white/20">
<h3 className="text-2xl font-bold mb-6 flex items-center text-red-400">
<Shield className="mr-3" />
Weak Against
</h3>
{loading ? (
<div className="flex items-center space-x-3 text-gray-400">
<div className="transform-gpu will-change-transform">
<Loader size={20} className="animate-spin" />
</div>
<span>Loading Pokemon that counter {pokemon.name}...</span>
</div>
) : weakAgainst.length > 0 ? (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
{weakAgainst.map((counter, index) => (
<div key={index} className="bg-white/5 rounded-lg p-4 border border-red-400/20">
<h4 className="font-semibold mb-2">{counter.name}</h4>
<div className="flex flex-wrap gap-1 mb-2">
{counter.types?.map((type: string) => (
<span key={type} className={`px-2 py-1 rounded text-xs ${getTypeColor(type)}`}>
{type}
</span>
))}
</div>
<div className="text-sm text-gray-300">
{counter.competitiveTier && (
<div>Tier: {counter.competitiveTier}</div>
)}
{counter.battleRole && (
<div>Role: {counter.battleRole}</div>
)}
</div>
</div>
))}
</div>
) : (
<div className="text-gray-400">No major counters found.</div>
)}
</div>
{/* Recommended Counter Moves */}
<div className="bg-white/10 backdrop-blur-lg rounded-2xl p-8 border border-white/20">
<h3 className="text-2xl font-bold mb-6 flex items-center text-yellow-400">
<Zap className="mr-3" />
Recommended Counter Moves
</h3>
{loading ? (
<div className="flex items-center space-x-3 text-gray-400">
<div className="transform-gpu will-change-transform">
<Loader size={20} className="animate-spin" />
</div>
<span>Loading moves that are effective against {pokemon.name}...</span>
</div>
) : counterMoves.length > 0 ? (
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
{counterMoves.map((move, index) => (
<div key={index} className="bg-white/5 rounded-lg p-4 border border-yellow-400/20">
<div className="flex justify-between items-start mb-2">
<h4 className="font-semibold">{move.name}</h4>
<span className={`px-2 py-1 rounded text-xs ${getTypeColor(move.type)}`}>
{move.type}
</span>
</div>
<div className="space-y-1 text-sm text-gray-300">
<div className="flex justify-between">
<span>Category:</span>
<span>{move.category}</span>
</div>
{move.power && (
<div className="flex justify-between">
<span>Power:</span>
<span>{move.power}</span>
</div>
)}
{move.accuracy && (
<div className="flex justify-between">
<span>Accuracy:</span>
<span>{move.accuracy}%</span>
</div>
)}
</div>
{move.description && (
<p className="text-xs text-gray-400 mt-2">{move.description}</p>
)}
</div>
))}
</div>
) : (
<div className="text-gray-400">No specific counter moves found.</div>
)}
</div>
</div>
);
};
export default PokemonAnalysis;