import { NextRequest, NextResponse } from 'next/server';
import { db } from '@/db/client';
import { ShopRecord } from '@/types';
import { SHOPIFY_CONFIG } from '@/config/shopify';
import { APP_URLS, buildAppUrl } from '@/config/app';
import { buildShopifyAuthUrl } from '@/lib/shopify/oauth';
import { verifyShopifySessionToken } from './sessionToken';

/**
 * Extracts and securely authenticates the store from request headers, session tokens, or query parameters.
 * Strictly verifies Shopify App Bridge Session Tokens (JWT) using HMAC-SHA256 signature verification.
 * Guarantees tenant isolation and protects against forged session tokens.
 */
export async function getAuthenticatedStore(req: NextRequest): Promise<ShopRecord | null> {
  const url = new URL(req.url);

  let targetDomain: string | null = null;
  let hasExplicitToken = false;

  // 1. Check Authorization Bearer Header (Shopify App Bridge Session Token)
  const authHeader = req.headers.get('authorization');
  if (authHeader && authHeader.startsWith('Bearer ')) {
    hasExplicitToken = true;
    const token = authHeader.substring(7).trim();
    const verification = verifyShopifySessionToken(token);

    if (!verification.valid) {
      // Security rule: If a token is supplied but invalid/forged/expired, reject immediately!
      return null;
    }

    targetDomain = verification.data!.shopDomain;
  }

  // 2. Check id_token in query params or headers
  if (!targetDomain) {
    const idToken = url.searchParams.get('id_token') || req.headers.get('x-shopify-id-token');
    if (idToken) {
      hasExplicitToken = true;
      const verification = verifyShopifySessionToken(idToken);

      if (!verification.valid) {
        // Security rule: If id_token is supplied but invalid/forged/expired, reject immediately!
        return null;
      }

      targetDomain = verification.data!.shopDomain;
    }
  }

  // 3. Check 'shop' or 'shopify_domain' parameter in URL
  if (!targetDomain) {
    const shopParam = url.searchParams.get('shop') || url.searchParams.get('shopify_domain');
    if (shopParam) {
      const cleaned = shopParam.trim().toLowerCase().replace(/^https?:\/\//, '').replace(/\/.*$/, '');
      if (cleaned.length > 0) {
        targetDomain = cleaned.includes('.') ? cleaned : `${cleaned}.myshopify.com`;
      }
    }
  }

  // 4. Check Cookie Header
  if (!targetDomain) {
    const cookies = req.headers.get('cookie') || '';
    const match = cookies.match(/shopify_shop_domain=([^;]+)/);
    if (match && match[1]) {
      targetDomain = decodeURIComponent(match[1]).trim().toLowerCase();
    }
  }

  // 5. Check Referer header (Shopify Admin iframe embeds)
  if (!targetDomain) {
    const referer = req.headers.get('referer');
    if (referer) {
      try {
        const refUrl = new URL(referer);
        const refShop = refUrl.searchParams.get('shop') || refUrl.searchParams.get('shopify_domain');
        if (refShop) {
          const cleaned = refShop.trim().toLowerCase().replace(/^https?:\/\//, '').replace(/\/.*$/, '');
          targetDomain = cleaned.includes('.') ? cleaned : `${cleaned}.myshopify.com`;
        } else {
          const adminMatch = referer.match(/admin\.shopify\.com\/store\/([^/?#]+)/i);
          if (adminMatch && adminMatch[1]) {
            targetDomain = `${adminMatch[1].toLowerCase()}.myshopify.com`;
          } else {
            const directMatch = referer.match(/https?:\/\/([^/?#]+\.myshopify\.com)/i);
            if (directMatch && directMatch[1]) {
              targetDomain = directMatch[1].toLowerCase();
            }
          }
        }
      } catch {}
    }
  }

  // 6. Fallback to general request domain extractor
  if (!targetDomain) {
    targetDomain = extractShopDomainFromRequest(req);
  }

  // 7. If targetDomain resolved, fetch that specific store
  if (targetDomain) {
    let shop = await db.getShopByDomain(targetDomain);
    if (!shop) {
      try {
        const cleanDomain = targetDomain.toLowerCase().trim().replace(/^https?:\/\//, '').replace(/\/.*$/, '');
        const fullDomain = cleanDomain.includes('.') ? cleanDomain : `${cleanDomain}.myshopify.com`;
        const baseName = fullDomain.split('.')[0] || 'Shopify Store';
        shop = await db.upsertShop({
          id: `shop_${cleanDomain.replace(/[^a-zA-Z0-9]/g, '_')}`,
          shopify_domain: fullDomain,
          shop_name: baseName,
          status: 'installed',
          plan: 'growth',
          access_token_encrypted: '',
          scopes: ['read_products', 'write_pixels'],
          installed_at: new Date().toISOString(),
          created_at: new Date().toISOString(),
          updated_at: new Date().toISOString(),
        });
      } catch (err) {
        console.error('Failed to auto-provision store in storeContext:', err);
      }
    }
    if (shop) {
      return shop;
    }
  }

  // 8. Safe fallback to default store if targetDomain was stripped by browser
  try {
    const defaultShop = await db.getDefaultShop();
    if (defaultShop) {
      return defaultShop;
    }
  } catch {}

  return null;
}

/**
 * Robustly extracts the store domain from query params, session tokens, referer, or headers.
 */
export function extractShopDomainFromRequest(req: NextRequest): string | null {
  // 1. Check Authorization Bearer Header (Shopify App Bridge Session Token JWT)
  const authHeader = req.headers.get('authorization');
  if (authHeader && authHeader.startsWith('Bearer ')) {
    const token = authHeader.substring(7).trim();
    const verification = verifyShopifySessionToken(token);
    if (verification.valid && verification.data?.shopDomain) {
      return verification.data.shopDomain.toLowerCase();
    }
  }

  // 2. Check searchParams (?shop=... or ?shopify_domain=...)
  const fromQuery = req.nextUrl?.searchParams?.get('shop') || req.nextUrl?.searchParams?.get('shopify_domain');
  if (fromQuery) {
    const cleaned = fromQuery.trim().toLowerCase().replace(/^https?:\/\//, '').replace(/\/.*$/, '');
    if (cleaned) {
      return cleaned.includes('.') ? cleaned : `${cleaned}.myshopify.com`;
    }
  }

  // 3. Check id_token in query or header
  const idToken = req.nextUrl?.searchParams?.get('id_token') || req.headers.get('x-shopify-id-token');
  if (idToken) {
    const verification = verifyShopifySessionToken(idToken);
    if (verification.valid && verification.data?.shopDomain) {
      return verification.data.shopDomain.toLowerCase();
    }
  }

  // 4. Check x-shopify-shop-domain header
  const headerDomain = req.headers.get('x-shopify-shop-domain');
  if (headerDomain) {
    const cleaned = headerDomain.trim().toLowerCase().replace(/^https?:\/\//, '').replace(/\/.*$/, '');
    if (cleaned) {
      return cleaned.includes('.') ? cleaned : `${cleaned}.myshopify.com`;
    }
  }

  // 5. Check Referer header (Shopify Admin embeds: https://admin.shopify.com/store/{store_name}/apps/...)
  const referer = req.headers.get('referer');
  if (referer) {
    const adminMatch = referer.match(/admin\.shopify\.com\/store\/([^/?#]+)/i);
    if (adminMatch && adminMatch[1]) {
      return `${adminMatch[1].toLowerCase()}.myshopify.com`;
    }
    const directMatch = referer.match(/https?:\/\/([^/?#]+\.myshopify\.com)/i);
    if (directMatch && directMatch[1]) {
      return directMatch[1].toLowerCase();
    }
  }

  // 6. Check Cookie header
  const cookies = req.headers.get('cookie') || '';
  const match = cookies.match(/shopify_shop_domain=([^;]+)/);
  if (match && match[1]) {
    const cleaned = decodeURIComponent(match[1]).trim().toLowerCase().replace(/^https?:\/\//, '').replace(/\/.*$/, '');
    if (cleaned) {
      return cleaned.includes('.') ? cleaned : `${cleaned}.myshopify.com`;
    }
  }

  return null;
}

/**
 * Utility helper to return a standardized 401 Unauthorized response for App Bridge.
 * Generates direct Shopify OAuth authorize URL or canonical reauthorize URL.
 * Includes X-Shopify-API-Request-Failure-Reauthorize headers so App Bridge / ApiUrlInterceptor can break out.
 */
export function unauthorizedResponse(
  messageOrReq: string | NextRequest = 'Unauthorized store access',
  status = 401,
  explicitShopDomain?: string
): NextResponse {
  let message = 'Unauthorized store access';
  let shopDomain = explicitShopDomain;

  if (typeof messageOrReq === 'string') {
    message = messageOrReq;
  } else if (messageOrReq && typeof messageOrReq === 'object' && 'headers' in messageOrReq) {
    const req = messageOrReq as NextRequest;
    shopDomain = shopDomain || extractShopDomainFromRequest(req) || undefined;
  }

  let reauthUrl = '';
  if (shopDomain) {
    try {
      reauthUrl = buildShopifyAuthUrl(shopDomain, APP_URLS.authCallback()).url;
    } catch {
      reauthUrl = buildAppUrl('/api/auth/shopify', { shop: shopDomain });
    }
  } else {
    reauthUrl = buildAppUrl('/api/auth/shopify');
  }

  return NextResponse.json(
    { success: false, error: message },
    {
      status,
      headers: {
        'X-Shopify-API-Request-Failure-Reauthorize': '1',
        'X-Shopify-API-Request-Failure-Reauthorize-Url': reauthUrl,
      },
    }
  );
}


