import { serve } from 'https://deno.land/std@0.168.0/http/server.ts'
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'

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

// Helper function to convert ArrayBuffer to hex string
function bufferToHex(buffer: ArrayBuffer): string {
  const byteArray = new Uint8Array(buffer);
  return Array.from(byteArray)
    .map((byte) => byte.toString(16).padStart(2, "0"))
    .join("");
}

// Calculate HMAC-SHA256 using Deno's native crypto.subtle API
async function calculateHmacSha256(secret: string, message: string): Promise<string> {
  const encoder = new TextEncoder();
  const keyData = encoder.encode(secret);
  const key = await crypto.subtle.importKey(
    "raw",
    keyData,
    { name: "HMAC", hash: { name: "SHA-256" } },
    false,
    ["sign"]
  );
  const messageData = encoder.encode(message);
  const signature = await crypto.subtle.sign("HMAC", key, messageData);
  return bufferToHex(signature);
}

// Validate HMAC signature from ShopRenter
// IMPORTANT: Preserve original parameter order from URL (same as oauth-shoprenter-callback)
async function validateHMAC(rawQueryString: string, clientSecret: string, clientId: string): Promise<boolean> {
  if (!clientSecret) {
    console.error('[ShopRenter] Client secret is empty or undefined')
    return false
  }

  // Parse the query string to get the hmac value
  const params = new URLSearchParams(rawQueryString)
  const hmacValue = params.get('hmac')
  if (!hmacValue) {
    console.error('[ShopRenter] HMAC missing from request')
    return false
  }

  // Build the params string by preserving the original order from the URL
  // and excluding the hmac and app_url parameters
  const paramsWithoutHmac = rawQueryString
    .split('&')
    .filter(param => {
      const key = param.split('=')[0]
      return key !== 'hmac' && key !== 'app_url'
    })
    .join('&')

  console.log(`[ShopRenter] HMAC validation - params (original order): ${paramsWithoutHmac}`)
  console.log(`[ShopRenter] HMAC validation - client secret length: ${clientSecret.length}`)

  // Calculate HMAC using Deno's native crypto.subtle API (SHA-256)
  const calculatedHmacWithSecret = await calculateHmacSha256(clientSecret, paramsWithoutHmac)

  console.log(`[ShopRenter] HMAC validation - received hmac: ${hmacValue}`)
  console.log(`[ShopRenter] HMAC validation - calculated hmac (with secret): ${calculatedHmacWithSecret}`)

  // Compare HMACs
  const resultWithSecret = calculatedHmacWithSecret === hmacValue
  console.log(`[ShopRenter] HMAC validation result (with secret): ${resultWithSecret}`)

  if (resultWithSecret) {
    return true
  }

  // Fallback: try with Client ID (in case of documentation confusion)
  const calculatedHmacWithId = await calculateHmacSha256(clientId, paramsWithoutHmac)
  console.log(`[ShopRenter] HMAC validation - calculated hmac (with id): ${calculatedHmacWithId}`)

  const resultWithId = calculatedHmacWithId === hmacValue
  console.log(`[ShopRenter] HMAC validation result (with id): ${resultWithId}`)

  return resultWithId
}

// Validate timestamp - lenient validation (logs warnings but doesn't reject)
// HMAC validation is the primary security check
function validateTimestamp(timestamp: string, maxAgeSeconds = 300): boolean {
  const requestTime = parseInt(timestamp, 10)
  const currentTime = Math.floor(Date.now() / 1000)
  const age = currentTime - requestTime

  if (age < -60) {
    // Allow up to 60 seconds of clock skew for future timestamps
    console.warn(`[ShopRenter] Request timestamp is in the future by ${-age}s - allowing due to potential clock skew`)
  }

  if (age > maxAgeSeconds) {
    console.warn(`[ShopRenter] Request timestamp is old: ${age}s > ${maxAgeSeconds}s - allowing due to potential ShopRenter timestamp issues`)
  }

  // Always return true - we rely on HMAC validation for security
  return true
}

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

  try {
    const url = new URL(req.url)
    const shopname = url.searchParams.get('shopname')
    const timestamp = url.searchParams.get('timestamp')
    const hmac = url.searchParams.get('hmac')

    console.log(`[ShopRenter] Uninstall webhook received for ${shopname}`)

    // Check required parameters
    if (!shopname || !timestamp || !hmac) {
      return new Response(
        JSON.stringify({ message: 'Missing required parameters' }),
        { status: 200, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
      )
    }

    // Get environment variables (support both naming conventions with fallback)
    const shoprenterClientId = Deno.env.get('SHOPRENTER_APP_CLIENT_ID') || Deno.env.get('SHOPRENTER_CLIENT_ID')
    const shoprenterClientSecret = Deno.env.get('SHOPRENTER_APP_CLIENT_SECRET') || Deno.env.get('SHOPRENTER_CLIENT_SECRET')
    const supabaseUrl = Deno.env.get('SUPABASE_URL')!
    const supabaseServiceKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!

    // Log which environment variables are being used
    console.log(`[ShopRenter] Using client ID from: ${Deno.env.get('SHOPRENTER_APP_CLIENT_ID') ? 'SHOPRENTER_APP_CLIENT_ID' : 'SHOPRENTER_CLIENT_ID'}`)
    console.log(`[ShopRenter] Using client secret from: ${Deno.env.get('SHOPRENTER_APP_CLIENT_SECRET') ? 'SHOPRENTER_APP_CLIENT_SECRET' : 'SHOPRENTER_CLIENT_SECRET'}`)

    if (!shoprenterClientId || !shoprenterClientSecret) {
      console.error('ShopRenter client credentials not configured. Set either SHOPRENTER_APP_CLIENT_ID/SECRET or SHOPRENTER_CLIENT_ID/SECRET')
      // Still return 200 to prevent retries
      return new Response(
        JSON.stringify({ message: 'Configuration error' }),
        { status: 200, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
      )
    }

    // Validate timestamp (lenient - logs only)
    validateTimestamp(timestamp)

    // Validate HMAC using the raw query string to preserve parameter order
    const rawQueryString = url.search.substring(1) // Remove leading '?'
    if (!(await validateHMAC(rawQueryString, shoprenterClientSecret, shoprenterClientId))) {
      console.error('[ShopRenter] HMAC validation failed')
      // Still return 200 to prevent retries
      return new Response(
        JSON.stringify({ message: 'HMAC validation failed' }),
        { status: 200, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
      )
    }

    console.log('[ShopRenter] HMAC validation passed')

    // Create Supabase client with service role key
    const supabase = createClient(supabaseUrl, supabaseServiceKey)

    // Find store by shopname (include scraper config for disabling)
    const { data: store, error: storeError } = await supabase
      .from('stores')
      .select('id, alt_data, scraper_api_url, scraper_api_secret, scraper_registered')
      .eq('platform_name', 'shoprenter')
      .eq('store_name', shopname)
      .maybeSingle()

    if (storeError) {
      console.error('[ShopRenter] Error finding store:', storeError)
      // Still return 200
      return new Response(
        JSON.stringify({ message: 'Store lookup error' }),
        { status: 200, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
      )
    }

    if (store) {
      const uninstallTimestamp = new Date().toISOString()

      // Merge existing alt_data with uninstall info
      const updatedAltData = {
        ...(store.alt_data || {}),
        uninstalled: true,
        uninstalled_at: uninstallTimestamp
      }

      // Disable store - DO NOT DELETE anything
      const { error: updateError } = await supabase
        .from('stores')
        .update({
          is_active: false,
          qdrant_sync_enabled: false,
          scraper_enabled: false,
          sync_status: 'idle',
          alt_data: updatedAltData
        })
        .eq('id', store.id)

      if (updateError) {
        console.error('[ShopRenter] Error updating store:', updateError)
      } else {
        console.log(`[ShopRenter] Store ${shopname} disabled (is_active=false, qdrant_sync_enabled=false, scraper_enabled=false)`)
      }

      // Disable sync config
      const { error: syncConfigError } = await supabase
        .from('store_sync_config')
        .update({ enabled: false })
        .eq('store_id', store.id)

      if (syncConfigError) {
        console.error('[ShopRenter] Error disabling sync config:', syncConfigError)
      } else {
        console.log(`[ShopRenter] Sync config disabled for store ${shopname}`)
      }

      // Disable tokens (not delete)
      const { error: tokensError } = await supabase
        .from('shoprenter_tokens')
        .update({ is_active: false })
        .eq('store_id', store.id)

      if (tokensError) {
        console.error('[ShopRenter] Error disabling tokens:', tokensError)
      } else {
        console.log(`[ShopRenter] Tokens disabled for store ${shopname}`)
      }

      // Disable webhooks (not delete)
      const { error: webhooksError } = await supabase
        .from('shoprenter_webhooks')
        .update({ is_active: false })
        .eq('store_id', store.id)

      if (webhooksError) {
        console.error('[ShopRenter] Error disabling webhooks:', webhooksError)
      } else {
        console.log(`[ShopRenter] Webhooks disabled for store ${shopname}`)
      }

      // Disable scheduled scraping at the scraper microservice
      if (store.scraper_registered) {
        try {
          // Get scraper API config (per-store or global defaults)
          const scraperApiUrl = store.scraper_api_url || Deno.env.get('DEFAULT_SCRAPER_API_URL')
          const scraperApiSecret = store.scraper_api_secret || Deno.env.get('DEFAULT_SCRAPER_API_SECRET')

          if (scraperApiUrl && scraperApiSecret) {
            console.log(`[ShopRenter] Disabling scheduled scraping for store ${store.id}`)

            const scraperResponse = await fetch(`${scraperApiUrl}/api/shops/${store.id}/schedule`, {
              method: 'PATCH',
              headers: {
                'Authorization': `Bearer ${scraperApiSecret}`,
                'Content-Type': 'application/json',
              },
              body: JSON.stringify({ enabled: false }),
            })

            if (scraperResponse.ok) {
              console.log(`[ShopRenter] Scheduled scraping disabled for store ${shopname}`)
            } else {
              const errorText = await scraperResponse.text()
              console.error(`[ShopRenter] Error disabling scraper scheduling (${scraperResponse.status}): ${errorText}`)
            }
          } else {
            console.warn(`[ShopRenter] Scraper API not configured, skipping scraper disable for store ${shopname}`)
          }
        } catch (scraperError) {
          // Don't fail the webhook if scraper call fails
          console.error(`[ShopRenter] Error calling scraper API:`, scraperError)
        }
      } else {
        console.log(`[ShopRenter] Store ${shopname} not registered with scraper, skipping scraper disable`)
      }

      console.log(`[ShopRenter] Store ${shopname} uninstalled successfully (all features disabled, data preserved)`)
    } else {
      console.log(`[ShopRenter] Store ${shopname} not found in database`)
    }

    // Always respond with 200 (ShopRenter expects this)
    return new Response(
      JSON.stringify({ message: 'Uninstall processed' }),
      { status: 200, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
    )

  } catch (error) {
    console.error('[ShopRenter] Uninstall webhook error:', error)
    // Still return 200 to prevent retries
    return new Response(
      JSON.stringify({ message: 'Internal error' }),
      { status: 200, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
    )
  }
})
