<script lang="ts">
  import type { MonsterGeneratorProps, MonsterWorkflowState, CaptionType, CaptionLength } from '$lib/types';
  import UploadStep from './UploadStep.svelte';
  import WorkflowProgress from './WorkflowProgress.svelte';
  import MonsterResult from './MonsterResult.svelte';
  
  interface Props extends MonsterGeneratorProps {}
  
  let { joyCaptionClient, rwkvClient, fluxClient }: Props = $props();
  
  let state: MonsterWorkflowState = $state({
    currentStep: 'upload',
    userImage: null,
    imageCaption: null,
    monsterConcept: null,
    imagePrompt: null,
    monsterImage: null,
    error: null,
    isProcessing: false
  });
  
  // Prompt templates
  const MONSTER_CONCEPT_PROMPT = (caption: string) => `Based on this description of a person/photo: "${caption}"

Create a unique monster concept inspired by the key visual elements. Include:
- Physical appearance and distinguishing features
- Special abilities or powers  
- Personality traits
- Habitat or origin

Be creative and detailed. The monster should be fantastical but somehow connected to the original image's essence.`;

  const IMAGE_GENERATION_PROMPT = (concept: string) => `Convert this monster concept into a detailed image generation prompt:
"${concept}"

Create a vivid, artistic prompt focusing on visual details, art style, lighting, and atmosphere. Format it as a single paragraph optimized for image generation.`;
  
  async function handleImageSelected(file: File) {
    if (!joyCaptionClient || !rwkvClient || !fluxClient) {
      state.error = "Services not connected. Please wait...";
      return;
    }
    
    state.userImage = file;
    state.error = null;
    startWorkflow();
  }
  
  async function startWorkflow() {
    state.isProcessing = true;
    
    try {
      // Step 1: Caption the image
      await captionImage();
      await new Promise(resolve => setTimeout(resolve, 100)); // Small delay for state update
      
      // Step 2: Generate monster concept
      await generateMonsterConcept();
      await new Promise(resolve => setTimeout(resolve, 100)); // Small delay for state update
      
      // Step 3: Generate image prompt
      await generateImagePrompt();
      await new Promise(resolve => setTimeout(resolve, 100)); // Small delay for state update
      
      // Step 4: Generate monster image
      await generateMonsterImage();
      
      state.currentStep = 'complete';
    } catch (err) {
      console.error('Workflow error:', err);
      state.error = err instanceof Error ? err.message : 'An unknown error occurred';
    } finally {
      state.isProcessing = false;
    }
  }
  
  async function captionImage() {
    state.currentStep = 'captioning';
    
    if (!joyCaptionClient || !state.userImage) {
      throw new Error('Caption service not available or no image provided');
    }
    
    const output = await joyCaptionClient.predict("/stream_chat", [
      state.userImage,
      "Descriptive" as CaptionType,
      "very long" as CaptionLength,
      [], // extra_options
      "", // name_input
      ""  // custom_prompt
    ]);
    
    const [prompt, caption] = output.data;
    state.imageCaption = caption;
    console.log('Caption generated:', caption);
  }
  
  async function generateMonsterConcept() {
    state.currentStep = 'conceptualizing';
    
    if (!rwkvClient || !state.imageCaption) {
      throw new Error('Text generation service not available or no caption');
    }
    
    const conceptPrompt = MONSTER_CONCEPT_PROMPT(state.imageCaption);
    
    console.log('Generating monster concept with prompt:', conceptPrompt);
    
    const output = await rwkvClient.predict(0, [
      conceptPrompt,
      300,   // maxTokens
      1.2,   // temperature (more creative)
      0.8,   // topP
      0.1,   // presencePenalty
      0.1    // countPenalty
    ]);
    
    console.log('RWKV output:', output);
    state.monsterConcept = output.data[0];
    console.log('Monster concept generated:', state.monsterConcept);
    
    if (!state.monsterConcept || state.monsterConcept.trim() === '') {
      throw new Error('Failed to generate monster concept - received empty response');
    }
  }
  
  async function generateImagePrompt() {
    state.currentStep = 'promptCrafting';
    
    if (!rwkvClient || !state.monsterConcept) {
      throw new Error('Text generation service not available or no concept');
    }
    
    const promptGenerationPrompt = IMAGE_GENERATION_PROMPT(state.monsterConcept);
    
    console.log('Generating image prompt from concept');
    
    const output = await rwkvClient.predict(0, [
      promptGenerationPrompt,
      150,   // maxTokens
      0.9,   // temperature
      0.7,   // topP
      0.1,   // presencePenalty
      0.1    // countPenalty
    ]);
    
    console.log('Image prompt output:', output);
    state.imagePrompt = output.data[0];
    console.log('Image prompt generated:', state.imagePrompt);
    
    if (!state.imagePrompt || state.imagePrompt.trim() === '') {
      throw new Error('Failed to generate image prompt - received empty response');
    }
  }
  
  async function generateMonsterImage() {
    state.currentStep = 'generating';
    
    if (!fluxClient || !state.imagePrompt) {
      throw new Error('Image generation service not available or no prompt');
    }
    
    const output = await fluxClient.predict("/infer", [
      state.imagePrompt,
      0,      // seed
      true,   // randomizeSeed
      1024,   // width
      1024,   // height
      4       // steps
    ]);
    
    const [image, usedSeed] = output.data;
    let url: string | undefined;
    
    if (typeof image === "string") url = image;
    else if (image && image.url) url = image.url;
    else if (image && image.path) url = image.path;
    
    if (url) {
      state.monsterImage = {
        imageUrl: url,
        seed: usedSeed,
        prompt: state.imagePrompt
      };
    } else {
      throw new Error('Failed to generate monster image');
    }
  }
  
  function reset() {
    state = {
      currentStep: 'upload',
      userImage: null,
      imageCaption: null,
      monsterConcept: null,
      imagePrompt: null,
      monsterImage: null,
      error: null,
      isProcessing: false
    };
  }
</script>

<div class="monster-generator">
  
  {#if state.currentStep !== 'upload'}
    <WorkflowProgress currentStep={state.currentStep} error={state.error} />
  {/if}
  
  {#if state.currentStep === 'upload'}
    <UploadStep 
      onImageSelected={handleImageSelected}
      isProcessing={state.isProcessing}
    />
  {:else if state.currentStep === 'complete'}
    <MonsterResult state={state} onReset={reset} />
  {:else}
    <div class="processing-container">
      <div class="spinner"></div>
      <p class="processing-text">
        {#if state.currentStep === 'captioning'}
          Analyzing your image...
        {:else if state.currentStep === 'conceptualizing'}
          Creating monster concept...
        {:else if state.currentStep === 'promptCrafting'}
          Crafting generation prompt...
        {:else if state.currentStep === 'generating'}
          Generating your monster...
        {/if}
      </p>
      
      {#if state.imageCaption && state.currentStep !== 'captioning'}
        <div class="intermediate-result">
          <h4>Image Description:</h4>
          <p>{state.imageCaption}</p>
        </div>
      {/if}
      
      {#if state.monsterConcept && state.currentStep !== 'captioning' && state.currentStep !== 'conceptualizing'}
        <div class="intermediate-result">
          <h4>Monster Concept:</h4>
          <p>{state.monsterConcept}</p>
        </div>
      {/if}
      
      {#if state.imagePrompt && state.currentStep === 'generating'}
        <div class="intermediate-result">
          <h4>Generation Prompt:</h4>
          <p>{state.imagePrompt}</p>
        </div>
      {/if}
    </div>
  {/if}
</div>

<style>
  .monster-generator {
    width: 100%;
    max-width: 1200px;
    margin: 0 auto;
    padding: 2rem;
  }
  
  
  .processing-container {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 3rem 1rem;
  }
  
  .spinner {
    width: 60px;
    height: 60px;
    border: 3px solid #f3f3f3;
    border-top: 3px solid #007bff;
    border-radius: 50%;
    animation: spin 1s linear infinite;
    margin-bottom: 2rem;
  }
  
  @keyframes spin {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
  }
  
  .processing-text {
    font-size: 1.2rem;
    color: #333;
    margin-bottom: 2rem;
  }
  
  .intermediate-result {
    width: 100%;
    max-width: 700px;
    background: #f8f9fa;
    padding: 1.5rem;
    border-radius: 8px;
    margin-bottom: 1.5rem;
    text-align: left;
  }
  
  .intermediate-result h4 {
    margin: 0 0 0.5rem 0;
    color: #495057;
  }
  
  .intermediate-result p {
    margin: 0;
    line-height: 1.6;
    color: #333;
  }
</style>