/**
 * Character Manager Component
 * 
 * Main interface for managing characters in the comic
 * Shows character list, allows editing, and generates reference images
 */

import type { JSX } from 'react';
import { useState, useCallback, useEffect } from 'react';
import { Users, RefreshCw, AlertCircle, Check, User, Sparkles, Image as ImageIcon, Grid3X3 } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { useComicStore } from '@/store/comicStore';
import { generateCharacterReference, generateCharacterSheet } from '@/services/falAiService';
import { updateCharacterFromDescription } from '@/utils/characterTemplates';
import type { Character } from '@/types';

interface CharacterCardProps {
  character: Character;
  isGenerating: boolean;
  onGenerateRef: () => void;
  onGenerateSheet: () => void;
  onEdit: (updates: Partial<Character>) => void;
  userMode: 'casual' | 'professional';
}

function CharacterCard({ 
  character, 
  isGenerating, 
  onGenerateRef, 
  onGenerateSheet,
  onEdit,
  userMode 
}: CharacterCardProps): JSX.Element {
  const [isEditing, setIsEditing] = useState(false);
  const [editedDesc, setEditedDesc] = useState(character.description);

  const handleSave = () => {
    onEdit({ description: editedDesc });
    setIsEditing(false);
  };

  return (
    <div className="border rounded-lg bg-card overflow-hidden">
      {/* Character Header */}
      <div className="p-4 border-b bg-muted/30">
        <div className="flex items-start justify-between">
          <div className="flex items-center gap-3">
            <div className="w-10 h-10 rounded-full bg-primary/10 flex items-center justify-center">
              <User className="w-5 h-5 text-primary" />
            </div>
            <div>
              <h3 className="font-semibold">{character.name}</h3>
              <span className="text-xs px-2 py-0.5 bg-secondary text-secondary-foreground rounded-full capitalize">
                {character.role}
              </span>
            </div>
          </div>
          
          {/* Action Buttons */}
          <div className="flex gap-1">
            {userMode === 'professional' && (
              <Button
                variant="ghost"
                size="sm"
                onClick={() => setIsEditing(!isEditing)}
                disabled={isGenerating}
              >
                {isEditing ? 'Cancel' : 'Edit'}
              </Button>
            )}
          </div>
        </div>
      </div>

      {/* Reference Image */}
      <div className="aspect-square bg-muted flex items-center justify-center relative">
        {character.referenceImageUrl ? (
          <img 
            src={character.referenceImageUrl} 
            alt={character.name}
            className="w-full h-full object-cover"
          />
        ) : (
          <div className="text-center p-4">
            <ImageIcon className="w-12 h-12 text-muted-foreground mx-auto mb-2" />
            <p className="text-sm text-muted-foreground">No reference image</p>
          </div>
        )}
        
        {/* Generate Button Overlay */}
        {!character.referenceImageUrl && !isGenerating && (
          <div className="absolute inset-0 flex items-center justify-center bg-black/50">
            <Button onClick={onGenerateRef} variant="secondary" size="lg">
              <Sparkles className="w-4 h-4 mr-2" />
              Generate
            </Button>
          </div>
        )}
        
        {isGenerating && (
          <div className="absolute inset-0 flex items-center justify-center bg-black/50">
            <RefreshCw className="w-8 h-8 text-white animate-spin" />
          </div>
        )}
      </div>

      {/* Character Details */}
      <div className="p-4 space-y-3">
        {/* Description */}
        {isEditing ? (
          <div className="space-y-2">
            <textarea
              value={editedDesc}
              onChange={(e) => setEditedDesc(e.target.value)}
              className="w-full h-24 p-2 text-sm border rounded resize-none"
              placeholder="Character description..."
            />
            <Button size="sm" onClick={handleSave} className="w-full">
              <Check className="w-4 h-4 mr-2" />
              Save Description
            </Button>
          </div>
        ) : (
          <p className="text-sm text-muted-foreground line-clamp-3">
            {character.description || 'No description available.'}
          </p>
        )}

        {/* Color Palette */}
        {userMode === 'professional' && (
          <div className="flex gap-2">
            {Object.entries(character.colorPalette).map(([key, color]) => (
              color && (
                <div key={key} className="flex items-center gap-1">
                  <div 
                    className="w-4 h-4 rounded border"
                    style={{ backgroundColor: color.toLowerCase() }}
                    title={color}
                  />
                  <span className="text-xs text-muted-foreground capitalize">{key}</span>
                </div>
              )
            ))}
          </div>
        )}

        {/* Action Buttons */}
        <div className="flex gap-2 pt-2">
          {character.referenceImageUrl && (
            <Button 
              variant="outline" 
              size="sm" 
              onClick={onGenerateRef}
              disabled={isGenerating}
              className="flex-1"
            >
              <RefreshCw className={`w-4 h-4 mr-1 ${isGenerating ? 'animate-spin' : ''}`} />
              Regenerate
            </Button>
          )}
          
          {userMode === 'professional' && character.referenceImageUrl && (
            <Button 
              variant="outline" 
              size="sm" 
              onClick={onGenerateSheet}
              disabled={isGenerating}
              className="flex-1"
            >
              <Grid3X3 className="w-4 h-4 mr-1" />
              Sheet
            </Button>
          )}
        </div>
      </div>
    </div>
  );
}

export function CharacterManager(): JSX.Element {
  const {
    characters,
    setCharacters,
    setCharacterRefImage,
    userMode,
    artStyle,
    setWorkflowStep,
    workflow,
    setWorkflowError,
  } = useComicStore();

  const [generatingId, setGeneratingId] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);

  // Auto-parse descriptions on mount if templates are empty
  useEffect(() => {
    const needsParsing = characters.some(char => !char.promptTemplate.age || char.promptTemplate.age === '');
    if (needsParsing) {
      const updated = characters.map(char => {
        if (!char.promptTemplate.age || char.promptTemplate.age === '') {
          return updateCharacterFromDescription(char);
        }
        return char;
      });
      setCharacters(updated);
    }
  }, []);

  // Parse descriptions and update templates on mount
  const handleParseAll = useCallback(() => {
    const updated = characters.map(char => {
      if (!char.promptTemplate.age || char.promptTemplate.age === '') {
        return updateCharacterFromDescription(char);
      }
      return char;
    });
    setCharacters(updated);
  }, [characters, setCharacters]);

  const handleGenerateRef = useCallback(async (characterId: string) => {
    setGeneratingId(characterId);
    setError(null);

    try {
      const character = characters.find(c => c.id === characterId);
      if (!character) return;

      // Ensure character has parsed template
      let charToUse = character;
      if (!character.promptTemplate.age || character.promptTemplate.age === '') {
        charToUse = updateCharacterFromDescription(character);
      }

      const imageUrl = await generateCharacterReference(charToUse, artStyle);
      setCharacterRefImage(characterId, imageUrl);
    } catch (err) {
      const msg = err instanceof Error ? err.message : 'Failed to generate reference';
      console.error('Character generation error:', err);
      setError(msg);
      setWorkflowError(msg);
    } finally {
      setGeneratingId(null);
    }
  }, [characters, artStyle, setCharacterRefImage, setWorkflowError]);

  const handleGenerateAll = useCallback(async () => {
    setError(null);
    
    // First, parse all descriptions
    const parsedCharacters = characters.map(char => {
      if (!char.promptTemplate.age || char.promptTemplate.age === '') {
        return updateCharacterFromDescription(char);
      }
      return char;
    });
    setCharacters(parsedCharacters);

    // Then generate references one by one
    for (const character of parsedCharacters) {
      if (!character.referenceImageUrl) {
        setGeneratingId(character.id);
        try {
          const imageUrl = await generateCharacterReference(character, artStyle);
          setCharacterRefImage(character.id, imageUrl);
        } catch (err) {
          const msg = err instanceof Error ? err.message : 'Failed to generate reference';
          console.error(`Failed to generate ${character.name}:`, err);
          setError(msg);
          setWorkflowError(msg);
          setGeneratingId(null);
          return;
        }
      }
    }
    setGeneratingId(null);
  }, [characters, artStyle, setCharacters, setCharacterRefImage, setWorkflowError]);

  const handleGenerateSheet = useCallback(async (characterId: string) => {
    setGeneratingId(characterId);
    setError(null);

    try {
      const character = characters.find(c => c.id === characterId);
      if (!character) return;

      const sheetUrls = await generateCharacterSheet(character, artStyle);
      
      // Update character with sheet URLs
      const updatedChars = characters.map(c => 
        c.id === characterId 
          ? { ...c, characterSheetUrls: sheetUrls }
          : c
      );
      setCharacters(updatedChars);
    } catch (err) {
      const msg = err instanceof Error ? err.message : 'Failed to generate sheet';
      setError(msg);
      setWorkflowError(msg);
    } finally {
      setGeneratingId(null);
    }
  }, [characters, artStyle, setCharacters, setWorkflowError]);

  const handleEditCharacter = useCallback((characterId: string, updates: Partial<Character>) => {
    const character = characters.find(c => c.id === characterId);
    if (!character) return;

    const updated = updateCharacterFromDescription({
      ...character,
      ...updates,
    });

    const updatedChars = characters.map(c => 
      c.id === characterId ? updated : c
    );
    setCharacters(updatedChars);
  }, [characters, setCharacters]);

  const handleProceed = useCallback(() => {
    setWorkflowStep('generating-panels');
  }, [setWorkflowStep]);

  const allHaveRefs = characters.every(c => c.referenceImageUrl);
  const generatedCount = characters.filter(c => c.referenceImageUrl).length;

  return (
    <div className="max-w-6xl mx-auto space-y-6">
      {/* Header */}
      <div className="flex items-center justify-between">
        <div>
          <h2 className="text-2xl font-bold flex items-center gap-2">
            <Users className="w-6 h-6" />
            Characters
          </h2>
          <p className="text-muted-foreground">
            {generatedCount} of {characters.length} have reference images
          </p>
        </div>
        
        <div className="flex gap-2">
          <Button variant="outline" onClick={handleParseAll}>
            Parse Descriptions
          </Button>
          <Button 
            variant="outline" 
            onClick={handleGenerateAll}
            disabled={generatingId !== null || allHaveRefs}
          >
            {generatingId ? (
              <RefreshCw className="w-4 h-4 mr-2 animate-spin" />
            ) : (
              <Sparkles className="w-4 h-4 mr-2" />
            )}
            Generate All
          </Button>
          <Button onClick={handleProceed} disabled={!allHaveRefs}>
            {allHaveRefs ? 'Proceed to Panels' : 'Generate All References First'}
          </Button>
        </div>
      </div>

      {/* Error Display */}
      {(error || workflow.error) && (
        <div className="bg-destructive/10 border border-destructive/30 text-destructive px-4 py-3 rounded-lg flex items-center gap-3">
          <AlertCircle className="w-5 h-5 shrink-0" />
          <p className="text-sm">{error || workflow.error}</p>
        </div>
      )}

      {/* Progress */}
      {characters.length > 0 && (
        <div className="space-y-2">
          <div className="h-2 bg-muted rounded-full overflow-hidden">
            <div 
              className="h-full bg-primary transition-all duration-500"
              style={{ width: `${(generatedCount / characters.length) * 100}%` }}
            />
          </div>
          <p className="text-center text-sm text-muted-foreground">
            {generatedCount === characters.length 
              ? 'All characters ready!' 
              : `${characters.length - generatedCount} characters need reference images`
            }
          </p>
        </div>
      )}

      {/* Character Grid */}
      {characters.length === 0 ? (
        <div className="text-center py-12 bg-muted/50 rounded-lg">
          <Users className="w-12 h-12 text-muted-foreground mx-auto mb-4" />
          <p className="text-muted-foreground">No characters found in the script.</p>
          <p className="text-sm text-muted-foreground mt-1">
            Go back to Story and generate a script first.
          </p>
        </div>
      ) : (
        <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4">
          {characters.map((character) => (
            <CharacterCard
              key={character.id}
              character={character}
              isGenerating={generatingId === character.id}
              onGenerateRef={() => handleGenerateRef(character.id)}
              onGenerateSheet={() => handleGenerateSheet(character.id)}
              onEdit={(updates) => handleEditCharacter(character.id, updates)}
              userMode={userMode}
            />
          ))}
        </div>
      )}
    </div>
  );
}
