import { serve } from 'https://deno.land/std@0.168.0/http/server.ts'
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'
import { wrapHandler, logError } from '../_shared/error-handler.ts'
import {
  fetchAllProducts,
  fetchAllOrders,
  fetchAllCustomers,
  ShopifyProduct,
  ShopifyOrder,
  ShopifyCustomer
} from '../_shared/shopify-client.ts'
import { formatFirstValidPhone, detectCountryCode } from '../_shared/phone-formatter.ts'
import {
  collectionExists,
  createCollection,
  upsertPoints,
  deletePointsByFilter,
  scrollPoints,
  getCollectionName,
  generatePointId,
  initializeStoreCollections,
  generateEmbeddingBatch,
  createProductText,
  createOrderText,
  createCustomerText,
  QdrantPoint,
  QdrantConfig
} from '../_shared/qdrant-client.ts'

const corsHeaders = {
  'Access-Control-Allow-Origin': '*',
  'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
}

// Retry logic for API calls
async function fetchWithRetry<T>(
  fn: () => Promise<T>,
  maxRetries = 3,
  retryDelay = 1000
): Promise<T> {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await fn()
    } catch (error: any) {
      const isLastAttempt = i === maxRetries - 1

      // Check if error is rate limiting
      if (error.message?.includes('429') || error.message?.includes('Rate limit')) {
        if (!isLastAttempt) {
          const delay = retryDelay * Math.pow(2, i) // Exponential backoff
          console.log(`[Shopify] Rate limited, retrying in ${delay}ms...`)
          await new Promise(resolve => setTimeout(resolve, delay))
          continue
        }
      }

      // For other errors or last attempt, throw
      if (isLastAttempt) {
        throw error
      }

      // Retry other errors with shorter delay
      await new Promise(resolve => setTimeout(resolve, retryDelay))
    }
  }

  throw new Error('Max retries exceeded')
}

// Log Qdrant sync operation
async function logQdrantSync(
  supabaseAdmin: any,
  storeId: string,
  syncType: string,
  collectionName: string,
  operation: string,
  itemsProcessed: number,
  itemsSucceeded: number,
  itemsFailed: number,
  startedAt: Date,
  errorMessage?: string
): Promise<void> {
  try {
    await supabaseAdmin
      .from('qdrant_sync_logs')
      .insert({
        store_id: storeId,
        sync_type: syncType,
        collection_name: collectionName,
        operation,
        items_processed: itemsProcessed,
        items_succeeded: itemsSucceeded,
        items_failed: itemsFailed,
        error_message: errorMessage,
        started_at: startedAt.toISOString(),
        completed_at: new Date().toISOString(),
      })
  } catch (error) {
    console.error('[Qdrant] Failed to log sync operation:', error)
  }
}

// Sync products to Qdrant
async function syncProductsToQdrant(
  storeId: string,
  storeName: string,
  products: ShopifyProduct[],
  supabaseAdmin: any,
  config?: QdrantConfig
): Promise<{ synced: number; errors: number }> {
  const startTime = new Date()
  const collectionName = getCollectionName(storeName, 'products')

  console.log(`[Qdrant] Syncing ${products.length} products to ${collectionName}`)

  let synced = 0
  let errors = 0

  try {
    // Ensure collection exists
    if (!(await collectionExists(collectionName, config))) {
      await createCollection(collectionName, [
        { field: 'store_id', type: 'keyword' },
        { field: 'product_id', type: 'keyword' },
        { field: 'platform', type: 'keyword' },
        { field: 'status', type: 'keyword' },
        { field: 'price', type: 'float' },
        { field: 'sku', type: 'keyword' },
      ], config)
    }

    // Get existing product IDs from Qdrant to detect deletions
    const existingPoints = await scrollPoints(collectionName, {
      must: [{ key: 'store_id', match: { value: storeId } }]
    }, 1000, config)

    const existingProductIds = new Set(
      existingPoints.points.map((p: any) => p.payload?.product_id).filter(Boolean)
    )

    // Current product IDs from Shopify
    const currentProductIds = new Set(products.map(p => p.id.toString()))

    // Find deleted products (in Qdrant but not in Shopify)
    const deletedProductIds = Array.from(existingProductIds).filter(
      id => !currentProductIds.has(id)
    )

    // Delete removed products from Qdrant
    if (deletedProductIds.length > 0) {
      console.log(`[Qdrant] Deleting ${deletedProductIds.length} removed products`)
      await deletePointsByFilter(collectionName, {
        must: [
          { key: 'store_id', match: { value: storeId } },
          { key: 'product_id', match: { any: deletedProductIds } }
        ]
      }, config)
    }

    // Generate text representations for all products
    const productTexts = products.map((product) => {
      const primaryVariant = product.variants?.[0]
      return createProductText({
        title: product.title,
        description: product.body_html,
        sku: primaryVariant?.sku,
        vendor: product.vendor,
        product_type: product.product_type,
        tags: product.tags ? product.tags.split(',').map(t => t.trim()) : [],
        variants: product.variants,
        price: primaryVariant?.price,
        status: product.status,
      })
    })

    // Generate embeddings in batch
    console.log(`[Qdrant] Generating embeddings for ${productTexts.length} products...`)
    const embeddings = await generateEmbeddingBatch(productTexts)
    console.log(`[Qdrant] Embeddings generated successfully`)

    // Convert products to Qdrant points with embeddings and comprehensive details
    const points: QdrantPoint[] = products.map((product, index) => {
      const primaryVariant = product.variants?.[0]
      return {
        id: generatePointId('shopify', storeId, product.id),
        vector: embeddings[index],
        payload: {
          // Basic identification
          store_id: storeId,
          product_id: product.id.toString(),
          platform: 'shopify',
          title: product.title,
          handle: product.handle,

          // Vendor and categorization
          vendor: product.vendor || null,
          product_type: product.product_type || null,
          tags: product.tags ? product.tags.split(',').map(t => t.trim()) : [],

          // Descriptions
          description: product.body_html || null,

          // Pricing (from primary variant)
          price: primaryVariant ? parseFloat(primaryVariant.price) : 0,
          compare_at_price: primaryVariant?.compare_at_price ? parseFloat(primaryVariant.compare_at_price) : null,
          currency: primaryVariant?.currency_code || 'USD',

          // Primary variant details
          sku: primaryVariant?.sku || null,
          barcode: primaryVariant?.barcode || null,
          inventory_quantity: primaryVariant?.inventory_quantity || 0,
          inventory_policy: primaryVariant?.inventory_policy || 'deny',

          // All variants (for variable products)
          variants: product.variants?.map((v: any) => ({
            id: v.id,
            title: v.title,
            price: parseFloat(v.price),
            compare_at_price: v.compare_at_price ? parseFloat(v.compare_at_price) : null,
            sku: v.sku,
            barcode: v.barcode,
            inventory_quantity: v.inventory_quantity,
            option1: v.option1,
            option2: v.option2,
            option3: v.option3,
            weight: v.weight,
            weight_unit: v.weight_unit
          })) || [],

          // Product options (Color, Size, etc.)
          options: product.options?.map((opt: any) => ({
            id: opt.id,
            name: opt.name,
            position: opt.position,
            values: opt.values
          })) || [],

          // Images
          images: product.images?.map((img: any) => ({
            id: img.id,
            src: img.src,
            alt: img.alt || product.title,
            position: img.position,
            width: img.width,
            height: img.height
          })) || [],

          // Product status and metadata
          status: product.status,
          published_at: product.published_at || null,
          created_at: product.created_at || null,
          updated_at: product.updated_at || null,

          // Metadata
          synced_at: new Date().toISOString(),
        }
      }
    })

    // Upsert to Qdrant
    await upsertPoints(collectionName, points, config)
    synced = points.length

    await logQdrantSync(
      supabaseAdmin,
      storeId,
      'products',
      collectionName,
      'upsert',
      products.length,
      synced,
      errors,
      startTime
    )

    console.log(`[Qdrant] Products sync complete: ${synced} synced, ${deletedProductIds.length} deleted`)
  } catch (error: any) {
    console.error('[Qdrant] Product sync error:', error)
    errors = products.length
    await logQdrantSync(
      supabaseAdmin,
      storeId,
      'products',
      collectionName,
      'upsert',
      products.length,
      synced,
      errors,
      startTime,
      error.message
    )
  }

  return { synced, errors }
}

// Sync orders to Qdrant
async function syncOrdersToQdrant(
  storeId: string,
  storeName: string,
  orders: ShopifyOrder[],
  supabaseAdmin: any,
  config?: QdrantConfig
): Promise<{ synced: number; errors: number }> {
  const startTime = new Date()
  const collectionName = getCollectionName(storeName, 'orders')

  console.log(`[Qdrant] Syncing ${orders.length} orders to ${collectionName}`)

  let synced = 0
  let errors = 0

  try {
    if (!(await collectionExists(collectionName, config))) {
      await createCollection(collectionName, [
        { field: 'store_id', type: 'keyword' },
        { field: 'order_id', type: 'keyword' },
        { field: 'platform', type: 'keyword' },
        { field: 'financial_status', type: 'keyword' },
        { field: 'total_price', type: 'float' },
        { field: 'customer_email', type: 'keyword' },
      ], config)
    }

    // Generate text representations for all orders
    const orderTexts = orders.map((order) =>
      createOrderText({
        order_number: order.order_number,
        name: order.name,
        customer_name: order.customer ? `${order.customer.first_name || ''} ${order.customer.last_name || ''}`.trim() : null,
        customer_email: order.customer?.email || order.email,
        customer_phone: order.customer?.phone || order.billing_address?.phone,
        email: order.email,
        phone: order.customer?.phone || order.billing_address?.phone,
        billing_address: order.billing_address,
        shipping_address: order.shipping_address,
        total_price: order.current_total_price,
        currency: order.currency,
        financial_status: order.financial_status,
        fulfillment_status: order.fulfillment_status,
        line_items: order.line_items,
        note: order.note,
      })
    )

    // Generate embeddings in batch
    console.log(`[Qdrant] Generating embeddings for ${orderTexts.length} orders...`)
    const embeddings = await generateEmbeddingBatch(orderTexts)
    console.log(`[Qdrant] Embeddings generated successfully`)

    // Convert orders to Qdrant points with embeddings
    const points: QdrantPoint[] = orders.map((order, index) => ({
      id: generatePointId('shopify', storeId, order.id),
      vector: embeddings[index],
      payload: {
        store_id: storeId,
        order_id: order.id.toString(),
        platform: 'shopify',
        order_number: order.order_number.toString(),
        name: order.name,
        email: order.email || null,
        customer_name: order.customer ? `${order.customer.first_name || ''} ${order.customer.last_name || ''}`.trim() : null,
        customer_email: order.customer?.email || order.email || null,
        customer_phone: order.customer?.phone || order.billing_address?.phone || null,
        phone: order.customer?.phone || order.billing_address?.phone || null,
        financial_status: order.financial_status,
        fulfillment_status: order.fulfillment_status || null,
        total_price: parseFloat(order.current_total_price) || 0,
        currency: order.currency,
        billing_address: order.billing_address || null,
        billing_city: order.billing_address?.city || null,
        billing_country: order.billing_address?.country || null,
        shipping_address: order.shipping_address || null,
        shipping_city: order.shipping_address?.city || null,
        shipping_country: order.shipping_address?.country || null,
        note: order.note || null,
        synced_at: new Date().toISOString(),
      }
    }))

    await upsertPoints(collectionName, points, config)
    synced = points.length

    await logQdrantSync(
      supabaseAdmin,
      storeId,
      'orders',
      collectionName,
      'upsert',
      orders.length,
      synced,
      errors,
      startTime
    )

    console.log(`[Qdrant] Orders sync complete: ${synced} synced`)
  } catch (error: any) {
    console.error('[Qdrant] Order sync error:', error)
    errors = orders.length
    await logQdrantSync(
      supabaseAdmin,
      storeId,
      'orders',
      collectionName,
      'upsert',
      orders.length,
      synced,
      errors,
      startTime,
      error.message
    )
  }

  return { synced, errors }
}

// Sync customers to Qdrant
async function syncCustomersToQdrant(
  storeId: string,
  storeName: string,
  customers: ShopifyCustomer[],
  supabaseAdmin: any,
  config?: QdrantConfig
): Promise<{ synced: number; errors: number }> {
  const startTime = new Date()
  const collectionName = getCollectionName(storeName, 'customers')

  console.log(`[Qdrant] Syncing ${customers.length} customers to ${collectionName}`)

  let synced = 0
  let errors = 0

  try {
    if (!(await collectionExists(collectionName, config))) {
      await createCollection(collectionName, [
        { field: 'store_id', type: 'keyword' },
        { field: 'customer_id', type: 'keyword' },
        { field: 'platform', type: 'keyword' },
        { field: 'email', type: 'keyword' },
      ], config)
    }

    // Generate text representations for all customers
    const customerTexts = customers.map((customer) =>
      createCustomerText({
        first_name: customer.first_name,
        last_name: customer.last_name,
        email: customer.email,
        phone: customer.phone || customer.default_address?.phone,
        default_address: customer.default_address,
        addresses: customer.addresses,
        orders_count: customer.orders_count,
        total_spent: customer.total_spent,
        currency: customer.currency,
        state: customer.state,
        accepts_marketing: customer.accepts_marketing,
        tags: customer.tags ? customer.tags.split(',').map(t => t.trim()) : [],
      })
    )

    // Generate embeddings in batch
    console.log(`[Qdrant] Generating embeddings for ${customerTexts.length} customers...`)
    const embeddings = await generateEmbeddingBatch(customerTexts)
    console.log(`[Qdrant] Embeddings generated successfully`)

    // Convert customers to Qdrant points with embeddings
    const points: QdrantPoint[] = customers.map((customer, index) => ({
      id: generatePointId('shopify', storeId, customer.id),
      vector: embeddings[index],
      payload: {
        store_id: storeId,
        customer_id: customer.id.toString(),
        platform: 'shopify',
        email: customer.email,
        first_name: customer.first_name || null,
        last_name: customer.last_name || null,
        phone: customer.phone || customer.default_address?.phone || null,
        default_address: customer.default_address || null,
        city: customer.default_address?.city || null,
        country: customer.default_address?.country || null,
        addresses: customer.addresses || [],
        orders_count: customer.orders_count || 0,
        total_spent: parseFloat(customer.total_spent) || 0,
        currency: customer.currency || 'USD',
        state: customer.state,
        accepts_marketing: customer.accepts_marketing || false,
        tags: customer.tags ? customer.tags.split(',').map(t => t.trim()) : [],
        synced_at: new Date().toISOString(),
      }
    }))

    await upsertPoints(collectionName, points, config)
    synced = points.length

    await logQdrantSync(
      supabaseAdmin,
      storeId,
      'customers',
      collectionName,
      'upsert',
      customers.length,
      synced,
      errors,
      startTime
    )

    console.log(`[Qdrant] Customers sync complete: ${synced} synced`)
  } catch (error: any) {
    console.error('[Qdrant] Customer sync error:', error)
    errors = customers.length
    await logQdrantSync(
      supabaseAdmin,
      storeId,
      'customers',
      collectionName,
      'upsert',
      customers.length,
      synced,
      errors,
      startTime,
      error.message
    )
  }

  return { synced, errors }
}

// Sync products from Shopify
async function syncProducts(
  storeId: string,
  storeName: string,
  supabaseAdmin: any,
  qdrantEnabled: boolean,
  canSyncProducts: boolean,
  qdrantConfig?: QdrantConfig
): Promise<{ synced: number; errors: number; qdrant?: { synced: number; errors: number } }> {
  console.log('[Shopify] Syncing products...')
  let synced = 0
  let errors = 0

  if (!canSyncProducts) {
    console.log('[Shopify] Product sync disabled by store permissions')
    return { synced: 0, errors: 0 }
  }

  try {
    const products = await fetchWithRetry(() => fetchAllProducts(storeId))

    if (!products || products.length === 0) {
      console.log('[Shopify] No products found')
      return { synced: 0, errors: 0 }
    }

    // Get store details for currency
    const { data: store } = await supabaseAdmin
      .from('stores')
      .select('alt_data')
      .eq('id', storeId)
      .single()

    const currency = store?.alt_data?.currency || 'USD'

    // Map and upsert products to SQL cache with exclusion status
    const productsToCache = await Promise.all(
      products.map(async (product: ShopifyProduct) => {
        const primaryVariant = product.variants?.[0]

        // Build categories array from product_type and vendor
        const categories: any[] = []
        if (product.product_type) {
          categories.push({
            id: product.product_type.toLowerCase().replace(/\s+/g, '-'),
            name: product.product_type
          })
        }

        // Check if product is excluded by category using database function
        const { data: categoryExcluded, error: categoryExclusionError } = await supabaseAdmin
          .rpc('is_product_excluded_by_category', {
            p_store_id: storeId,
            p_categories: categories,
            p_platform: 'shopify'
          })

        if (categoryExclusionError) {
          console.error(`[Shopify] Error checking category exclusion for product ${product.id}:`, categoryExclusionError)
        }

        // Check if product is individually excluded from cache
        const { data: existingProduct, error: existingError } = await supabaseAdmin
          .from('shopify_products_cache')
          .select('excluded')
          .eq('store_id', storeId)
          .eq('product_id', product.id.toString())
          .single()

        if (existingError && existingError.code !== 'PGRST116') {
          console.error(`[Shopify] Error checking existing product exclusion for ${product.id}:`, existingError)
        }

        // Product is excluded if:
        // 1. Excluded by category, OR
        // 2. Individually excluded (from existing cache record)
        const isExcluded = categoryExcluded || (existingProduct?.excluded === true)

        return {
          store_id: storeId,
          product_id: product.id.toString(),
          name: product.title, // Map title to name for consistency
          sku: primaryVariant?.sku || null,
          categories: categories,
          excluded: isExcluded,
          last_synced_at: new Date().toISOString()
        }
      })
    )

    // Batch upsert in chunks of 100 to avoid payload size limits
    const chunkSize = 100
    for (let i = 0; i < productsToCache.length; i += chunkSize) {
      const chunk = productsToCache.slice(i, i + chunkSize)

      const { error: upsertError } = await supabaseAdmin
        .from('shopify_products_cache')
        .upsert(chunk, {
          onConflict: 'store_id,product_id'
        })

      if (upsertError) {
        console.error('[Shopify] Error caching products chunk:', upsertError)
        errors += chunk.length
      } else {
        synced += chunk.length
        console.log(`[Shopify] Cached ${chunk.length} products (${synced}/${productsToCache.length})`)
      }
    }

    console.log(`[Shopify] Products sync complete: ${synced} synced, ${errors} errors`)

    // Handle Qdrant sync with exclusion logic
    let qdrantResult
    if (qdrantEnabled) {
      // Get excluded product IDs for Qdrant cleanup
      const excludedProductIds = productsToCache
        .filter(p => p.excluded)
        .map(p => p.product_id)

      // Filter products for Qdrant sync (only non-excluded)
      const productsForQdrant = products.filter(product => {
        const productCacheItem = productsToCache.find(p => p.product_id === product.id.toString())
        return productCacheItem && !productCacheItem.excluded
      })

      // Delete excluded products from Qdrant
      if (excludedProductIds.length > 0) {
        console.log(`[Shopify] Deleting ${excludedProductIds.length} excluded products from Qdrant...`)
        try {
          const { deletePointsByFilter, getCollectionName } = await import('../_shared/qdrant-client.ts')
          const collectionName = getCollectionName(storeName, 'products')
          await deletePointsByFilter(
            collectionName,
            {
              key: 'product_id',
              match: { any: excludedProductIds }
            }
          )
          console.log(`[Shopify] Deleted excluded products from Qdrant successfully`)
        } catch (qdrantDeleteError) {
          console.error('[Shopify] Error deleting excluded products from Qdrant:', qdrantDeleteError)
        }
      }

      // Sync remaining (non-excluded) products to Qdrant
      qdrantResult = await syncProductsToQdrant(storeId, storeName, productsForQdrant, supabaseAdmin, qdrantConfig)
      console.log(`[Shopify] Qdrant sync complete: ${qdrantResult.synced} synced, ${qdrantResult.errors} errors, ${excludedProductIds.length} excluded`)
    }

    return { synced, errors, qdrant: qdrantResult }
  } catch (error) {
    console.error('[Shopify] Product sync error:', error)
    errors++
    return { synced, errors }
  }
}

// Sync orders from Shopify
async function syncOrders(
  storeId: string,
  storeName: string,
  supabaseAdmin: any,
  countryCode: string,
  qdrantEnabled: boolean,
  canSyncOrders: boolean,
  qdrantConfig?: QdrantConfig
): Promise<{ synced: number; errors: number; qdrant?: { synced: number; errors: number } }> {
  console.log('[Shopify] Syncing orders...')
  let synced = 0
  let errors = 0

  if (!canSyncOrders) {
    console.log('[Shopify] Order sync disabled by store permissions')
    return { synced: 0, errors: 0 }
  }

  try {
    const orders = await fetchWithRetry(() => fetchAllOrders(storeId))

    if (!orders || orders.length === 0) {
      console.log('[Shopify] No orders found')
      return { synced: 0, errors: 0 }
    }

    // Map and upsert orders
    const ordersToCache = orders.map((order: ShopifyOrder) => ({
      store_id: storeId,
      shopify_order_id: order.id.toString(),
      order_number: order.order_number.toString(),
      name: order.name,
      email: order.email || null,
      phone: formatFirstValidPhone([
        order.customer?.phone,
        order.billing_address?.phone,
        order.shipping_address?.phone
      ], countryCode),
      financial_status: order.financial_status,
      fulfillment_status: order.fulfillment_status || null,
      total_price: parseFloat(order.current_total_price) || 0,
      subtotal_price: parseFloat(order.current_subtotal_price) || 0,
      total_tax: parseFloat(order.current_total_tax) || 0,
      currency: order.currency,
      customer_name: order.customer ? `${order.customer.first_name || ''} ${order.customer.last_name || ''}`.trim() : null,
      customer_email: order.customer?.email || order.email || null,
      line_items: order.line_items || [],
      billing_address: order.billing_address || null,
      shipping_address: order.shipping_address || null,
      note: order.note || null,
      tags: order.tags ? order.tags.split(',').map(t => t.trim()) : [],
      order_created_at: order.created_at,
      order_updated_at: order.updated_at,
      raw_data: order,
      last_synced_at: new Date().toISOString()
    }))

    // Batch upsert in chunks of 100
    const chunkSize = 100
    for (let i = 0; i < ordersToCache.length; i += chunkSize) {
      const chunk = ordersToCache.slice(i, i + chunkSize)

      const { error: upsertError } = await supabaseAdmin
        .from('shopify_orders_cache')
        .upsert(chunk, {
          onConflict: 'store_id,shopify_order_id'
        })

      if (upsertError) {
        console.error('[Shopify] Error caching orders chunk:', upsertError)
        errors += chunk.length
      } else {
        synced += chunk.length
        console.log(`[Shopify] Cached ${chunk.length} orders (${synced}/${ordersToCache.length})`)
      }
    }

    console.log(`[Shopify] Orders sync complete: ${synced} synced, ${errors} errors`)

    // Sync to Qdrant if enabled
    let qdrantResult
    if (qdrantEnabled) {
      qdrantResult = await syncOrdersToQdrant(storeId, storeName, orders, supabaseAdmin, qdrantConfig)
    }

    return { synced, errors, qdrant: qdrantResult }
  } catch (error) {
    console.error('[Shopify] Order sync error:', error)
    errors++
    return { synced, errors }
  }
}

// Sync customers from Shopify
async function syncCustomers(
  storeId: string,
  storeName: string,
  supabaseAdmin: any,
  countryCode: string,
  qdrantEnabled: boolean,
  canSyncCustomers: boolean,
  qdrantConfig?: QdrantConfig
): Promise<{ synced: number; errors: number; qdrant?: { synced: number; errors: number } }> {
  console.log('[Shopify] Syncing customers...')
  let synced = 0
  let errors = 0

  if (!canSyncCustomers) {
    console.log('[Shopify] Customer sync disabled by store permissions')
    return { synced: 0, errors: 0 }
  }

  try {
    const customers = await fetchWithRetry(() => fetchAllCustomers(storeId))

    if (!customers || customers.length === 0) {
      console.log('[Shopify] No customers found')
      return { synced: 0, errors: 0 }
    }

    // Map and upsert customers
    const customersToCache = customers.map((customer: ShopifyCustomer) => ({
      store_id: storeId,
      shopify_customer_id: customer.id.toString(),
      email: customer.email,
      first_name: customer.first_name || null,
      last_name: customer.last_name || null,
      phone: formatFirstValidPhone([
        customer.phone,
        customer.default_address?.phone
      ], countryCode),
      accepts_marketing: customer.accepts_marketing || false,
      orders_count: customer.orders_count || 0,
      total_spent: parseFloat(customer.total_spent) || 0,
      currency: customer.currency || 'USD',
      state: customer.state,
      addresses: customer.addresses || [],
      default_address: customer.default_address || null,
      tags: customer.tags ? customer.tags.split(',').map(t => t.trim()) : [],
      note: customer.note || null,
      customer_created_at: customer.created_at,
      customer_updated_at: customer.updated_at,
      raw_data: customer,
      last_synced_at: new Date().toISOString()
    }))

    // Batch upsert in chunks of 100
    const chunkSize = 100
    for (let i = 0; i < customersToCache.length; i += chunkSize) {
      const chunk = customersToCache.slice(i, i + chunkSize)

      const { error: upsertError } = await supabaseAdmin
        .from('shopify_customers_cache')
        .upsert(chunk, {
          onConflict: 'store_id,shopify_customer_id'
        })

      if (upsertError) {
        console.error('[Shopify] Error caching customers chunk:', upsertError)
        errors += chunk.length
      } else {
        synced += chunk.length
        console.log(`[Shopify] Cached ${chunk.length} customers (${synced}/${customersToCache.length})`)
      }
    }

    console.log(`[Shopify] Customers sync complete: ${synced} synced, ${errors} errors`)

    // Sync to Qdrant if enabled
    let qdrantResult
    if (qdrantEnabled) {
      qdrantResult = await syncCustomersToQdrant(storeId, storeName, customers, supabaseAdmin, qdrantConfig)
    }

    return { synced, errors, qdrant: qdrantResult }
  } catch (error) {
    console.error('[Shopify] Customer sync error:', error)
    errors++
    return { synced, errors }
  }
}

serve(wrapHandler('shopify-sync', async (req) => {
  if (req.method === 'OPTIONS') {
    return new Response('ok', { headers: corsHeaders })
  }

  try {
    const url = new URL(req.url)
    const storeId = url.searchParams.get('store_id')
    const syncType = url.searchParams.get('type') || 'all' // all, products, orders, customers

    if (!storeId) {
      return new Response(
        JSON.stringify({ error: 'store_id parameter is required' }),
        { status: 400, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
      )
    }

    // Verify user authorization
    const authHeader = req.headers.get('authorization')
    if (!authHeader) {
      return new Response(
        JSON.stringify({ error: 'No authorization header' }),
        { status: 401, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
      )
    }

    const token = authHeader.replace('Bearer ', '')
    const supabaseUrl = Deno.env.get('SUPABASE_URL')!
    const supabaseKey = Deno.env.get('SUPABASE_ANON_KEY')!
    const supabase = createClient(supabaseUrl, supabaseKey)

    const { data: { user }, error: userError } = await supabase.auth.getUser(token)

    if (userError || !user) {
      return new Response(
        JSON.stringify({ error: 'Invalid token' }),
        { status: 401, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
      )
    }

    // Verify store ownership and get permissions
    const supabaseServiceKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!
    const supabaseAdmin = createClient(supabaseUrl, supabaseServiceKey)

    const { data: store, error: storeError } = await supabaseAdmin
      .from('stores')
      .select('id, platform_name, store_name, store_url, qdrant_sync_enabled, qdrant_url, qdrant_api_key')
      .eq('id', storeId)
      .eq('user_id', user.id)
      .eq('platform_name', 'shopify')
      .single()

    if (storeError || !store) {
      return new Response(
        JSON.stringify({ error: 'Shopify store not found or access denied' }),
        { status: 404, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
      )
    }

    // Check data access permissions
    // Get access policies from store_sync_config
    const { data: syncConfig } = await supabaseAdmin
      .from('store_sync_config')
      .select('products_access_policy, orders_access_policy, customers_access_policy')
      .eq('store_id', storeId)
      .single()

    // Only sync if policy is 'sync' (not 'api_only' or 'not_allowed')
    const canSyncProducts = syncConfig?.products_access_policy === 'sync'
    const canSyncOrders = syncConfig?.orders_access_policy === 'sync'
    const canSyncCustomers = syncConfig?.customers_access_policy === 'sync'
    const qdrantEnabled = store.qdrant_sync_enabled !== false

    // Prepare Qdrant configuration (per-store override or defaults from environment)
    const qdrantConfig = (store.qdrant_url || store.qdrant_api_key) ? {
      url: store.qdrant_url || undefined,
      apiKey: store.qdrant_api_key || undefined,
    } : undefined

    console.log('[Shopify] Sync permissions:', {
      products: canSyncProducts,
      productsPolicy: syncConfig?.products_access_policy || 'not_configured',
      orders: canSyncOrders,
      ordersPolicy: syncConfig?.orders_access_policy || 'not_configured',
      customers: canSyncCustomers,
      customersPolicy: syncConfig?.customers_access_policy || 'not_configured',
      qdrant: qdrantEnabled,
      qdrantCustomConfig: qdrantConfig ? 'yes' : 'no (using defaults)'
    })

    // Initialize Qdrant collections if enabled
    if (qdrantEnabled) {
      try {
        await initializeStoreCollections(
          store.store_name,
          canSyncOrders,
          canSyncCustomers,
          qdrantConfig
        )
      } catch (error) {
        console.error('[Qdrant] Failed to initialize collections:', error)
      }
    }

    // Detect country code from store URL for phone formatting
    const countryCode = detectCountryCode(store.store_url)
    console.log(`[Shopify] Detected country code: ${countryCode} for store: ${store.store_name}`)

    console.log(`[Shopify] Starting ${syncType} sync for store: ${store.store_name}`)

    const results: any = {
      store_id: storeId,
      store_name: store.store_name,
      sync_type: syncType,
      started_at: new Date().toISOString()
    }

    // Perform sync based on type
    if (syncType === 'all' || syncType === 'products') {
      results.products = await syncProducts(storeId, store.store_name, supabaseAdmin, qdrantEnabled, canSyncProducts, qdrantConfig)
    }

    if (syncType === 'all' || syncType === 'orders') {
      results.orders = await syncOrders(storeId, store.store_name, supabaseAdmin, countryCode, qdrantEnabled, canSyncOrders, qdrantConfig)
    }

    if (syncType === 'all' || syncType === 'customers') {
      results.customers = await syncCustomers(storeId, store.store_name, supabaseAdmin, countryCode, qdrantEnabled, canSyncCustomers, qdrantConfig)
    }

    results.completed_at = new Date().toISOString()

    console.log(`[Shopify] Sync completed for store: ${store.store_name}`)
    console.log(`[Shopify] Results:`, JSON.stringify(results, null, 2))

    return new Response(
      JSON.stringify({
        success: true,
        message: 'Sync completed successfully',
        results
      }),
      { status: 200, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
    )

  } catch (error: any) {
    console.error('[Shopify] Sync error:', error)
    return new Response(
      JSON.stringify({
        success: false,
        error: error.message || 'Sync failed'
      }),
      { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
    )
  }
}))
