import { defineStore } from 'pinia'
import { ref } from 'vue'
import type { Image, CropParams, StickerLayer, SharedImage, SharedImagePage } from '@/types'

interface UploadExtras {
  original?: File
  cropParams?: CropParams
  stickerState?: StickerLayer[]
  cropOrientation?: 'landscape' | 'portrait'
}

export const useImagesStore = defineStore('images', () => {
  const images       = ref<Image[]>([])
  const loading      = ref(false)
  const error        = ref<string | null>(null)
  const pendingCount = ref(0)

  /**
   * Fetch the image list. Pass `silent: true` from background refreshes
   * (pull-to-refresh) so the loading spinner doesn't blink and replace the
   * existing grid mid-fetch.
   */
  async function fetchImages(opts: { silent?: boolean } = {}) {
    if (!opts.silent) loading.value = true
    error.value   = null
    try {
      const res = await fetch('/api/images')
      if (!res.ok) throw new Error('Failed to load images')
      images.value = await res.json()
    } catch (e) {
      error.value = e instanceof Error ? e.message : 'Unknown error'
    } finally {
      loading.value = false
    }
  }

  async function uploadImage(file: File, extras?: UploadExtras): Promise<Image> {
    const form = new FormData()
    form.append('file', file)
    if (extras?.original)         form.append('original',        extras.original)
    if (extras?.cropParams)       form.append('cropParams',      JSON.stringify(extras.cropParams))
    if (extras?.stickerState)     form.append('stickerState',    JSON.stringify(extras.stickerState))
    if (extras?.cropOrientation)  form.append('cropOrientation', extras.cropOrientation)

    const res = await fetch('/api/images', { method: 'POST', body: form })
    if (!res.ok) {
      const body = await res.json().catch(() => ({}))
      throw new Error(body.error ?? 'Upload failed')
    }
    const image: Image = await res.json()
    images.value.unshift(image)
    return image
  }

  async function reprocessImage(imageId: number, composited: File, extras?: { cropParams?: CropParams; stickerState?: StickerLayer[]; cropOrientation?: 'landscape' | 'portrait' }): Promise<Image> {
    const form = new FormData()
    form.append('file', composited)
    if (extras?.cropParams)      form.append('cropParams',      JSON.stringify(extras.cropParams))
    if (extras?.stickerState)    form.append('stickerState',    JSON.stringify(extras.stickerState))
    if (extras?.cropOrientation) form.append('cropOrientation', extras.cropOrientation)

    const res = await fetch(`/api/images/${imageId}/reprocess`, { method: 'POST', body: form })
    if (!res.ok) {
      const body = await res.json().catch(() => ({}))
      throw new Error(body.error ?? 'Reprocess failed')
    }
    const updated: Image = await res.json()
    const idx = images.value.findIndex(i => i.id === imageId)
    if (idx !== -1) images.value[idx] = updated
    return updated
  }

  async function deleteImage(id: number): Promise<void> {
    const res = await fetch(`/api/images/${id}`, { method: 'DELETE' })
    if (!res.ok) throw new Error('Delete failed')
    images.value = images.value.filter(img => img.id !== id)
  }

  async function setApproval(imageId: number, deviceId: number, approved: boolean): Promise<void> {
    const method = approved ? 'POST' : 'DELETE'
    const res = await fetch(`/api/images/${imageId}/approve/${deviceId}`, { method })
    if (!res.ok) throw new Error('Failed to update approval')
    const updated: Image = await res.json()
    const idx = images.value.findIndex(i => i.id === imageId)
    if (idx !== -1) images.value[idx] = updated
  }

  async function fetchSharedImages(status?: string, page = 1, limit = 20): Promise<SharedImagePage> {
    const params = new URLSearchParams({ page: String(page), limit: String(limit) })
    if (status) params.set('status', status)
    const res = await fetch(`/api/shared-images?${params}`)
    if (!res.ok) throw new Error('Failed to load shared images')
    return res.json()
  }

  async function fetchPendingCount(): Promise<void> {
    const res = await fetch('/api/shared-images/pending-count')
    if (res.ok) {
      const data = await res.json()
      pendingCount.value = data.count
    }
  }

  async function approveShared(sharedId: number, deviceIds: number[]): Promise<SharedImage> {
    const res = await fetch(`/api/shared-images/${sharedId}/approve`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ deviceIds }),
    })
    if (!res.ok) throw new Error('Failed to approve')
    if (pendingCount.value > 0) pendingCount.value--
    return res.json()
  }

  async function declineShared(sharedId: number): Promise<SharedImage> {
    const res = await fetch(`/api/shared-images/${sharedId}/decline`, { method: 'POST' })
    if (!res.ok) throw new Error('Failed to decline')
    if (pendingCount.value > 0) pendingCount.value--
    return res.json()
  }

  async function shareImage(imageId: number, recipientEmail: string): Promise<void> {
    const res = await fetch(`/api/images/${imageId}/share`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ recipientEmail }),
    })
    if (!res.ok) {
      const body = await res.json().catch(() => ({}))
      throw new Error(body.error ?? 'Failed to share')
    }
  }

  return {
    images, loading, error, pendingCount,
    fetchImages, uploadImage, reprocessImage, deleteImage, setApproval,
    fetchSharedImages, fetchPendingCount, approveShared, declineShared, shareImage,
  }
})
