import { serve } from 'https://deno.land/std@0.168.0/http/server.ts'
import { wrapHandler } from '../_shared/error-handler.ts'

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

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

// Validate HMAC signature from ShopRenter
// Per ShopRenter documentation, HMAC is calculated from the query string without HMAC parameter
async function validateHMAC(params: Record<string, string>, clientSecret: string, clientId: string): Promise<boolean> {
  if (!clientSecret) {
    console.error('[ShopRenter] Client secret is empty or undefined')
    return false
  }

  const hmacValue = params.hmac
  if (!hmacValue) {
    console.error('[ShopRenter] HMAC missing from request')
    return false
  }

  // Build the params string by preserving the original order
  // ShopRenter calculates HMAC using: shopname=...&code=...&timestamp=... (original order)
  // Exclude hmac and sr_install (our custom parameter)
  const paramsWithoutHmac = Object.entries(params)
    .filter(([key]) => key !== 'hmac' && key !== 'sr_install')
    .map(([key, value]) => `${key}=${value}`)
    .join('&')

  console.log(`[ShopRenter] HMAC validation - params: ${paramsWithoutHmac}`)

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

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

  try {
    // Parse request body containing the URL parameters
    const body = await req.json()
    const { shopname, code, timestamp, hmac, sr_install } = body

    console.log(`[ShopRenter] Validating HMAC for ${shopname}`)

    // Check required parameters
    if (!shopname || !code || !timestamp || !hmac) {
      return new Response(
        JSON.stringify({ valid: false, error: 'Missing required parameters' }),
        { status: 400, 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')

    if (!shoprenterClientId || !shoprenterClientSecret) {
      console.error('ShopRenter client credentials not configured')
      return new Response(
        JSON.stringify({ valid: false, error: 'ShopRenter integration not configured' }),
        { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
      )
    }

    // Build params object preserving order (shopname, code, timestamp)
    const params: Record<string, string> = {
      shopname,
      code,
      timestamp,
      hmac
    }

    // Validate HMAC
    const isValid = await validateHMAC(params, shoprenterClientSecret, shoprenterClientId)

    if (!isValid) {
      console.error(`[ShopRenter] HMAC validation failed for ${shopname}`)
      return new Response(
        JSON.stringify({ valid: false, error: 'HMAC validation failed' }),
        { status: 403, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
      )
    }

    console.log(`[ShopRenter] HMAC validation successful for ${shopname}`)

    return new Response(
      JSON.stringify({
        valid: true,
        shopname,
        installation_id: sr_install
      }),
      { status: 200, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
    )

  } catch (error) {
    console.error('[ShopRenter] HMAC validation error:', error)
    return new Response(
      JSON.stringify({ valid: false, error: 'Failed to validate HMAC' }),
      { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
    )
  }
}))
