import { defineStore } from "pinia";
import { ref, computed } from "vue";
import { invoke } from "@tauri-apps/api/core";

export interface MaskStroke {
    type: 'path' | 'rect';
    points?: {x: number, y: number}[]; // Normalized
    rect?: {x: number, y: number, w: number, h: number}; // Normalized
    width?: number; // Normalized brush width for paths
}

export interface ImageItem {
  path: string;
  originalPath: string;
  thumbnail: string; 
  name: string;
  width?: number;
  height?: number;
  zcaSuggestion?: { x: number; y: number; zone: string };
  manualPosition?: { x: number; y: number };
  scale?: number;
  opacity?: number;
  color?: string;
  maskStrokes?: MaskStroke[];
}

export interface WatermarkSettings {
    type: 'text'; 
    text: string;
    color: string; 
    opacity: number; 
    scale: number; 
}

export const useGalleryStore = defineStore("gallery", () => {
  const images = ref<ImageItem[]>([]);
  const selectedIndex = ref<number>(-1);
  
  // 'add' = Add Watermark, 'remove' = Remove Watermark (Inpainting)
  const editMode = ref<'add' | 'remove'>('add');
  
  const watermarkSettings = ref<WatermarkSettings>({
      type: 'text',
      text: '水印',
      color: '#FFFFFF',
      opacity: 1.0,
      scale: 0.03, 
  });
  
  const brushSettings = ref({
      size: 20, // screen pixels
      opacity: 0.5 // visual only
  });

  const isDetecting = ref(false);
  const isProcessing = ref(false);
  const progress = ref({ current: 0, total: 0 });

  const selectedImage = computed(() => {
    if (selectedIndex.value >= 0 && selectedIndex.value < images.value.length) {
      return images.value[selectedIndex.value];
    }
    return null;
  });

  function setImages(newImages: ImageItem[]) {
    images.value = newImages.map(img => ({
        ...img,
        // Ensure originalPath is set if not already present from backend
        originalPath: img.originalPath || img.path
    }));
    selectedIndex.value = -1;
  }

  function restoreImage(index: number) {
      const img = images.value[index];
      if (img) {
          img.path = img.originalPath;
          img.maskStrokes = []; // Also clear any masks if restoring
      }
  }
  
  function updateWatermarkSettings(settings: Partial<WatermarkSettings>) {
      watermarkSettings.value = { ...watermarkSettings.value, ...settings };
  }

  function setImageManualPosition(index: number, x: number, y: number) {
      if (images.value[index]) {
          images.value[index].manualPosition = { x, y };
      }
  }

  function setImageSetting(index: number, setting: 'scale' | 'opacity' | 'color', value: number | string) {
      if (images.value[index]) {
          // @ts-ignore
          images.value[index][setting] = value;
      }
  }

  function addMaskStroke(index: number, stroke: MaskStroke) {
      if (images.value[index]) {
          if (!images.value[index].maskStrokes) {
              images.value[index].maskStrokes = [];
          }
          images.value[index].maskStrokes!.push(stroke);
      }
  }

  function clearMask(index: number) {
      if (images.value[index]) {
          images.value[index].maskStrokes = [];
      }
  }

  // Helper to run detection on a single image object
  async function detectWatermarkForImage(img: ImageItem) {
      try {
          // Clear existing mask first
          img.maskStrokes = [];
          
          // @ts-ignore
          const result = await invoke<{rects: {x: number, y: number, width: number, height: number}[]}>("detect_watermark", { path: img.path });
          
          if (result.rects && result.rects.length > 0) {
             result.rects.forEach(r => {
                 img.maskStrokes!.push({
                     type: 'rect',
                     rect: { x: r.x, y: r.y, w: r.width, h: r.height }
                 });
             });
          }
      } catch (e) {
          console.error(`Detection failed for ${img.name}`, e);
      }
  }

  async function detectCurrentWatermark() {
      if (selectedIndex.value < 0 || !images.value[selectedIndex.value]) return;
      isDetecting.value = true;
      progress.value = { current: 0, total: 1 };
      try {
          await detectWatermarkForImage(images.value[selectedIndex.value]);
          progress.value.current = 1;
      } finally {
          isDetecting.value = false;
      }
  }

  async function detectAllWatermarks() {
      if (images.value.length === 0) return;
      isDetecting.value = true;
      progress.value = { current: 0, total: images.value.length };

      try {
          const batchSize = 5;
          for (let i = 0; i < images.value.length; i += batchSize) {
              const batch = images.value.slice(i, i + batchSize).map(async (img) => {
                  await detectWatermarkForImage(img);
                  progress.value.current++; 
              });
              await Promise.all(batch);
          }
      } finally {
          isDetecting.value = false;
      }
  }

  async function recalcAllWatermarks() {
      if (images.value.length === 0) return;
      
      const text = watermarkSettings.value.text;
      const baseScale = watermarkSettings.value.scale;
      
      // Process in batches to avoid overwhelming the backend
      const batchSize = 5;
      for (let i = 0; i < images.value.length; i += batchSize) {
          const batch = images.value.slice(i, i + batchSize).map(async (img) => {
              try {
                  const result = await invoke<{x: number, y: number, scale: number}>("layout_watermark", { 
                      path: img.path,
                      text: text,
                      baseScale: baseScale
                  });
                  
                  const idx = images.value.indexOf(img);
                  if (idx >= 0) {
                      setImageManualPosition(idx, result.x, result.y);
                      setImageSetting(idx, 'scale', result.scale);
                  }
              } catch (e) {
                  console.error(`Layout failed for ${img.name}`, e);
              }
          });
          await Promise.all(batch);
      }
  }

  // Internal helper for single image inpainting logic
  async function runInpaintingForImage(img: ImageItem) {
      if (!img.maskStrokes || img.maskStrokes.length === 0) return;
      
      try {
          const newPath = await invoke<string>("run_inpainting", { 
              path: img.path,
              strokes: img.maskStrokes
          });
          
          img.path = newPath;
          img.maskStrokes = [];
      } catch (e) {
          console.error("Inpainting failed", e);
          throw e; // Propagate error
      }
  }

  async function processInpainting(index: number) {
      const img = images.value[index];
      if (!img) return;
      
      isProcessing.value = true;
      progress.value = { current: 0, total: 1 };
      try {
          await runInpaintingForImage(img);
          progress.value.current = 1;
      } catch (e) {
          alert("处理失败: " + e);
      } finally {
          isProcessing.value = false;
      }
  }

  async function processAllInpainting() {
      const candidates = images.value.filter(img => img.maskStrokes && img.maskStrokes.length > 0);
      if (candidates.length === 0) return;

      isProcessing.value = true;
      progress.value = { current: 0, total: candidates.length };
      try {
          // Sequential processing to avoid freezing UI or overloading backend
          for (const img of candidates) {
              await runInpaintingForImage(img);
              progress.value.current++;
          }
          alert("批量处理完成！");
      } catch (e) {
          alert("批量处理部分失败: " + e);
      } finally {
          isProcessing.value = false;
      }
  }

  // Applies the settings from the CURRENT image (or global if not overridden) to ALL images
  // Strategy: Update Global Settings to match current view, and clear individual overrides so everyone follows global.
  function applySettingsToAll() {
      const current = selectedImage.value;
      if (!current) return;

      const newScale = current.scale ?? watermarkSettings.value.scale;
      const newOpacity = current.opacity ?? watermarkSettings.value.opacity;
      const newColor = current.color ?? watermarkSettings.value.color;

      // 1. Update Global
      watermarkSettings.value.scale = newScale;
      watermarkSettings.value.opacity = newOpacity;
      watermarkSettings.value.color = newColor;

      // 2. Clear overrides on ALL images
      images.value.forEach(img => {
          img.scale = undefined;
          img.opacity = undefined;
          img.color = undefined;
      });
  }

  async function selectImage(index: number) {
    if (index < 0 || index >= images.value.length) return;
    selectedIndex.value = index;

    const img = images.value[index];
    if (!img.zcaSuggestion) {
        try {
            const suggestion = await invoke<{x: number, y: number, zone: string}>("get_zca_suggestion", { path: img.path });
            img.zcaSuggestion = suggestion;
        } catch (e) {
            console.error("ZCA failed", e);
        }
    }
  }

  function nextImage() {
    if (images.value.length === 0) return;
    const nextIndex = (selectedIndex.value + 1) % images.value.length;
    selectImage(nextIndex);
  }

  function prevImage() {
    if (images.value.length === 0) return;
    const prevIndex = (selectedIndex.value - 1 + images.value.length) % images.value.length;
    selectImage(prevIndex);
  }

  return {
    images,
    selectedIndex,
    selectedImage,
    editMode,
    watermarkSettings,
    brushSettings,
    isDetecting,
    isProcessing,
    progress,
    setImages,
    selectImage,
    updateWatermarkSettings,
    setImageManualPosition,
    setImageSetting,
    applySettingsToAll,
    addMaskStroke,
    clearMask,
    detectCurrentWatermark,
    detectAllWatermarks,
    recalcAllWatermarks,
    processInpainting,
    processAllInpainting,
    restoreImage,
    nextImage,
    prevImage
  };
});
