// routes/manageBrands.js
const express = require('express');
const axios = require('axios');
const { v4: uuid } = require('uuid');
const { getToken } = require('../tokenStore');
const { log } = require('../logger');

const router = express.Router();
const API_VERSION = '2023-10';
// Simple in-memory process tracker
const processes = {};

function slugify(str) {
  return str
    .toString()
    .trim()
    .toLowerCase()
    .replace(/[^a-z0-9]+/g, '-')
    .replace(/^-+|-+$/g, '');
}


const GetAllProductsOfBranch = async (brandId, turn14accessToken) => {
  var AllProductsOfBrans = [];

  try {
    const res = await fetch(`https://turn14.data4autos.com/v1/items/brandallitems/${brandId}`, {
      headers: {
        Authorization: `Bearer ${turn14accessToken}`,
        "Content-Type": "application/json",
      },
    });
    const data = await res.json();
    // Ensure we have an array of valid items
    const validItems = Array.isArray(data)
      ? data.filter(item => item && item.id && item.attributes)
      : [];
    AllProductsOfBrans = validItems
    console.log("AllProductsOfBrans", AllProductsOfBrans.length);
    const items = Array.isArray(AllProductsOfBrans) ? AllProductsOfBrans.slice(0, 5) : [];
    console.log("items", items.length);

    return items;
  } catch (err) {  
    console.error("Error fetching items:", err);
    return null
  }
}

const AddProductToStore = async (shop, accessToken, product) => {
  var results = [];
  const SHOP = shop
  const ACCESS_TOKEN = accessToken
  const item = product;


  const client = axios.create({
    baseURL: `https://${SHOP}/admin/api/${API_VERSION}/graphql.json`,
    headers: {
      'X-Shopify-Access-Token': ACCESS_TOKEN,
      'Content-Type': 'application/json',
    },
  });


  try {

    const attrs = item.attributes;
    //  console.log("Processing item:", attrs);

    // Build and normalize collection titles
    const category = attrs.category;
    const subcategory = attrs.subcategory || "";
    const brand = attrs.brand;
    const subcats = subcategory
      .split(/[,\/]/)
      .map((s) => s.trim())
      .filter(Boolean);
    const collectionTitles = Array.from(
      new Set([category, ...subcats, brand].filter(Boolean))
    );
    // console.log("Collection Titles:", collectionTitles);

    // Find or create collections, collect their IDs
    const collectionIds = []

    for (const title of collectionTitles) {
      //  console.log(`Searching for collection "${title}"…`);

      // 1. Query existing manual collection by title
      const lookupQuery = `
      query {
        collections(first: 1, query: "title:\\"${title}\\" AND collection_type:manual") {
          nodes { id }
        }
      }
    `;
      const lookupResp = await client.post('', { query: lookupQuery });
      const existing = lookupResp.data.data.collections.nodes;

      if (existing.length) {
        console.log(`→ Found existing collection: ${existing[0].id}`);
        collectionIds.push(existing[0].id);
        continue;
      }

      // 2. Otherwise, create it
      //console.log(`→ No existing collection. Creating "${title}"…`);
      const createMutation = `
      mutation collectionCreate($input: CollectionInput!) {
        collectionCreate(input: $input) {
          collection { id }
          userErrors { field message }
        }
      }
    `;
      const createResp = await client.post('', {
        query: createMutation,
        variables: { input: { title } }
      });
      const createData = createResp.data.data.collectionCreate;
      if (createData.userErrors.length) {
        throw new Error(
          `Could not create collection "${title}": ` +
          createData.userErrors.map(e => e.message).join(', ')
        );
      }
      const newId = createData.collection.id;
      //   console.log(`→ Created collection: ${newId}`);
      collectionIds.push(newId);

    }



    // Build tags
    const tags = [
      attrs.category,
      ...subcats,
      attrs.brand,
      attrs.part_number,
      attrs.mfr_part_number,
      attrs.price_group,
      attrs.units_per_sku && `${attrs.units_per_sku} per SKU`,
      attrs.barcode
    ].filter(Boolean).map((t) => t.trim());
    // console.log("Tags:", tags);

    // Prepare media inputs
    const mediaInputs = (attrs.files || [])
      .filter((f) => f.type === "Image" && f.url)
      .map((file) => ({
        originalSource: file.url,
        mediaContentType: "IMAGE",
        alt: `${attrs.product_name} — ${file.media_content}`,
      }));
    // console.log("Media inputs:", mediaInputs);

    // Pick the longest "Market Description" or fallback to part_description
    const marketDescs = (attrs.descriptions || [])
      .filter((d) => d.type === "Market Description")
      .map((d) => d.description);
    const descriptionHtml = marketDescs.length
      ? marketDescs.reduce((a, b) => (b.length > a.length ? b : a))
      : attrs.part_description;
    // console.log("Description HTML:", descriptionHtml);

    // Create product + attach to collections + add media
    // const createProdRes = await admin.graphql(`
    //   mutation($prod: ProductCreateInput!, $media: [CreateMediaInput!]) {
    //     productCreate(product: $prod, media: $media) {
    //       product {
    //         id
    //         variants(first: 1) {
    //           nodes { id inventoryItem { id } price compareAtPrice barcode }
    //         }
    //       }
    //       userErrors { field message }
    //     }
    //   }
    // `, {
    //   variables: {
    //     prod: {
    //       title: attrs.product_name,
    //       descriptionHtml: descriptionHtml,
    //       vendor: attrs.brand,
    //       productType: attrs.category,
    //       handle: slugify(attrs.part_number || attrs.product_name),
    //       tags,
    //       collectionsToJoin: collectionIds,
    //       status: "ACTIVE",
    //     },
    //     media: mediaInputs,
    //   },
    // });


    //   const createProdRes = await client.post('', {
    //     query: `
    //   mutation($prod: ProductCreateInput!, $media: [CreateMediaInput!]) {
    //     productCreate(product: $prod, media: $media) {
    //       product {
    //         id
    //         variants(first: 1) {
    //           nodes {
    //             id
    //             inventoryItem { id }
    //             price
    //             compareAtPrice
    //             barcode
    //           }
    //         }
    //       }
    //       userErrors { field message }
    //     }
    //   }
    // `,
    //     variables: {
    //       prod: {
    //         title: attrs.product_name,
    //         descriptionHtml: descriptionHtml,
    //         vendor: attrs.brand,
    //         productType: attrs.category,
    //         handle: slugify(item.id + "-" + attrs.mfr_part_number || attrs.product_name),
    //         tags,
    //         collectionsToJoin: collectionIds,
    //         status: "ACTIVE",
    //       },
    //       media: mediaInputs,
    //     },
    //   });

    //   const createProdJson = createProdRes.data;
    //   console.log("Create product response:", createProdJson);

    //   const prodErrs = createProdJson.data?.productCreate?.userErrors || [];
    //   if (prodErrs.length) {
    //     const taken = prodErrs.some(e => /already in use/i.test(e.message));
    //     if (taken) {
    //       results.push({ skippedHandle: attrs.part_number, reason: "handle in use" });
    //       return null 
    //     }
    //     throw new Error(`ProductCreate errors: ${prodErrs.map(e => e.message).join(", ")}`);
    //   }

    //   const product = createProdJson.data.productCreate.product;

    const createProdRes = await client.post('', {
      query: `
    mutation($prod: ProductInput!, $media: [CreateMediaInput!]) {
      productCreate(input: $prod, media: $media) {
        product {
          id
          variants(first: 1) {
            nodes {
              id
              inventoryItem { id }
              price
              compareAtPrice
              barcode
            }
          }
        }
        userErrors { field message }
      }
    }
  `,
      variables: {
        prod: {
          title: attrs.product_name,
          descriptionHtml: descriptionHtml,
          vendor: attrs.brand,
          productType: attrs.category,
          handle: slugify(item.id + "-" + (attrs.mfr_part_number || attrs.product_name)),
          tags,
          collectionsToJoin: collectionIds,
          status: "ACTIVE",
        },
        media: mediaInputs,
      },
    });
 
    const createProdJson = createProdRes.data;
    //console.log("Create product response:", createProdJson);

    const prodErrs = createProdJson.data?.productCreate?.userErrors || [];
    if (prodErrs.length) {
      const taken = prodErrs.some(e => /already in use/i.test(e.message));
      if (taken) {
        results.push({ skippedHandle: attrs.part_number, reason: "handle in use" });
        return null;
      }
      throw new Error(`ProductCreate errors: ${prodErrs.map(e => e.message).join(", ")}`);
    }

    const product = createProdJson.data.productCreate.product;
    const variantNode = product.variants?.nodes?.[0];
    if (!variantNode) {
      console.error("Variant node is undefined for product:", product.id);
      return null
    }

    const variantId = variantNode.id;
    const inventoryItemId = variantNode.inventoryItem?.id;



    // Bulk-update variant (price, compare-at, barcode)
    const price = parseFloat(attrs.price) || 1000;
    const comparePrice = parseFloat(attrs.compare_price) || null;
    const barcode = attrs.barcode || "";

    const bulkRes = await client.post('', {
      query: `
    mutation($productId: ID!, $variants: [ProductVariantsBulkInput!]!) {
      productVariantsBulkUpdate(productId: $productId, variants: $variants) {
        productVariants {
          id
          price
          compareAtPrice
          barcode
        }
        userErrors {
          field
          message
        }
      }
    }
  `,
      variables: {
        productId: product.id,
        variants: [{
          id: variantId,
          price,
          ...(comparePrice !== null && { compareAtPrice: comparePrice }),
          ...(barcode && { barcode }),
        }],
      },
    });
    const bulkJson = bulkRes.data;
    const bulkErrs = bulkJson.data.productVariantsBulkUpdate.userErrors;
    if (bulkErrs.length) {
      throw new Error(`Bulk update errors: ${bulkErrs.map(e => e.message).join(", ")}`);
    }


    // Fetch the Online Store publication ID
    //console.log("Fetching Online Store publication ID...");
    const publicationsRes = await client.post('', { 
      query: `
    query {
      publications(first: 10) {
        edges {
          node {
            id
            name
          }
        }
      }
    }
  `
    });
    const publicationsJson = publicationsRes.data;
    // console.log("Publications response:", publicationsJson);

    const onlineStorePublication = publicationsJson.data.publications.edges.find(
      pub => pub.node.name === 'Online Store'
    );
    const onlineStorePublicationId = onlineStorePublication ? onlineStorePublication.node.id : null;
    if (onlineStorePublicationId) {
      //  console.log("Publishing product to Online Store...");

      // ▶︎ Replace admin.graphql(…) with:
      const publishRes = await client.post('', {
        query: `
      mutation($id: ID!, $publicationId: ID!) {
        publishablePublish(id: $id, input: { publicationId: $publicationId }) {
          publishable {
            ... on Product {
              id
              title
              status
            }
          }
          userErrors { field message }
        }
      }
    `,
        variables: {
          id: product.id,
          publicationId: onlineStorePublicationId,
        },
      });

      const publishJson = publishRes.data;
      console.log("Publish response:", publishJson);

      const publishErrs = publishJson.data.publishablePublish.userErrors;
      if (publishErrs.length) {
        throw new Error(`Publish errors: ${publishErrs.map(e => e.message).join(", ")}`);
      }
    } else {
      throw new Error("Online Store publication not found.");
    }


    // Update inventory item (SKU, cost & weight)
    const costPerItem = parseFloat(attrs.purchase_cost) || 0;
    const weightValue = parseFloat(attrs.dimensions?.[0]?.weight) || 0;

    //   console.log("Updating inventory item...");
    //   const invRes = await client.post('', {
    //     query: `
    //   mutation($id: ID!, $input: InventoryItemInput!) {
    //     inventoryItemUpdate(id: $id, input: $input) {
    //       inventoryItem {
    //         id
    //         sku
    //         measurement {
    //           weight { value unit }
    //         }
    //       }
    //       userErrors { field message }
    //     }
    //   }
    // `,
    //     variables: {
    //       id: inventoryItemId,
    //       input: {
    //         sku: attrs.part_number,
    //         cost: parseFloat(attrs.purchase_cost) || 0,
    //         measurement: {
    //           weight: {
    //             value: parseFloat(attrs.dimensions?.[0]?.weight) || 0,
    //             unit: "POUNDS"
    //           }
    //         }
    //       }
    //     }
    //   });

    //   const invJson = invRes.data;
    //   console.log("Inventory update response:", invJson);

    //   const invErrs = invJson.data.inventoryItemUpdate.userErrors;
    //   if (invErrs.length) {
    //     throw new Error(`Inventory update errors: ${invErrs.map(e => e.message).join(", ")}`);
    //   }
    //   const inventoryItem = invJson.data.inventoryItemUpdate.inventoryItem;


    //   console.log("Updating inventory item...");
    // const invRes = await client.post('', {
    //   query: `
    //     mutation($id: ID!, $input: InventoryItemUpdateInput!) {
    //       inventoryItemUpdate(id: $id, input: $input) {
    //         inventoryItem {
    //           id
    //           sku
    //           measurement {
    //             weight { value unit }
    //           }
    //         }
    //         userErrors { field message }
    //       }
    //     }
    //   `,
    //   variables: {
    //     id: inventoryItemId,
    //     input: {
    //       sku: attrs.part_number,
    //       cost: parseFloat(attrs.purchase_cost) || 0,
    //       measurement: {
    //         weight: {
    //           value: parseFloat(attrs.dimensions?.[0]?.weight) || 0,
    //           unit: "POUNDS"
    //         }
    //       }
    //     }
    //   }
    // });

    // const invJson = invRes.data;
    // console.log("Inventory update response:", invJson);

    // const invErrs = invJson.data.inventoryItemUpdate.userErrors;
    // if (invErrs.length) {
    //   throw new Error(`Inventory update errors: ${invErrs.map(e => e.message).join(", ")}`);
    // }
    // const inventoryItem = invJson.data.inventoryItemUpdate.inventoryItem;


    console.log("Updating inventory item...");
    const invRes = await client.post('', {
      query: `
    mutation($id: ID!, $input: InventoryItemUpdateInput!) {
      inventoryItemUpdate(id: $id, input: $input) {
        inventoryItem {
          id
          unitCost { amount }
          tracked
        }
        userErrors { field message }
      }
    }
  `,
      variables: {
        id: inventoryItemId,
        input: {
          cost: parseFloat(attrs.purchase_cost) || 0,
          tracked: true
        }
      }
    });

    const invJson = invRes.data;
    console.log("Inventory update response:", invJson);

    const invErrs = invJson.data.inventoryItemUpdate.userErrors;
    if (invErrs.length) {
      throw new Error(`Inventory update errors: ${invErrs.map(e => e.message).join(", ")}`);
    }
    const inventoryItem = invJson.data.inventoryItemUpdate.inventoryItem;





    // Collect results
    results.push({
      productId: product.id,
      variant: {
        id: variantId,
        price: variantNode.price,
        compareAtPrice: variantNode.compareAtPrice,
        sku: inventoryItem.sku,
        barcode: variantNode.barcode,
        weight: inventoryItem?.measurement?.weight.value,
        weightUnit: inventoryItem?.measurement?.weight.unit,
      },
      collections: collectionTitles,
      tags,
    });

    return results;



  } catch (err) {
    console.error("Error in AddProductToStore:", err);
    results.push({ error: `Failed to process item ${item.id}: ${err.message}` });
    return results;
  }
}

const GetAllProductsandAddToStore = async (shop, accessToken, brandId, turn14accessToken) => {
  const products = await GetAllProductsOfBranch(brandId, turn14accessToken);
  if (!products) {
    console.error("No products found or error fetching products.");
    return [];
  }

  const results = [];
  for (const item of products) {
    const res = await AddProductToStore(shop, accessToken, item);
    results.push(...res);
  }
  return results;
}

async function fetchAllCollections(shop, accessToken) {
  const adminUrl = `https://${shop}/admin/api/2023-10/graphql.json`;
  const headers = {
    'X-Shopify-Access-Token': accessToken,
    'Content-Type': 'application/json',
  };

  let allCollections = [];
  let hasNextPage = true;
  let endCursor = null;
  const pageSize = 100;

  while (hasNextPage) {
    const fetchQuery = `
      query GetCollections {
        collections(first: ${pageSize}${endCursor ? `, after: "${endCursor}"` : ''}) {
          edges {
            node {
              id
              title
            }
            cursor
          }
          pageInfo {
            hasNextPage
            endCursor
          }
        }
      }
    `;

    const fetchResp = await axios.post(adminUrl, { query: fetchQuery }, { headers });
    const collections = fetchResp.data.data.collections.edges.map(e => e.node);
    allCollections = allCollections.concat(collections);

    hasNextPage = fetchResp.data.data.collections.pageInfo.hasNextPage;
    endCursor = fetchResp.data.data.collections.pageInfo.endCursor;
  }

  return allCollections;
}



router.post('/', async (req, res) => {
  const { shop, brandID, turn14accessToken } = req.body;

  const procId = uuid();
  processes[procId] = { status: 'started', detail: null };

  res.json({ processId: procId, status: 'started' });

  (async () => {
    try {
      log(shop, `🔔 [${procId}] ManageBrands started`);
      processes[procId].status = 'fetching_collections';

      // 1. Get token
      const tokenRecord = getToken(shop);
      if (!tokenRecord) throw new Error('No token for shop');



      const allCollections = await GetAllProductsandAddToStore(shop, tokenRecord.accessToken, brandID, turn14accessToken);
      log(shop, `🔍 [${procId}] Fetchedd ${allCollections.length} existing collections`);


    } catch (err) {
      processes[procId].status = 'error';
      processes[procId].detail = err.message;
      log(shop, `❌ [${procId}] Error: ${err.message}`);
    }
  })();
});

router.get('/status/:processId', (req, res) => {
  const info = processes[req.params.processId];
  if (!info) return res.status(404).json({ error: 'Not found' });
  res.json(info);
});

module.exports = router;
