import { serve } from 'https://deno.land/std@0.168.0/http/server.ts'
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'
import { createHmac } from 'https://deno.land/std@0.168.0/node/crypto.ts'
import { wrapHandler, logError } from '../_shared/error-handler.ts'
import { createScraperClient } from '../_shared/scraper-client.ts'

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

// Shopify OAuth scopes required for the app
const SHOPIFY_SCOPES = [
  'read_products',
  'read_orders',
  'read_customers',
  'read_inventory',
  'read_price_rules'
]

// Validate Shopify shop domain
function validateShopDomain(shop: string): { valid: boolean; error?: string; normalized?: string } {
  try {
    // Shop should be in format: store-name.myshopify.com
    const shopPattern = /^[a-zA-Z0-9][a-zA-Z0-9-]*\.myshopify\.com$/

    if (!shopPattern.test(shop)) {
      return {
        valid: false,
        error: 'Invalid shop domain. Must be in format: store-name.myshopify.com'
      }
    }

    return { valid: true, normalized: shop.toLowerCase() }
  } catch (error) {
    return { valid: false, error: 'Invalid shop domain format' }
  }
}

// Verify Shopify HMAC signature
function verifyHmac(params: Record<string, string>, hmac: string, secret: string): boolean {
  // Remove hmac and signature from params
  const { hmac: _, signature: __, ...filteredParams } = params

  // Sort and build query string
  const sortedParams = Object.keys(filteredParams)
    .sort()
    .map(key => `${key}=${filteredParams[key]}`)
    .join('&')

  // Calculate HMAC
  const calculatedHmac = createHmac('sha256', secret)
    .update(sortedParams)
    .digest('hex')

  return calculatedHmac === hmac
}

// Exchange authorization code for access token
async function exchangeCodeForToken(
  shop: string,
  code: string,
  apiKey: string,
  apiSecret: string
): Promise<{ success: boolean; accessToken?: string; scopes?: string[]; error?: string }> {
  try {
    const tokenUrl = `https://${shop}/admin/oauth/access_token`

    const response = await fetch(tokenUrl, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        client_id: apiKey,
        client_secret: apiSecret,
        code
      })
    })

    if (!response.ok) {
      const errorText = await response.text()
      console.error('[Shopify] Token exchange failed:', response.status, errorText)
      return {
        success: false,
        error: `Failed to exchange code for token (${response.status})`
      }
    }

    const data = await response.json()

    return {
      success: true,
      accessToken: data.access_token,
      scopes: data.scope ? data.scope.split(',') : []
    }
  } catch (error) {
    console.error('[Shopify] Token exchange error:', error)
    return {
      success: false,
      error: error instanceof Error ? error.message : 'Failed to exchange code for token'
    }
  }
}

// Register store with scraper service
async function registerStoreWithScraper(
  storeId: string,
  storeUrl: string,
  supabase: any
): Promise<void> {
  try {
    console.log(`[Shopify] Registering store ${storeId} with scraper service`)

    // Create scraper client with global configuration
    const scraperClient = await createScraperClient()

    // Register shop with scraper using store_id as custom_id
    const job = await scraperClient.registerShop(storeUrl, storeId)
    console.log(`[Shopify] Scraper registration job created: ${job.id}`)

    // Set up webhook to receive scraper status updates
    const webhookUrl = `${Deno.env.get('SUPABASE_URL')}/functions/v1/scraper-webhook`
    try {
      await scraperClient.setWebhook(storeId, webhookUrl)
      console.log(`[Shopify] Scraper webhook configured for store ${storeId}`)
    } catch (webhookError) {
      console.warn(`[Shopify] Failed to configure scraper webhook:`, webhookError)
      // Continue anyway - webhook is optional
    }

    // Enable scheduled scraping
    try {
      await scraperClient.setScheduling(storeId, true)
      console.log(`[Shopify] Scraper scheduling enabled for store ${storeId}`)
    } catch (scheduleError) {
      console.warn(`[Shopify] Failed to enable scraper scheduling:`, scheduleError)
      // Continue anyway
    }

    // Update database to mark as registered
    const { error: updateError } = await supabase
      .from('stores')
      .update({ scraper_registered: true })
      .eq('id', storeId)

    if (updateError) {
      console.error(`[Shopify] Failed to update scraper registration status:`, updateError)
      // Continue anyway - this is not critical for the OAuth flow
    } else {
      console.log(`[Shopify] Store ${storeId} successfully registered with scraper`)
    }

  } catch (error) {
    console.error(`[Shopify] Failed to register store with scraper:`, error)
    // Don't throw error - scraper registration should not fail the OAuth flow
  }
}

// Test Shopify API connection
async function testShopifyConnection(
  shop: string,
  accessToken: string
): Promise<{ success: boolean; shopData?: any; error?: string }> {
  try {
    const apiUrl = `https://${shop}/admin/api/2024-01/shop.json`

    const response = await fetch(apiUrl, {
      headers: {
        'X-Shopify-Access-Token': accessToken,
        'Content-Type': 'application/json'
      }
    })

    if (!response.ok) {
      const errorText = await response.text()
      console.error('[Shopify] API test failed:', response.status, errorText)
      return {
        success: false,
        error: `API connection failed (${response.status})`
      }
    }

    const data = await response.json()
    return { success: true, shopData: data.shop }
  } catch (error) {
    console.error('[Shopify] Connection test error:', error)
    return {
      success: false,
      error: error instanceof Error ? error.message : 'Failed to connect to Shopify'
    }
  }
}

serve(wrapHandler('oauth-shopify', async (req) => {
  if (req.method === 'OPTIONS') {
    return new Response('ok', { headers: corsHeaders })
  }
    const url = new URL(req.url)
    const action = url.searchParams.get('action') || 'init'

    // Get environment variables
    const shopifyApiKey = Deno.env.get('SHOPIFY_API_KEY')
    const shopifyApiSecret = Deno.env.get('SHOPIFY_API_SECRET')
    const supabaseUrl = Deno.env.get('SUPABASE_URL')!
    const supabaseKey = Deno.env.get('SUPABASE_ANON_KEY')!
    const supabaseServiceKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!
    const frontendUrl = Deno.env.get('FRONTEND_URL') || 'https://shopcall.ai'

    if (!shopifyApiKey || !shopifyApiSecret) {
      console.error('Shopify API credentials not configured')
      return new Response(
        JSON.stringify({ error: 'Shopify integration not configured' }),
        { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
      )
    }

    // ========================================================================
    // Handle OAuth initiation
    // ========================================================================
    if (action === 'init') {
      const shop = url.searchParams.get('shop')
      const phoneNumberId = url.searchParams.get('phoneNumberId')

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

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

      // Validate shop domain
      const validation = validateShopDomain(shop)
      if (!validation.valid) {
        return new Response(
          JSON.stringify({ error: validation.error }),
          { status: 400, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
        )
      }

      // Get user from authorization header
      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 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 phone number is available and belongs to user
      const { data: phoneNumber, error: phoneError } = await supabase
        .from('phone_numbers')
        .select('id, is_available')
        .eq('id', phoneNumberId)
        .single()

      if (phoneError || !phoneNumber) {
        console.error('[Shopify] Phone number not found:', phoneError)
        return new Response(
          JSON.stringify({ error: 'Invalid phone number selected' }),
          { status: 400, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
        )
      }

      if (!phoneNumber.is_available) {
        console.error('[Shopify] Phone number not available:', phoneNumberId)
        return new Response(
          JSON.stringify({ error: 'Selected phone number is no longer available' }),
          { status: 400, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
        )
      }

      // Generate state parameter for CSRF protection
      const state = crypto.randomUUID()

      // Store state in database with phone_number_id
      const { error: stateError } = await supabase
        .from('oauth_states')
        .insert({
          state,
          user_id: user.id,
          platform: 'shopify',
          shopname: validation.normalized,
          phone_number_id: phoneNumberId,
          expires_at: new Date(Date.now() + 15 * 60 * 1000).toISOString() // 15 minutes
        })

      if (stateError) {
        console.error('[Shopify] Error storing state:', stateError)
        return new Response(
          JSON.stringify({ error: 'Failed to initiate OAuth flow' }),
          { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
        )
      }

      // Build Shopify OAuth authorization URL
      const callbackUrl = `${url.protocol}//${url.host}${url.pathname}?action=callback`
      const scopes = SHOPIFY_SCOPES.join(',')

      const authUrl = new URL(`https://${validation.normalized}/admin/oauth/authorize`)
      authUrl.searchParams.set('client_id', shopifyApiKey)
      authUrl.searchParams.set('scope', scopes)
      authUrl.searchParams.set('redirect_uri', callbackUrl)
      authUrl.searchParams.set('state', state)

      console.log(`[Shopify] OAuth initiated for shop: ${validation.normalized}`)

      return new Response(
        JSON.stringify({
          success: true,
          authUrl: authUrl.toString(),
          message: 'Redirect to Shopify for authorization'
        }),
        { status: 200, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
      )
    }

    // ========================================================================
    // Handle OAuth callback
    // ========================================================================
    if (action === 'callback') {
      const code = url.searchParams.get('code')
      const hmac = url.searchParams.get('hmac')
      const shop = url.searchParams.get('shop')
      const state = url.searchParams.get('state')
      const timestamp = url.searchParams.get('timestamp')

      console.log(`[Shopify] OAuth callback received for shop: ${shop}`)

      // Validate required parameters
      if (!code || !hmac || !shop || !state) {
        console.error('[Shopify] Missing required callback parameters')
        return new Response(null, {
          status: 302,
          headers: {
            ...corsHeaders,
            'Location': `${frontendUrl}/webshops?error=shopify_oauth_failed`
          }
        })
      }

      // Validate shop domain
      const validation = validateShopDomain(shop)
      if (!validation.valid) {
        console.error('[Shopify] Invalid shop domain:', shop)
        return new Response(null, {
          status: 302,
          headers: {
            ...corsHeaders,
            'Location': `${frontendUrl}/webshops?error=invalid_shop_domain`
          }
        })
      }

      // Verify HMAC signature
      const params: Record<string, string> = {}
      url.searchParams.forEach((value, key) => {
        params[key] = value
      })

      if (!verifyHmac(params, hmac, shopifyApiSecret)) {
        console.error('[Shopify] HMAC verification failed')
        return new Response(null, {
          status: 302,
          headers: {
            ...corsHeaders,
            'Location': `${frontendUrl}/webshops?error=shopify_hmac_invalid`
          }
        })
      }

      // Verify state parameter
      const supabaseAdmin = createClient(supabaseUrl, supabaseServiceKey)

      const { data: stateData, error: stateError } = await supabaseAdmin
        .from('oauth_states')
        .select('*')
        .eq('state', state)
        .eq('platform', 'shopify')
        .single()

      if (stateError || !stateData) {
        console.error('[Shopify] Invalid or expired state parameter:', stateError)
        return new Response(null, {
          status: 302,
          headers: {
            ...corsHeaders,
            'Location': `${frontendUrl}/webshops?error=shopify_invalid_state`
          }
        })
      }

      // Check if state is expired
      if (new Date(stateData.expires_at) < new Date()) {
        console.error('[Shopify] State parameter expired')
        await supabaseAdmin.from('oauth_states').delete().eq('state', state)
        return new Response(null, {
          status: 302,
          headers: {
            ...corsHeaders,
            'Location': `${frontendUrl}/webshops?error=shopify_state_expired`
          }
        })
      }

      // Exchange code for access token
      const tokenResult = await exchangeCodeForToken(
        validation.normalized!,
        code,
        shopifyApiKey,
        shopifyApiSecret
      )

      if (!tokenResult.success || !tokenResult.accessToken) {
        console.error('[Shopify] Failed to exchange code for token:', tokenResult.error)
        await supabaseAdmin.from('oauth_states').delete().eq('state', state)
        return new Response(null, {
          status: 302,
          headers: {
            ...corsHeaders,
            'Location': `${frontendUrl}/webshops?error=shopify_token_exchange_failed`
          }
        })
      }

      // Test API connection and get shop details
      const testResult = await testShopifyConnection(
        validation.normalized!,
        tokenResult.accessToken
      )

      if (!testResult.success) {
        console.error('[Shopify] API connection test failed:', testResult.error)
        await supabaseAdmin.from('oauth_states').delete().eq('state', state)
        return new Response(null, {
          status: 302,
          headers: {
            ...corsHeaders,
            'Location': `${frontendUrl}/webshops?error=shopify_connection_failed`
          }
        })
      }

      // Extract shop info
      const shopData = testResult.shopData
      const storeName = shopData?.name || validation.normalized?.split('.')[0] || 'Unknown Store'
      const shopDomain = validation.normalized!

      // Verify phone number is still available
      const phoneNumberId = stateData.phone_number_id
      if (!phoneNumberId) {
        console.error('[Shopify] No phone number ID in state')
        await supabaseAdmin.from('oauth_states').delete().eq('state', state)
        return new Response(null, {
          status: 302,
          headers: {
            ...corsHeaders,
            'Location': `${frontendUrl}/webshops?error=phone_number_missing`
          }
        })
      }

      const { data: phoneNumber, error: phoneError } = await supabaseAdmin
        .from('phone_numbers')
        .select('id, is_available')
        .eq('id', phoneNumberId)
        .single()

      if (phoneError || !phoneNumber || !phoneNumber.is_available) {
        console.error('[Shopify] Phone number no longer available:', phoneNumberId)
        await supabaseAdmin.from('oauth_states').delete().eq('state', state)
        return new Response(null, {
          status: 302,
          headers: {
            ...corsHeaders,
            'Location': `${frontendUrl}/webshops?error=phone_number_unavailable`
          }
        })
      }

      // Store credentials in database with phone_number_id
      const { data: insertedStore, error: insertError } = await supabaseAdmin
        .from('stores')
        .insert({
          user_id: stateData.user_id,
          platform_name: 'shopify',
          store_name: storeName,
          store_url: shopDomain,
          api_key: tokenResult.accessToken,
          scopes: tokenResult.scopes || SHOPIFY_SCOPES,
          phone_number_id: phoneNumberId,
          alt_data: {
            shopifyDomain: shopDomain,
            shop_id: shopData?.id,
            email: shopData?.email,
            currency: shopData?.currency,
            timezone: shopData?.timezone,
            plan_name: shopData?.plan_name,
            connectedAt: new Date().toISOString()
          }
        })
        .select('id')
        .single()

      if (insertError || !insertedStore) {
        console.error('[Shopify] Error storing credentials:', insertError)
        await supabaseAdmin.from('oauth_states').delete().eq('state', state)
        return new Response(null, {
          status: 302,
          headers: {
            ...corsHeaders,
            'Location': `${frontendUrl}/webshops?error=failed_to_save`
          }
        })
      }

      // Update phone number to mark as assigned (is_available=false, store_id)
      const { error: phoneUpdateError } = await supabaseAdmin
        .from('phone_numbers')
        .update({
          is_available: false,
          store_id: insertedStore.id,
          updated_at: new Date().toISOString()
        })
        .eq('id', phoneNumberId)

      if (phoneUpdateError) {
        console.error('[Shopify] Error updating phone number:', phoneUpdateError)
        // Rollback: delete the store
        await supabaseAdmin.from('stores').delete().eq('id', insertedStore.id)
        await supabaseAdmin.from('oauth_states').delete().eq('state', state)
        return new Response(null, {
          status: 302,
          headers: {
            ...corsHeaders,
            'Location': `${frontendUrl}/webshops?error=phone_assignment_failed`
          }
        })
      }

      // Clean up state
      await supabaseAdmin.from('oauth_states').delete().eq('state', state)

      console.log(`[Shopify] Store connected successfully: ${storeName} (${shopDomain}) with phone number ${phoneNumberId}`)

      // Register store with scraper service in background
      registerStoreWithScraper(insertedStore.id, `https://${shopDomain}`, supabaseAdmin)
        .then(() => console.log(`[Shopify] Scraper registration completed for store ${insertedStore.id}`))
        .catch(err => console.error(`[Shopify] Scraper registration failed:`, err))

      // Trigger auto-sync in background
      const triggerSyncUrl = `${supabaseUrl}/functions/v1/trigger-sync`
      fetch(triggerSyncUrl, {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${supabaseServiceKey}`,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({ store_id: insertedStore.id })
      })
        .then(() => console.log(`[Shopify] Auto-sync triggered for store ${insertedStore.id}`))
        .catch(err => console.error(`[Shopify] Failed to trigger auto-sync:`, err))

      // Redirect back to frontend with success
      return new Response(null, {
        status: 302,
        headers: {
          ...corsHeaders,
          'Location': `${frontendUrl}/webshops?shopify_connected=true&store=${encodeURIComponent(storeName)}`
        }
      })
    }

    // Unknown action
    return new Response(
      JSON.stringify({ error: 'Invalid action parameter' }),
      { status: 400, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
    )
}))
