<template>
  <main class="flex flex-col flex-1 bg-white/80 dark:bg-gray-900/80 backdrop-blur-md rounded-3xl shadow-2xl border border-gray-200/50 dark:border-gray-700/50 transition-all duration-300" :class="{ 'lg:overflow-hidden': layers.some(l => l.sprites.length) }">
    <!-- Welcome state -->
    <div v-if="!layers.some(l => l.sprites.length)" class="p-6 sm:p-10">
      <div class="mb-8">
        <div class="flex items-center justify-between gap-4 mb-1">
          <p class="text-2xl font-bold text-gray-800 dark:text-gray-100">Upload sprites or single image</p>
          <a href="https://ko-fi.com/X8X416D44P" target="_blank" rel="noopener noreferrer">
            <img height="36" style="border: 0px; height: 36px" src="https://storage.ko-fi.com/cdn/kofi6.png?v=6" alt="Buy Me a Coffee at ko-fi.com" />
          </a>
        </div>
        <p class="text-sm text-gray-600 dark:text-gray-400">Drag and drop images or import from JSON</p>
      </div>
      <file-uploader @upload-sprites="handleSpritesUpload" />

      <div class="mt-10">
        <div class="prose prose-lg dark:prose-invert max-w-none">
          <div>
            <h1 class="text-2xl font-bold text-gray-800 dark:text-gray-100 mb-4">Welcome to Spritesheet generator</h1>
            <p class="text-gray-700 dark:text-gray-300 mb-4">Create spritesheets for your game development and animation projects with our completely free, open-source Spritesheet generator.</p>
            <p class="text-gray-700 dark:text-gray-300 mb-6">This powerful online tool lets you upload individual sprite images and automatically arrange them into optimized sprite sheets with customizable layouts - perfect for indie developers, animators, and studios of any size.</p>
            <h3 class="text-2xl font-bold text-gray-800 dark:text-gray-100 mb-4">Key features of this sprite editor</h3>
            <ul class="text-gray-700 dark:text-gray-300 mb-6 space-y-2 list-disc">
              <li><strong>Free sprite editor</strong>: Edit, organize, and optimize your game sprites directly in your browser</li>
              <li><strong>Automatic spritesheet generation</strong>: Convert multiple PNG, JPG, or GIF images into efficient sprite atlases</li>
              <li><strong>Customizable grid layouts</strong>: Adjust spacing, padding, and arrangement for pixel-perfect results</li>
              <li><strong>Animation preview</strong>: Test your sprite animations before exporting</li>
              <li><strong>Cross-platform compatibility</strong>: Works with Unity, Godot, Phaser, Pygame, and other game engines</li>
              <li><strong>Zero installation required</strong>: No downloads - use our web-based sprite sheet maker instantly</li>
              <li><strong>Batch processing</strong>: Upload and process multiple sprites simultaneously</li>
              <li><strong>Export options</strong>: Download spritesheet as PNG, JPG, GIF, ZIP or JSON.</li>
            </ul>
            <div>
              <h4 class="text-xl font-bold text-gray-800 dark:text-gray-100 mb-4 flex items-center gap-2">
                <i class="fas fa-play-circle text-gray-800 dark:text-gray-200"></i>
                How it works
              </h4>
              <video controls playsinline class="w-full rounded-lg shadow-lg border border-gray-200 dark:border-gray-700" title="Spritesheet generator tutorial" aria-label="Spritesheet generator tutorial">
                <source src="@/assets/demo.mp4" type="video/mp4" />
              </video>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- Two-column layout: Left controls, Right preview -->
    <div v-if="layers.some(l => l.sprites.length)" class="flex flex-col flex-1 lg:grid lg:grid-cols-[380px_1fr] xl:grid-cols-[420px_1fr] lg:overflow-hidden min-h-0">
      <!-- Left sidebar - Controls -->
      <div class="p-6 bg-gray-50/50 dark:bg-gray-900/30 border-b lg:border-b-0 lg:border-r border-gray-200 dark:border-gray-700 lg:overflow-y-auto lg:overflow-x-auto lg:min-h-0">
        <div class="space-y-8">
          <!-- Upload Section -->
          <section>
            <div class="flex items-center justify-between mb-3">
              <h3 class="flex items-center gap-2 text-base font-bold text-gray-800 dark:text-gray-100">
                <i class="text-sm text-gray-700 dark:text-gray-300 fas fa-upload"></i>
                Upload
              </h3>
              <button @click="openJSONImportDialog" class="btn btn-dark btn-sm" data-rybbit-event="import-json">
                <i class="text-xs fas fa-file-import"></i>
                <span>JSON</span>
              </button>
            </div>
            <button
              class="w-full p-6 text-center border-2 border-dashed border-gray-300 dark:border-gray-600 rounded-xl hover:border-gray-500 dark:hover:border-gray-400 hover:bg-gray-50 dark:hover:bg-gray-800/50 transition-all cursor-pointer focus:outline-none focus:ring-2 focus:ring-gray-500 group"
              @click="openFileDialog"
            >
              <i class="fas fa-plus-circle text-3xl text-gray-400 dark:text-gray-500 group-hover:text-gray-600 dark:group-hover:text-gray-300 mb-3 transition-colors"></i>
              <p class="text-sm font-medium text-gray-600 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-gray-200 transition-colors">Add sprites</p>
            </button>
            <input ref="uploadInput" type="file" multiple accept="image/*" class="hidden" @change="handleUploadChange" />
            <input ref="jsonFileInput" type="file" accept=".json,application/json" class="hidden" @change="handleJSONFileChange" />
          </section>

          <!-- Layers -->
          <section>
            <div class="flex items-center justify-between mb-3">
              <h3 class="flex items-center gap-2 text-base font-bold text-gray-800 dark:text-gray-100">
                <i class="text-sm text-gray-700 dark:text-gray-300 fas fa-layer-group"></i>
                Layers
              </h3>
              <button @click="addLayer()" class="btn btn-dark btn-sm">
                <i class="text-xs fas fa-plus"></i>
                <span>Add</span>
              </button>
            </div>
            <div class="space-y-2">
              <div
                v-for="layer in layers"
                :key="layer.id"
                class="flex items-center gap-2 px-3 py-2 bg-white dark:bg-gray-800 border rounded-lg transition-all"
                :class="[layer.id === activeLayerId ? 'border-gray-800 ring-1 ring-gray-800 dark:border-gray-400 dark:ring-gray-400' : 'border-gray-200 dark:border-gray-700', !layer.visible ? 'opacity-50' : '']"
              >
                <button @click.stop="layer.visible = !layer.visible" class="btn btn-ghost btn-icon-sm rounded" :title="layer.visible ? 'Hide layer' : 'Show layer'">
                  <i :class="layer.visible ? 'text-sm text-gray-800 dark:text-gray-200 fas fa-eye' : 'text-sm text-gray-400 dark:text-gray-500 fas fa-eye-slash'"></i>
                </button>
                <input
                  v-if="editingLayerId === layer.id"
                  type="text"
                  v-model="editingLayerName"
                  @blur="finishEditingLayer"
                  @keyup.enter="finishEditingLayer"
                  @keyup.esc="cancelEditingLayer"
                  class="flex-1 px-2 py-1 text-sm border border-gray-800 dark:border-gray-400 dark:bg-gray-700 dark:text-gray-100 rounded outline-none focus:ring-2 focus:ring-gray-800 dark:focus:ring-gray-400"
                  ref="layerNameInput"
                  @click.stop
                />
                <button v-else @click="activeLayerId = layer.id" class="flex-1 px-2 py-1 text-sm font-medium text-left rounded transition-all cursor-pointer" :class="layer.id === activeLayerId ? 'text-gray-900 dark:text-gray-100' : 'text-gray-700 dark:text-gray-300'">
                  {{ layer.name }}
                  <span v-if="layer.sprites.length" class="ml-1 text-xs opacity-60">({{ layer.sprites.length }})</span>
                </button>
                <button v-if="editingLayerId !== layer.id" @click="startEditingLayer(layer.id, layer.name)" class="btn btn-ghost btn-icon-xs rounded" title="Rename">
                  <i class="text-xs text-gray-600 dark:text-gray-400 fas fa-pen"></i>
                </button>
                <button @click="moveLayer(layer.id, 'up')" class="btn btn-ghost btn-icon-xs rounded" title="Move up">
                  <i class="text-xs text-gray-600 dark:text-gray-400 fas fa-chevron-up"></i>
                </button>
                <button @click="moveLayer(layer.id, 'down')" class="btn btn-ghost btn-icon-xs rounded" title="Move down">
                  <i class="text-xs text-gray-600 dark:text-gray-400 fas fa-chevron-down"></i>
                </button>
                <button v-if="layers.length > 1" @click="removeLayer(layer.id)" class="btn btn-danger btn-icon-xs rounded" title="Delete">
                  <i class="text-xs fas fa-trash"></i>
                </button>
              </div>
            </div>
          </section>

          <!-- Grid Settings -->
          <section>
            <h3 class="flex items-center gap-2 mb-3 text-base font-bold text-gray-800 dark:text-gray-100">
              <i class="text-sm text-gray-700 dark:text-gray-300 fas fa-th"></i>
              Grid
            </h3>
            <div class="space-y-3">
              <div class="flex items-center justify-between px-3 py-2 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg">
                <label for="columns" class="text-sm font-medium text-gray-700 dark:text-gray-200">Columns</label>
                <input id="columns" type="number" v-model.number="columns" min="1" max="10" class="input-field w-16" />
              </div>

              <div class="px-3 py-2 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg">
                <label class="flex items-center justify-between mb-2 cursor-pointer">
                  <span class="text-sm font-medium text-gray-700 dark:text-gray-200">Manual size</span>
                  <input type="checkbox" v-model="settingsStore.manualCellSizeEnabled" class="w-4 h-4 rounded" />
                </label>
                <div v-if="settingsStore.manualCellSizeEnabled" class="flex items-center gap-1.5 mt-2">
                  <input type="number" v-model.number="settingsStore.manualCellWidth" min="1" max="2048" class="input-field w-full min-w-0" placeholder="W" />
                  <span class="flex-shrink-0 text-gray-500 dark:text-gray-400">×</span>
                  <input type="number" v-model.number="settingsStore.manualCellHeight" min="1" max="2048" class="input-field w-full min-w-0" placeholder="H" />
                </div>
                <div v-else class="mt-1 text-xs font-mono text-gray-500 dark:text-gray-400 break-words">{{ cellSize.width }} × {{ cellSize.height }}px</div>
              </div>
            </div>
          </section>

          <!-- Alignment -->
          <section>
            <h3 class="flex items-center gap-2 mb-3 text-base font-bold text-gray-800 dark:text-gray-100">
              <i class="text-sm text-gray-700 dark:text-gray-300 fas fa-align-center"></i>
              Align
            </h3>
            <div class="grid grid-cols-3 gap-2">
              <button @click="alignSprites('left')" class="btn btn-secondary btn-sm" title="Left">
                <i class="fas fa-arrow-left"></i>
              </button>
              <button @click="alignSprites('center')" class="btn btn-secondary btn-sm" title="Center">
                <i class="fas fa-arrows-left-right"></i>
              </button>
              <button @click="alignSprites('right')" class="btn btn-secondary btn-sm" title="Right">
                <i class="fas fa-arrow-right"></i>
              </button>
              <button @click="alignSprites('top')" class="btn btn-secondary btn-sm" title="Top">
                <i class="fas fa-arrow-up"></i>
              </button>
              <button @click="alignSprites('middle')" class="btn btn-secondary btn-sm" title="Middle">
                <i class="fas fa-arrows-up-down"></i>
              </button>
              <button @click="alignSprites('bottom')" class="btn btn-secondary btn-sm" title="Bottom">
                <i class="fas fa-arrow-down"></i>
              </button>
            </div>
          </section>

          <!-- Export -->
          <section>
            <h3 class="flex items-center gap-2 mb-3 text-base font-bold text-gray-800 dark:text-gray-100">
              <i class="text-sm text-gray-700 dark:text-gray-300 fas fa-download"></i>
              Export
            </h3>
            <div class="grid grid-cols-2 gap-2">
              <button @click="downloadSpritesheet" class="btn btn-dark btn-sm" data-rybbit-event="download-spritesheet">
                <i class="fas fa-image"></i>
                <span>PNG</span>
              </button>
              <button @click="exportSpritesheetJSON" class="btn btn-dark btn-sm" data-rybbit-event="export-json">
                <i class="fas fa-file-code"></i>
                <span>JSON</span>
              </button>
              <button @click="openGifFpsModal" class="btn btn-dark btn-sm" data-rybbit-event="download-gif">
                <i class="fas fa-film"></i>
                <span>GIF</span>
              </button>
              <button @click="downloadAsZip" class="btn btn-dark btn-sm" data-rybbit-event="download-zip">
                <i class="fas fa-file-archive"></i>
                <span>ZIP</span>
              </button>
              <button @click="openShareModal" class="btn btn-dark btn-sm col-span-2" data-rybbit-event="share-spritesheet">
                <i class="fas fa-share-alt"></i>
                <span>Share</span>
              </button>
            </div>
          </section>
        </div>
      </div>

      <!-- Right panel - Tabs -->
      <div class="flex flex-col overflow-hidden min-h-0">
        <!-- Tab Navigation -->
        <div class="bg-gray-50/50 dark:bg-gray-900/30 border-b border-gray-200 dark:border-gray-700">
          <div class="flex items-center justify-between gap-1 p-2">
            <div class="flex gap-1">
              <button
                @click="activeTab = 'canvas'"
                class="border-gray-600 border"
                :class="[
                  'flex items-center gap-2 px-4 py-2 text-sm font-medium rounded-lg transition-all cursor-pointer',
                  activeTab === 'canvas' ? 'bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 shadow-sm' : 'text-gray-600 dark:text-gray-400 hover:bg-white/50 dark:hover:bg-gray-800/50',
                ]"
              >
                <i class="fas fa-th"></i>
                <span>Canvas</span>
              </button>
              <button
                @click="activeTab = 'preview'"
                class="border-gray-600 border"
                :class="[
                  'flex items-center gap-2 px-4 py-2 text-sm font-medium rounded-lg transition-all cursor-pointer',
                  activeTab === 'preview' ? 'bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 shadow-sm' : 'text-gray-600 dark:text-gray-400 hover:bg-white/50 dark:hover:bg-gray-800/50',
                ]"
                data-rybbit-event="preview-animation"
              >
                <i class="fas fa-play"></i>
                <span>Preview</span>
              </button>
            </div>
            <button @click="openShareModal" class="flex items-center gap-2 px-4 py-2 mr-2.5 text-sm font-medium rounded-lg bg-gradient-to-r from-blue-500 to-purple-600 text-white shadow-sm hover:shadow-md transition-all cursor-pointer" data-rybbit-event="share-spritesheet-header">
              <i class="fas fa-share-alt"></i>
              <span>Share spritesheet</span>
            </button>
          </div>
        </div>

        <!-- Tab Content -->
        <div class="p-6 lg:flex-1 lg:overflow-auto lg:min-h-0">
          <div v-if="activeTab === 'canvas'" class="h-full">
            <sprite-canvas :layers="layers" :active-layer-id="activeLayerId" :columns="columns" @update-sprite="updateSpritePosition" @update-sprite-cell="updateSpriteCell" @remove-sprite="removeSprite" @replace-sprite="replaceSprite" @add-sprite="addSprite" />
          </div>
          <div v-if="activeTab === 'preview'" class="h-full">
            <sprite-preview :layers="layers" :active-layer-id="activeLayerId" :columns="columns" @update-sprite="updateSpritePosition" @update-sprite-in-layer="updateSpriteInLayer" />
          </div>
        </div>
      </div>
    </div>

    <SpritesheetSplitter :is-open="isSpritesheetSplitterOpen" :image-url="spritesheetImageUrl" :image-file="spritesheetImageFile" @close="closeSpritesheetSplitter" @split="handleSplitSpritesheet" />
    <GifFpsModal :is-open="isGifFpsModalOpen" @close="closeGifFpsModal" @confirm="downloadAsGif" :default-fps="10" />
    <ShareModal :is-open="isShareModalOpen" :share-function="shareFunction" @close="closeShareModal" />
  </main>
</template>

<script setup lang="ts">
  import { ref, toRef, computed } from 'vue';
  import FileUploader from '@/components/FileUploader.vue';
  import SpriteCanvas from '@/components/SpriteCanvas.vue';
  import SpritePreview from '@/components/SpritePreview.vue';
  import SpritesheetSplitter from '@/components/SpritesheetSplitter.vue';
  import GifFpsModal from '@/components/GifFpsModal.vue';
  import ShareModal from '@/components/ShareModal.vue';
  import { useExportLayers } from '@/composables/useExportLayers';
  import { useShare } from '@/composables/useShare';
  import { useLayers } from '@/composables/useLayers';
  import { getMaxDimensionsAcrossLayers } from '@/composables/useLayers';
  import { useSettingsStore } from '@/stores/useSettingsStore';
  import { calculateNegativeSpacing } from '@/composables/useNegativeSpacing';
  import { useHomeViewSEO } from './HomeView.seo';
  import type { SpriteFile } from '@/types/sprites';

  // Initialize SEO
  useHomeViewSEO();

  const settingsStore = useSettingsStore();
  const { layers, visibleLayers, activeLayer, activeLayerId, columns, updateSpritePosition, updateSpriteInLayer, updateSpriteCell, removeSprite, replaceSprite, addSprite, processImageFiles, alignSprites, addLayer, removeLayer, moveLayer } = useLayers();

  const { downloadSpritesheet, exportSpritesheetJSON, importSpritesheetJSON, downloadAsGif, downloadAsZip } = useExportLayers(
    layers,
    columns,
    toRef(settingsStore, 'negativeSpacingEnabled'),
    activeLayerId,
    toRef(settingsStore, 'backgroundColor'),
    toRef(settingsStore, 'manualCellSizeEnabled'),
    toRef(settingsStore, 'manualCellWidth'),
    toRef(settingsStore, 'manualCellHeight')
  );

  const getCellSize = () => {
    if (!visibleLayers.value.length) return { width: 0, height: 0 };

    if (settingsStore.manualCellSizeEnabled) {
      return { width: settingsStore.manualCellWidth, height: settingsStore.manualCellHeight };
    }

    const { maxWidth, maxHeight } = getMaxDimensionsAcrossLayers(visibleLayers.value);
    const allSprites = visibleLayers.value.flatMap(l => l.sprites);
    const negativeSpacing = calculateNegativeSpacing(allSprites, settingsStore.negativeSpacingEnabled);
    return { width: maxWidth + negativeSpacing, height: maxHeight + negativeSpacing };
  };

  const cellSize = computed(getCellSize);
  const activeTab = ref<'canvas' | 'preview'>('canvas');
  const isSpritesheetSplitterOpen = ref(false);
  const isGifFpsModalOpen = ref(false);
  const isShareModalOpen = ref(false);
  const uploadInput = ref<HTMLInputElement | null>(null);
  const jsonFileInput = ref<HTMLInputElement | null>(null);
  const spritesheetImageUrl = ref('');
  const spritesheetImageFile = ref<File | null>(null);
  const editingLayerId = ref<string | null>(null);
  const editingLayerName = ref('');
  const layerNameInput = ref<HTMLInputElement | null>(null);

  const handleSpritesUpload = async (files: File[]) => {
    const jsonFile = files.find(file => file.type === 'application/json' || file.name.endsWith('.json'));

    if (jsonFile) {
      await handleJSONImport(jsonFile);
      return;
    }

    if (files.length === 1 && files[0].type.startsWith('image/')) {
      const file = files[0];
      const reader = new FileReader();
      reader.onload = e => {
        const url = e.target?.result as string;
        const img = new Image();
        img.onload = () => {
          if (confirm('This looks like it might be a spritesheet. Would you like to split it into individual sprites?')) {
            spritesheetImageUrl.value = url;
            spritesheetImageFile.value = file;
            isSpritesheetSplitterOpen.value = true;
            return;
          }

          processImageFiles([file]);
        };
        img.onerror = () => {
          console.error('Failed to load image:', file.name);
        };
        img.src = url;
      };
      reader.onerror = () => {
        console.error('Failed to read image file:', file.name);
      };
      reader.readAsDataURL(file);
      return;
    }

    processImageFiles(files);
  };

  const handleJSONImport = async (jsonFile: File) => {
    try {
      await importSpritesheetJSON(jsonFile);
    } catch (error) {
      console.error('Error importing JSON:', error);
      alert('Failed to import JSON file. Please check the file format.');
    }
  };

  const closeSpritesheetSplitter = () => {
    isSpritesheetSplitterOpen.value = false;
    if (spritesheetImageUrl.value && spritesheetImageUrl.value.startsWith('blob:')) {
      try {
        URL.revokeObjectURL(spritesheetImageUrl.value);
      } catch {}
    }
    spritesheetImageUrl.value = '';
    spritesheetImageFile.value = null;
  };

  const openGifFpsModal = () => {
    if (!visibleLayers.value.some(l => l.sprites.length > 0)) {
      alert('Please upload or import sprites before generating a GIF.');
      return;
    }
    isGifFpsModalOpen.value = true;
  };

  const closeGifFpsModal = () => {
    isGifFpsModalOpen.value = false;
  };

  // Share functionality
  const { share } = useShare(layers, columns, toRef(settingsStore, 'negativeSpacingEnabled'), toRef(settingsStore, 'backgroundColor'), toRef(settingsStore, 'manualCellSizeEnabled'), toRef(settingsStore, 'manualCellWidth'), toRef(settingsStore, 'manualCellHeight'));

  const shareFunction = () => share();

  const openShareModal = () => {
    if (!visibleLayers.value.some(l => l.sprites.length > 0)) {
      alert('Please upload or import sprites before sharing.');
      return;
    }
    isShareModalOpen.value = true;
  };

  const closeShareModal = () => {
    isShareModalOpen.value = false;
  };

  const handleSplitSpritesheet = (spriteFiles: SpriteFile[]) => {
    processImageFiles(spriteFiles.map(s => s.file));
  };

  const openJSONImportDialog = () => {
    jsonFileInput.value?.click();
  };

  const handleJSONFileChange = async (event: Event) => {
    const input = event.target as HTMLInputElement;
    if (input.files && input.files.length > 0) {
      await handleJSONImport(input.files[0]);
      input.value = '';
    }
  };

  const openFileDialog = () => {
    uploadInput.value?.click();
  };

  const handleUploadChange = async (event: Event) => {
    const input = event.target as HTMLInputElement;
    if (input.files && input.files.length > 0) {
      await handleSpritesUpload(Array.from(input.files));
      input.value = '';
    }
  };

  const startEditingLayer = (layerId: string, currentName: string) => {
    editingLayerId.value = layerId;
    editingLayerName.value = currentName;
    // Focus the input on next tick
    setTimeout(() => {
      layerNameInput.value?.focus();
      layerNameInput.value?.select();
    }, 0);
  };

  const finishEditingLayer = () => {
    if (editingLayerId.value && editingLayerName.value.trim()) {
      const layer = layers.value.find(l => l.id === editingLayerId.value);
      if (layer) {
        layer.name = editingLayerName.value.trim();
      }
    }
    editingLayerId.value = null;
    editingLayerName.value = '';
  };

  const cancelEditingLayer = () => {
    editingLayerId.value = null;
    editingLayerName.value = '';
  };
</script>
