import axios from 'axios';
import https from 'https';
import fs from 'fs';
import readline from 'readline';
import path from 'path';
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';

// ─── HELPERS ────────────────────────────────────────────────────────────────────
function timestamp() {
    const now = new Date();
    const yyyy = now.getFullYear();
    const MM = String(now.getMonth() + 1).padStart(2, '0');
    const dd = String(now.getDate()).padStart(2, '0');
    const hh = String(now.getHours()).padStart(2, '0');
    const mm = String(now.getMinutes()).padStart(2, '0');
    const ss = String(now.getSeconds()).padStart(2, '0');
    return `${yyyy}${MM}${dd}_${hh}${mm}${ss}`;
}

// ─── GLOBALS ─────────────────────────────────────────────────────────────────────
const desiredInventoryByHandle = {};
const exportDir = path.join(path.dirname(new URL(import.meta.url).pathname), 'exports');

// ─── 1. START BULK EXPORT ────────────────────────────────────────────────────────
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) {
        console.error('[1] ❌ Errors starting export:', err);
        throw new Error('Error starting export');
    }

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

// ─── 2. POLL UNTIL READY ─────────────────────────────────────────────────────────
async function pollUntilReady() {
    console.log('[2] Polling for bulk-export completion…');
    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. URL:', op.url);
            return op.url;
        }
        if (op.status === 'FAILED') {
            console.error('[2] ❌ Failed with code:', op.errorCode);
            throw new Error('Bulk operation failed');
        }

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

// ─── 3. DOWNLOAD FILE ────────────────────────────────────────────────────────────
async function downloadToFile(fileUrl) {
    const fname = path.join(exportDir, `${timestamp()}_bulk_export.ndjson`);
    console.log('[3] Downloading export to', fname);

    const fileStream = fs.createWriteStream(fname);
    await new Promise((resolve, reject) => {
        https.get(fileUrl, res => {
            res.pipe(fileStream);
            fileStream.on('finish', () => {
                console.log('[3] ✔️ Download complete');
                fileStream.close(resolve);
            });
            fileStream.on('error', err => {
                console.error('[3] ❌ Download error:', err);
                reject(err);
            });
        });
    });

    return fname;
}

// ─── 4. PARSE HANDLE MAP ─────────────────────────────────────────────────────────
// async function buildHandleMap(ndjsonPath) {
//     console.log('[4] Parsing NDJSON and building handle map…');
//     const handleMap = {};
//     let totalLines = 0;

//     const rl = readline.createInterface({
//         input: fs.createReadStream(ndjsonPath),
//         crlfDelay: Infinity
//     });

//     desiredInventoryByHandle["84485"] = 2000;

//     for await (const line of rl) {
//         totalLines++;
//         try {
//             const rec = JSON.parse(line);
//             const h = rec.handle;
//             if (desiredInventoryByHandle.hasOwnProperty(h)) {
//                 const invtdataline = JSON.parse(line + 1);
//                 handleMap[h] = {
//                     variantId: invtdataline.id,
//                     inventoryItemId: invtdataline.inventoryItem.id
//                 };
//             }
//         } catch (e) {
//             console.error('[4] ⚠️ JSON parse error on line', totalLines, e);
//         }
//     }

//     console.log(handleMap)
//     console.log(`[4] ✔️ Parsed ${totalLines} lines. Matched handles:`, Object.keys(handleMap));

//     const mapPath = path.join(exportDir, `${timestamp()}_handle_map.json`);
//     fs.writeFileSync(mapPath, JSON.stringify(handleMap, null, 2));
//     console.log('[4] ✔️ Saved handle→inventory map to', mapPath);

//     return handleMap;
// }

async function buildHandleMap(ndjsonPath) {
    console.log('[4] Parsing NDJSON and building handle map…');
    desiredInventoryByHandle["84485"] = 2000;

    const handleMap = {};
    const productIdToHandle = {};
    let totalLines = 0;

    const rl = readline.createInterface({
        input: fs.createReadStream(ndjsonPath),
        crlfDelay: Infinity
    });

    for await (const line of rl) {
        totalLines++;
        try {
            const rec = JSON.parse(line);

            // It's a product line
            if (rec.handle && rec.id) {
                productIdToHandle[rec.id] = rec.handle;
            }

            // It's a variant line
            if (rec.__parentId && rec.inventoryItem && rec.inventoryItem.id) {
                const handle = productIdToHandle[rec.__parentId];
                if (handle && desiredInventoryByHandle.hasOwnProperty(handle)) {
                    if (!handleMap[handle]) handleMap[handle] = [];

                    handleMap[handle].push({
                        variantId: rec.id,
                        inventoryItemId: rec.inventoryItem.id
                    });
                }
            }
        } catch (e) {
            console.error('[4] ⚠️ JSON parse error on line', totalLines, e);
        }
    }

    console.log(`[4] ✔️ Parsed ${totalLines} lines. Matched handles: ${Object.keys(handleMap).length}`);

    // Save map to disk if needed
    const mapPath = path.join(exportDir, `${timestamp()}_handle_map.json`);
    fs.writeFileSync(mapPath, JSON.stringify(handleMap, null, 2));
    console.log('[4] ✔️ Saved handle→inventory map to', mapPath);

    return handleMap;
}


function writeBulkInventoryJSONL(handleMap, desiredInventoryByHandle, outputPath) {
    console.log('[5] Creating JSONL file for bulk inventory update…');
    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 }) => {
            const line = JSON.stringify({
                input: {
                    inventoryItemId,
                    availableDelta: qty
                }
            });
            stream.write(line + '\n');
            lineCount++;
        });
    }

    stream.end();
    console.log(`[5] ✔️ Wrote ${lineCount} inventory adjustments to ${outputPath}`);
}

// ─── 5. BUILD BULK MUTATION ───────────────────────────────────────────────────────
function makeBulkUpdateMutation(handleMap) {

    const filePath = path.join(__dirname, 'exports', 'bulk_inventory.jsonl');


    // Create the JSONL file instead of building a GraphQL mutation string
    writeBulkInventoryJSONL(handleMap, desiredInventoryByHandle, filePath);


    console.log('[6] Building bulk update mutation…');
    const ops = [];

    for (const [handle, items] of Object.entries(handleMap)) {
        const qty = desiredInventoryByHandle[handle];
        items.forEach(({ inventoryItemId }) => {
            ops.push(`
        inventoryAdjustQuantity(
          input: {inventoryItemId: "${inventoryItemId}", availableDelta: ${qty}}
        ) {
          inventoryLevel { id available }
          userErrors { field message }
        }
      `);
        });
    }

    const full = `
    mutation {
      bulkOperationRunMutation(
        mutation: """
        mutation {
          ${ops.join('\n')}
        }
        """
      ) {
        bulkOperation { id status }
        userErrors { field message }
      }
    }
  `;
    console.log('[6] ✔️ Mutation built with', ops.length, 'operations');
    console.log(full)
    return full;
}

// ─── FETCH LOCATIONS (OPTIONAL DEBUGGING) ────────────────────────────────────────
async function fetchAllLocations(pageSize = 250) {
    const endpoint = `https://${SHOP}/admin/api/${API_VERSION}/graphql.json`;
    let hasNextPage = true;
    let cursor = null;
    const allLocations = [];

    while (hasNextPage) {
        const query = `
      query ($first: Int!, $after: String) {
        locations(first: $first, after: $after) {
          pageInfo {
            hasNextPage
          }
          edges {
            cursor
            node {
              id
              name
            }
          }
        }
      }
    `;
        const variables = { first: pageSize, after: cursor };

        const resp = await axios.post(
            endpoint,
            { query, variables },
            { headers: { 'X-Shopify-Access-Token': ACCESS_TOKEN } }
        );

        const locs = resp.data.data.locations;
        locs.edges.forEach(edge => {
            allLocations.push(edge.node);
        });

        hasNextPage = locs.pageInfo.hasNextPage;
        cursor = hasNextPage ? locs.edges[locs.edges.length - 1].cursor : null;
    }

    console.log(`✅ Retrieved ${allLocations.length} locations`);
    return allLocations;
}

// ─── MAIN ─────────────────────────────────────────────────────────────────────────
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('✅ Inventory fetched from Turn14:', Object.keys(desiredInventoryByHandle).length, 'items');
    //console.log(desiredInventoryByHandle);

    if (!fs.existsSync(exportDir)) {
        console.log('Creating exports directory at', exportDir);
        fs.mkdirSync(exportDir);
    }

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

    const mutation = makeBulkUpdateMutation(handleMap);
    console.log('[5] Kicking off inventory update…');

    const resp = await axios.post(
        `https://${SHOP}/admin/api/${API_VERSION}/graphql.json`,
        { query: mutation },
        { headers: { 'X-Shopify-Access-Token': ACCESS_TOKEN } }
    );
    console.log('🚧 Full response:', JSON.stringify(resp.data, null, 2));

    console.log(resp.data.data)

    const errs = resp.data.data.bulkOperationRunMutation.userErrors;
    if (errs.length) {
        console.error('[5] ❌ Inventory bulk update errors:', errs);
    } else {
        console.log('[5] ✔️ Inventory bulk update kickstarted successfully');
    }
} catch (err) {
    console.error('🚨 Uncaught error:', err);
    process.exit(1);
}
