'use server'

import { createClient } from '@/lib/supabase/server'
import { revalidatePath } from 'next/cache'
import { Category, Product, ProductModule } from '../types'
import { randomUUID } from 'crypto'

export async function getProducts() {
  const supabase = await createClient()
  const { data, error } = await supabase
    .from('products')
    .select('*, category:categories(*), modules:product_modules(*)')
    .order('created_at', { ascending: false })

  if (error) throw error
  return data as Product[]
}

export async function getCategories() {
  const supabase = await createClient()
  const { data, error } = await supabase
    .from('categories')
    .select('*')
    .order('sort_order', { ascending: true })

  if (error) throw error
  return data as Category[]
}

export async function createCategory(category: Omit<Category, 'id' | 'created_at'>) {
  const supabase = await createClient()
  const { data, error } = await supabase
    .from('categories')
    .insert([category])
    .select()
    .single()

  if (error) throw error
  revalidatePath('/admin/categories')
  revalidatePath('/order')
  return data
}

export async function updateCategory(id: string, category: Partial<Category>) {
  const supabase = await createClient()
  const { error } = await supabase
    .from('categories')
    .update(category)
    .eq('id', id)

  if (error) throw error
  revalidatePath('/admin/categories')
  revalidatePath('/order')
}

export async function deleteCategory(id: string) {
  const supabase = await createClient()
  const { error } = await supabase
    .from('categories')
    .delete()
    .eq('id', id)

  if (error) throw error
  revalidatePath('/admin/categories')
  revalidatePath('/order')
}

export async function createProduct(
  product: Omit<Product, 'id' | 'created_at' | 'updated_at'>,
  modules: Omit<ProductModule, 'product_id' | 'created_at'>[]
) {
  const supabase = await createClient()

  // Start a transaction-like approach (Supabase doesn't have cross-table transactions easily in one call via JS client without RPC)
  const { data: newProduct, error: productError } = await supabase
    .from('products')
    .insert([product])
    .select()
    .single()

  if (productError) throw productError

  if (modules.length > 0) {
    const modulesWithId = modules.map(m => ({
      id: m.id || randomUUID(),
      product_id: newProduct.id,
      name: m.name,
      description: m.description || null,
      price: m.price,
      requirements: m.requirements || [],
      exclusions: m.exclusions || [],
      has_quantity: m.has_quantity ?? false,
    }))
    const { error: modulesError } = await supabase
      .from('product_modules')
      .insert(modulesWithId)

    if (modulesError) throw modulesError
  }

  revalidatePath('/admin/products')
  revalidatePath('/order')
  return newProduct
}

export async function updateProduct(id: string, product: Partial<Product>, modules: any[]) {
  const supabase = await createClient()

  const { error: productError } = await supabase
    .from('products')
    .update(product)
    .eq('id', id)

  if (productError) throw productError

  // For modules, a simple approach is to delete and re-insert or use upsert if they have IDs
  // To keep it simple: Delete all modules and re-insert the current list
  await supabase.from('product_modules').delete().eq('product_id', id)

  if (modules.length > 0) {
    const modulesWithId = modules.map(m => ({
      id: m.id || randomUUID(),
      product_id: id,
      name: m.name,
      description: m.description || null,
      price: m.price,
      requirements: m.requirements || [],
      exclusions: m.exclusions || [],
      has_quantity: m.has_quantity ?? false,
    }))
    const { error: modulesError } = await supabase
      .from('product_modules')
      .insert(modulesWithId)

    if (modulesError) throw modulesError
  }


  revalidatePath('/admin/products')
  revalidatePath('/order')
}

export async function deleteProduct(id: string) {
  const supabase = await createClient()
  const { error } = await supabase.from('products').delete().eq('id', id)
  if (error) throw error

  revalidatePath('/admin/products')
  revalidatePath('/order')
}

export async function transferModules(
  sourceProductId: string,
  targetProductId: string,
  mode: 'overwrite' | 'append'
) {
  const supabase = await createClient()

  // 1. Fetch modules of source product
  const { data: sourceModules, error: fetchError } = await supabase
    .from('product_modules')
    .select('*')
    .eq('product_id', sourceProductId)

  if (fetchError) throw fetchError
  if (!sourceModules || sourceModules.length === 0) return

  // 2. If overwrite, delete existing modules of target product
  if (mode === 'overwrite') {
    const { error: deleteError } = await supabase
      .from('product_modules')
      .delete()
      .eq('product_id', targetProductId)
    if (deleteError) throw deleteError
  }

  // 3. Map IDs to new UUIDs and fix requirements/exclusions
  const idMap: Record<string, string> = {}
  sourceModules.forEach(m => {
    idMap[m.id] = randomUUID()
  })

  const newModules = sourceModules.map(m => {
    const newId = idMap[m.id]
    const requirements = (m.requirements || []).map((id: string) => idMap[id] || id)
    const exclusions = (m.exclusions || []).map((id: string) => idMap[id] || id)
    return {
      id: newId,
      product_id: targetProductId,
      name: m.name,
      description: m.description,
      price: m.price,
      requirements,
      exclusions,
      has_quantity: m.has_quantity ?? false,
    }
  })

  // 4. Insert into DB
  const { error: insertError } = await supabase
    .from('product_modules')
    .insert(newModules)

  if (insertError) throw insertError

  revalidatePath('/admin/products')
  revalidatePath('/order')
}
