import axios from 'axios';
import https from 'https';
import fs from 'fs';
import readline from 'readline';
import path from 'path';
import FormData from 'form-data';
import { fileURLToPath } from 'url';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// ─── CONFIG ────────────────────────────────────────────────────────
const SHOP = 'veloxautomotive.myshopify.com';
const ACCESS_TOKEN = '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';
const API_VERSION = '2023-10';
const TURN14_ACCESS_TOKEN = '4d82c2d2a2ddb59a6da68afb722f50dd43f4640b';
const exportDir = path.join(__dirname, 'exports');
const JSONL_FILENAME = 'bulk_inventory.jsonl';

const desiredInventoryByHandle = {};

// ─── HELPERS ────────────────────────────────────────────────────────
function timestamp() {
    const now = new Date();
    return now.toISOString().replace(/[-:]/g, '').replace('T', '_').split('.')[0];
}

// ─── STAGE FILE UPLOAD ──────────────────────────────────────────────
async function getStagedUploadPath() {
    const mutation = `
    mutation {
      stagedUploadsCreate(input:[{
        resource: BULK_MUTATION_VARIABLES,
        filename: "${JSONL_FILENAME}",
        mimeType: "text/jsonl",
        httpMethod: POST
      }]){
        stagedTargets {
          url
          resourceUrl
          parameters { name value }
        }
        userErrors { field message }
      }
    }
  `;

    const resp = await axios.post(
        `https://${SHOP}/admin/api/${API_VERSION}/graphql.json`,
        { query: mutation },
        { headers: { 'X-Shopify-Access-Token': ACCESS_TOKEN } }
    );

    const result = resp.data.data.stagedUploadsCreate;

    if (result.userErrors.length) {
        throw new Error('Staged upload error: ' + JSON.stringify(result.userErrors));
    }

    const target = result.stagedTargets[0];
    const keyParam = target.parameters.find(p => p.name === 'key');
    if (!keyParam) throw new Error('Missing "key" parameter in staged upload target');

   // console.log("target",target)
    return {
        uploadUrl: target.url,
        parameters: target.parameters,
        stagedUploadPath: keyParam.value,
    };
}

async function uploadJSONLFile(uploadUrl, params, filePath) {
    const form = new FormData();
    params.forEach(({ name, value }) => form.append(name, value));
    form.append('file', fs.createReadStream(filePath));

    await axios.post(uploadUrl, form, {
        headers: form.getHeaders()
    });

    console.log('✅ Uploaded JSONL file to Shopify');
}

async function runBulkMutation(stagedUploadPath) {

    console.log("Resource URL",stagedUploadPath)
    const mutation = `
    mutation bulkInventoryAdjust($input: InventoryAdjustQuantityInput!) {
      inventoryAdjustQuantity(input: $input) {
        inventoryLevel { id available }
        userErrors { field message }
      }
    }
  `;

    const wrappedMutation = `
    mutation {
      bulkOperationRunMutation(
        mutation: """${mutation}""",
        stagedUploadPath: "${stagedUploadPath}"
      ) {
        bulkOperation { id status }
        userErrors { field message }
      }
    }
  `;

    const resp = await axios.post(
        `https://${SHOP}/admin/api/${API_VERSION}/graphql.json`,
        { query: wrappedMutation },
        { headers: { 'X-Shopify-Access-Token': ACCESS_TOKEN } }
    );

    console.log('📦 Mutation Response:', JSON.stringify(resp.data, null, 2));

    const result = resp.data.data?.bulkOperationRunMutation;
    if (!result) throw new Error('bulkOperationRunMutation failed.');

    if (result.userErrors.length) {
        console.error('❌ Mutation Errors:', result.userErrors);
    } else {
        console.log('✅ Bulk inventory update started with ID:', result.bulkOperation.id);
    }
}

// ─── EXPORT / NDJSON LOGIC ─────────────────────────────────────────
async function startBulkExport() {
    console.log('[1] Starting bulk export...');
    const mutation = `
    mutation {
      bulkOperationRunQuery(
        query: """
        {
          products {
            edges {
              node {
                id
                handle
                variants {
                  edges {
                    node {
                      id
                      inventoryItem { id }
                    }
                  }
                }
              }
            }
          }
        }
        """
      ) {
        bulkOperation { id status }
        userErrors { field message }
      }
    }
  `;

    const resp = await axios.post(
        `https://${SHOP}/admin/api/${API_VERSION}/graphql.json`,
        { query: mutation },
        { headers: { 'X-Shopify-Access-Token': ACCESS_TOKEN } }
    );

    const err = resp.data.data.bulkOperationRunQuery.userErrors;
    if (err.length) throw new Error(JSON.stringify(err));

    console.log('[1] ✔️ Export started:', resp.data.data.bulkOperationRunQuery.bulkOperation.id);
}

async function pollUntilReady() {
    const query = `{
    currentBulkOperation {
      status
      url
      errorCode
    }
  }`;

    while (true) {
        const resp = await axios.post(
            `https://${SHOP}/admin/api/${API_VERSION}/graphql.json`,
            { query },
            { headers: { 'X-Shopify-Access-Token': ACCESS_TOKEN } }
        );

        const op = resp.data.data.currentBulkOperation;
        console.log(`[2] Status: ${op.status}`);

        if (op.status === 'COMPLETED') {
            console.log('[2] ✔️ Completed export. File URL:', op.url);
            return op.url;
        }
        if (op.status === 'FAILED') {
            throw new Error('Bulk export failed: ' + op.errorCode);
        }

        await new Promise(r => setTimeout(r, 5000));
    }
}

async function downloadToFile(fileUrl) {
    const fname = path.join(exportDir, `${timestamp()}_bulk_export.ndjson`);
    const fileStream = fs.createWriteStream(fname);
    await new Promise((resolve, reject) => {
        https.get(fileUrl, res => {
            res.pipe(fileStream);
            fileStream.on('finish', () => {
                fileStream.close(resolve);
            });
            fileStream.on('error', reject);
        });
    });
    console.log(`[3] ✔️ Downloaded export to ${fname}`);
    return fname;
}

async function buildHandleMap(ndjsonPath) {
    console.log('[4] Building handle→inventory map...');
    const handleMap = {};
    const productIdToHandle = {};
    desiredInventoryByHandle["84485"] = 2000;
    const rl = readline.createInterface({
        input: fs.createReadStream(ndjsonPath),
        crlfDelay: Infinity
    });

    for await (const line of rl) {
        try {
            const rec = JSON.parse(line);
            if (rec.handle && rec.id) {
                productIdToHandle[rec.id] = rec.handle;
            }
            if (rec.__parentId && rec.inventoryItem?.id) {
                const handle = productIdToHandle[rec.__parentId];
                if (handle && desiredInventoryByHandle[handle] != null) {
                    if (!handleMap[handle]) handleMap[handle] = [];
                    handleMap[handle].push({
                        variantId: rec.id,
                        inventoryItemId: rec.inventoryItem.id
                    });
                }
            }
        } catch (e) {
            console.error('⚠️ JSON parse error:', e.message);
        }
    }

    console.log(`[4] ✔️ Matched ${Object.keys(handleMap).length} handles`);
    const mapPath = path.join(exportDir, `${timestamp()}_handle_map.json`);
    fs.writeFileSync(mapPath, JSON.stringify(handleMap, null, 2));
    return handleMap;
}

// function writeBulkInventoryJSONL(handleMap, desiredInventoryByHandle, outputPath) {
//     const stream = fs.createWriteStream(outputPath);
//     let lineCount = 0;

//     for (const [handle, items] of Object.entries(handleMap)) {
//         const qty = desiredInventoryByHandle[handle];
//         if (qty == null) continue;

//         items.forEach(({ inventoryItemId }) => {
//             stream.write(JSON.stringify({ input: { inventoryItemId, availableDelta: qty } }) + '\n');
//             lineCount++;
//         });
//     }

//     stream.end();
//     console.log(`✅ JSONL: wrote ${lineCount} inventory adjustments to ${outputPath}`);
// }



function writeBulkInventoryJSONL(handleMap, desiredInventoryByHandle, outputPath, locationId) {
  const stream = fs.createWriteStream(outputPath);
  let lineCount = 0;

  const inventoryUpdates = [];

  for (const [handle, items] of Object.entries(handleMap)) {
    const qty = desiredInventoryByHandle[handle];
    if (qty == null) continue;

    items.forEach(({ inventoryItemId }) => {
      inventoryUpdates.push({
        inventoryItemId,
        availableDelta: qty,
        locationId,
      });
      lineCount++;
    });
  }

  // Write all entries to the JSONL stream
  inventoryUpdates.forEach((entry) => {
    stream.write(JSON.stringify({ input: entry }) + '\n');
  });

  stream.end();
  console.log(`✅ JSONL: wrote ${lineCount} inventory adjustments to ${outputPath}`);
}



// ─── MAIN FLOW ─────────────────────────────────────────────────────
try {
    const turn14Res = await fetch(`https://turn14.data4autos.com/v1/inventory/allupdates`, {
        headers: {
            Authorization: `Bearer ${TURN14_ACCESS_TOKEN}`,
            "Content-Type": "application/json",
        },
    });
    const turn14Data = await turn14Res.json();

    for (const item of turn14Data) {
        desiredInventoryByHandle[item.id] = item.totalQuantity;
    }

    console.log(`✅ Loaded ${Object.keys(desiredInventoryByHandle).length} inventory items from Turn14`);

    if (!fs.existsSync(exportDir)) fs.mkdirSync(exportDir);

    await startBulkExport();
    const url = await pollUntilReady();
    const ndjsonPath = await downloadToFile(url);
    const handleMap = await buildHandleMap(ndjsonPath);

    const jsonlPath = path.join(exportDir, JSONL_FILENAME);

    console.log(handleMap)
    // writeBulkInventoryJSONL(handleMap, desiredInventoryByHandle, jsonlPath);

    // const { uploadUrl, stagedUploadPath, parameters } = await getStagedUploadPath();

    // console.log()
    // await uploadJSONLFile(uploadUrl, parameters, jsonlPath);
    // await runBulkMutation(stagedUploadPath);
} catch (err) {
    console.error('🚨 Error:', err);
    process.exit(1);
}
