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 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 = [];
      }
  }

  async function detectAllWatermarks() {
      if (images.value.length === 0) return;

      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 {
                  // @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) {
                     if (!img.maskStrokes) img.maskStrokes = [];
                     
                     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);
              }
          });
          await Promise.all(batch);
      }
  }

  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
                  });
                  
                  // Find index again just in case sort changed? No, we rely on reference or index.
                  // Img is reference. But setter needs index. 
                  // Let's use image reference finding.
                  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);
      }
  }

  async function processInpainting(index: number) {
      const img = images.value[index];
      if (!img || !img.maskStrokes || img.maskStrokes.length === 0) return;
      
      try {
          const newPath = await invoke<string>("run_inpainting", { 
              path: img.path,
              strokes: img.maskStrokes
          });
          
          // Update the image path to point to the processed version
          // NOTE: This updates the "Source" of the image in the store.
          // In a real app, maybe we keep original? But for "Wizard", modifying is the goal.
          img.path = newPath;
          // Clear mask after success
          img.maskStrokes = [];
          
          // Force UI refresh (thumbnail) - might be needed
          // Generate new thumb?
          // Since path changed, converting src should trigger reload.
          
      } catch (e) {
          console.error("Inpainting failed", e);
          alert("Inpainting failed: " + e);
      }
  }

  // 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);
        }
    }
  }

  return {
    images,
    selectedIndex,
    selectedImage,
    editMode,
    watermarkSettings,
    brushSettings,
    setImages,
    selectImage,
    updateWatermarkSettings,
    setImageManualPosition,
    setImageSetting,
    applySettingsToAll,
    addMaskStroke,
    clearMask,
    detectAllWatermarks,
    recalcAllWatermarks,
    processInpainting,
    restoreImage
  };
});
