const fs = require('fs/promises');
const { hashObject, nowIso } = require('./utils');

async function loadState(filePath) {
  try {
    const raw = await fs.readFile(filePath, 'utf8');
    if (!raw.trim()) {
      return null;
    }
    return JSON.parse(raw);
  } catch (error) {
    if (error.code === 'ENOENT') {
      return null;
    }

    if (error instanceof SyntaxError) {
      return null;
    }

    throw error;
  }
}

async function saveState(filePath, items) {
  const payload = {
    savedAt: nowIso(),
    hash: hashObject(items),
    items
  };
  await fs.writeFile(filePath, JSON.stringify(payload, null, 2), 'utf8');
  return payload;
}

function diffItems(previousItems = [], currentItems = []) {
  const prevMap = new Map(previousItems.map((item) => [item.__key, item]));
  const currMap = new Map(currentItems.map((item) => [item.__key, item]));

  const changes = [];

  for (const [key, item] of currMap) {
    if (!prevMap.has(key)) {
      changes.push({ type: 'added', item });
      continue;
    }

    const prev = prevMap.get(key);
    const prevComparable = JSON.stringify(prev);
    const currComparable = JSON.stringify(item);
    if (prevComparable !== currComparable) {
      changes.push({ type: 'updated', before: prev, after: item });
    }
  }

  for (const [key, item] of prevMap) {
    if (!currMap.has(key)) {
      changes.push({ type: 'removed', item });
    }
  }

  return changes;
}

module.exports = {
  loadState,
  saveState,
  diffItems
};
