const axios = require('axios');
const { log } = require('./logger');

/**
 * Create (or retrieve existing) fulfillment service + location for a shop.
 * Returns { fulfillmentService, locationId } — locationId is NEVER null if a
 * fulfillment service exists, because we fall back to the service's own location.
 */
async function createFulfillmentService(shop, accessToken) {
  const client = axios.create({
    baseURL: `https://${shop}/admin/api/2025-10/graphql.json`,
    headers: {
      'X-Shopify-Access-Token': accessToken,
      'Content-Type': 'application/json',
    },
  });

  try {
    log(shop, `🚀 [FulfillmentService] Creating fulfillment service...`);

    // ── Step 1: Create fulfillment service (or retrieve existing) ────────────
    const createResp = await client.post('', {
      query: `
        mutation {
          fulfillmentServiceCreate(
            name: "Data4Autos Distribution",
            callbackUrl: "https://backend.data4autos.com/fulfillment"
          ) {
            fulfillmentService {
              id serviceName callbackUrl handle
              location { id name }
            }
            userErrors { field message }
          }
        }
      `,
    });

    let fulfillmentService = createResp.data?.data?.fulfillmentServiceCreate?.fulfillmentService;
    const createErrors = createResp.data?.data?.fulfillmentServiceCreate?.userErrors || [];

    if (createErrors.length > 0) {
      log(shop, `⚠️  [FulfillmentService] Create errors: ${JSON.stringify(createErrors)}`);
      // Service likely already exists — query it instead
      log(shop, `🔍 [FulfillmentService] Querying existing fulfillment service...`);
      const existingResp = await client.post('', {
        query: `
          query {
            fulfillmentServices(type: THIRD_PARTY) {
              id serviceName callbackUrl handle
              location { id name }
            }
          }
        `,
      });
      const services = existingResp.data?.data?.fulfillmentServices || [];
      fulfillmentService = services.find(s => s.handle === 'data4autos-distribution') || services[0] || null;

      if (!fulfillmentService) {
        log(shop, `❌ [FulfillmentService] Could not create or find existing service`);
        return { fulfillmentService: null, locationId: null };
      }
      log(shop, `✅ [FulfillmentService] Found existing: ${fulfillmentService.id}`);
    } else {
      log(shop, `✅ [FulfillmentService] Created: ${fulfillmentService.id}`);
    }

    // The fulfillment service has its own Shopify-managed location — use it as fallback
    const serviceFallbackLocationId = fulfillmentService?.location?.id || null;
    log(shop, `📍 [FulfillmentService] Service location (fallback): ${serviceFallbackLocationId}`);

    // ── Step 2: Try to create a custom named location ────────────────────────
    // First get the store's primary location address (search broadly, not by exact name)
    let storeAddress = null;
    try {
      const locResp = await client.post('', {
        query: `query { locations(first: 1) { nodes { id name address { address1 address2 city province provinceCode country countryCode zip phone } } } }`,
      });
      const locNode = locResp.data?.data?.locations?.nodes?.[0];
      if (locNode) {
        storeAddress = locNode.address;
        log(shop, `📍 [FulfillmentService] Store address from "${locNode.name}": ${JSON.stringify(storeAddress)}`);
      }
    } catch (addrErr) {
      log(shop, `⚠️  [FulfillmentService] Could not fetch store address: ${addrErr.message}`);
    }

    let customLocationId = null;
    if (storeAddress) {
      try {
        const provinceCode = storeAddress.provinceCode || storeAddress.province || '';
        const countryCode = storeAddress.countryCode || 'US';

        const locAddResp = await client.post('', {
          query: `
            mutation {
              locationAdd(input: {
                name: "(App) Data4Autos Distribution API",
                address: {
                  address1: ${JSON.stringify(storeAddress.address1 || '')},
                  address2: ${JSON.stringify(storeAddress.address2 || '')},
                  city: ${JSON.stringify(storeAddress.city || '')},
                  provinceCode: ${JSON.stringify(provinceCode)},
                  countryCode: ${countryCode},
                  zip: ${JSON.stringify(storeAddress.zip || '')},
                  phone: ${JSON.stringify(storeAddress.phone || '')}
                },
                fulfillsOnlineOrders: true
              }) {
                location { id name }
                userErrors { code field message }
              }
            }
          `,
        });

        const locAddData = locAddResp.data?.data?.locationAdd;
        if (locAddData?.userErrors?.length > 0) {
          log(shop, `⚠️  [FulfillmentService] locationAdd errors: ${JSON.stringify(locAddData.userErrors)}`);
        } else if (locAddData?.location?.id) {
          customLocationId = locAddData.location.id;
          log(shop, `✅ [FulfillmentService] Custom location created: ${customLocationId}`);
        }
      } catch (locErr) {
        log(shop, `⚠️  [FulfillmentService] locationAdd threw: ${locErr.message}`);
      }
    }

    // Use custom location if created, otherwise fall back to fulfillment service location
    const locationId = customLocationId || serviceFallbackLocationId;
    log(shop, `📍 [FulfillmentService] Final locationId: ${locationId} (${customLocationId ? 'custom' : 'service fallback'})`);

    return { fulfillmentService, locationId };

  } catch (error) {
    const errDetail = error.response ? JSON.stringify(error.response.data) : error.message;
    log(shop, `💥 [FulfillmentService] Request failed: ${errDetail}`);
    return { fulfillmentService: null, locationId: null };
  }
}

module.exports = { createFulfillmentService };
