import { generateSecureToken } from '@/lib/crypto/encryption';
import { isValidShopifyDomain } from './hmac';
import { env } from '@/lib/config/env';

const SHOPIFY_DEFAULT_SCOPES = env.shopify.scopes.split(',');

export function buildShopifyAuthUrl(shopDomain: string, redirectUri: string): { url: string; state: string } {
  if (!isValidShopifyDomain(shopDomain)) {
    throw new Error(`Invalid Shopify domain format: ${shopDomain}`);
  }

  const apiKey = env.shopify.apiKey;
  const state = generateSecureToken(16);
  const scopes = SHOPIFY_DEFAULT_SCOPES.join(',');

  const url = `https://${shopDomain}/admin/oauth/authorize?client_id=${encodeURIComponent(apiKey)}&scope=${encodeURIComponent(scopes)}&redirect_uri=${encodeURIComponent(redirectUri)}&state=${encodeURIComponent(state)}`;

  return { url, state };
}

export async function exchangeShopifyAuthCode(shopDomain: string, code: string): Promise<{
  access_token: string;
  scope: string;
  expires_in?: number;
  refresh_token?: string;
}> {
  const cleanShop = shopDomain.replace(/^https?:\/\//, '').replace(/\/.*$/, '').trim();
  const apiKey = env.shopify.apiKey || process.env.SHOPIFY_API_KEY || '';
  const apiSecret = env.shopify.apiSecret || process.env.SHOPIFY_API_SECRET || '';

  if (!apiKey || !apiSecret || apiKey.startsWith('mock_')) {
    return {
      access_token: `shpat_mock_${Date.now()}`,
      scope: SHOPIFY_DEFAULT_SCOPES.join(','),
    };
  }

  const url = `https://${cleanShop}/admin/oauth/access_token`;
  const tokenParams = new URLSearchParams({
    client_id: apiKey,
    client_secret: apiSecret,
    code,
    expiring: '1',
  });

  const response = await fetch(url, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
      'Accept': 'application/json',
    },
    body: tokenParams.toString(),
  });

  if (!response.ok) {
    const errorText = await response.text();
    throw new Error(`Shopify token exchange failed (${response.status}): ${errorText}`);
  }

  return response.json();
}

/**
 * Refreshes an expiring offline access token using the stored refresh token.
 */
export async function refreshShopifyAccessToken(
  shopDomain: string,
  refreshToken: string,
  customApiKey?: string,
  customApiSecret?: string
): Promise<{
  access_token: string;
  scope?: string;
  expires_in: number;
  refresh_token?: string;
  refresh_token_expires_in?: number;
}> {
  const cleanShop = shopDomain.replace(/^https?:\/\//, '').replace(/\/.*$/, '').trim();
  const apiKey = customApiKey || env.shopify.apiKey || process.env.SHOPIFY_API_KEY || '';
  const apiSecret = customApiSecret || env.shopify.apiSecret || process.env.SHOPIFY_API_SECRET || '';

  const url = `https://${cleanShop}/admin/oauth/access_token`;
  const body = new URLSearchParams({
    client_id: apiKey,
    client_secret: apiSecret,
    grant_type: 'refresh_token',
    refresh_token: refreshToken,
    expiring: '1',
  });

  const response = await fetch(url, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
      'Accept': 'application/json',
    },
    body: body.toString(),
  });

  if (!response.ok) {
    const errorText = await response.text();
    throw new Error(`Shopify token refresh failed (${response.status}): ${errorText}`);
  }

  return response.json();
}

/**
 * Automatically exchanges a legacy non-expiring offline token for an expiring offline token
 * via Shopify's OAuth Token Exchange specification.
 */
export async function exchangeLegacyTokenForExpiring(
  shopDomain: string,
  legacyToken: string,
  customApiKey?: string,
  customApiSecret?: string
): Promise<{
  access_token: string;
  expires_in: number;
  refresh_token?: string;
  refresh_token_expires_in?: number;
  scope?: string;
}> {
  const cleanShop = shopDomain.replace(/^https?:\/\//, '').replace(/\/.*$/, '').trim();
  const apiKey = customApiKey || env.shopify.apiKey || process.env.SHOPIFY_API_KEY || '';
  const apiSecret = customApiSecret || env.shopify.apiSecret || process.env.SHOPIFY_API_SECRET || '';

  const url = `https://${cleanShop}/admin/oauth/access_token`;
  const body = new URLSearchParams({
    client_id: apiKey,
    client_secret: apiSecret,
    grant_type: 'urn:ietf:params:oauth:grant-type:token-exchange',
    subject_token: legacyToken,
    subject_token_type: 'urn:shopify:params:oauth:token-type:offline-access-token',
    requested_token_type: 'urn:shopify:params:oauth:token-type:offline-access-token',
    expiring: '1',
  });

  const response = await fetch(url, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
      'Accept': 'application/json',
    },
    body: body.toString(),
  });

  if (!response.ok) {
    const errorText = await response.text();
    throw new Error(`Shopify legacy token exchange failed (${response.status}): ${errorText}`);
  }

  return response.json();
}
