const fs = require('fs');
const path = require('path');

const dataDir = path.join(__dirname, '..', 'data');
const snapshotPath = path.join(dataDir, 'mongo-read-snapshot.json');

function normalizeState(state = {}) {
  return {
    proofs: Array.isArray(state.proofs) ? state.proofs : [],
    transactions: Array.isArray(state.transactions) ? state.transactions : [],
    pointEntries: Array.isArray(state.pointEntries) ? state.pointEntries : [],
    blocks: Array.isArray(state.blocks) ? state.blocks : [],
    nodes: Array.isArray(state.nodes) ? state.nodes : [],
    nodeEconomyEntries: Array.isArray(state.nodeEconomyEntries) ? state.nodeEconomyEntries : [],
    validatorVotes: Array.isArray(state.validatorVotes) ? state.validatorVotes : [],
    callbackEvents: Array.isArray(state.callbackEvents) ? state.callbackEvents : [],
    backupIndexes: Array.isArray(state.backupIndexes) ? state.backupIndexes : [],
    distributedChunks: Array.isArray(state.distributedChunks) ? state.distributedChunks : [],
    wallets: Array.isArray(state.wallets) ? state.wallets : [],
    walletTransactions: Array.isArray(state.walletTransactions) ? state.walletTransactions : [],
    trxCollateralAccounts: Array.isArray(state.trxCollateralAccounts) ? state.trxCollateralAccounts : [],
    trxCollateralEvents: Array.isArray(state.trxCollateralEvents) ? state.trxCollateralEvents : [],
    settings: state.settings && typeof state.settings === 'object' && !Array.isArray(state.settings) ? state.settings : {},
    rewardEntries: Array.isArray(state.rewardEntries) ? state.rewardEntries : [],
    rewardAuditEntries: Array.isArray(state.rewardAuditEntries) ? state.rewardAuditEntries : [],
    rewardReviewDecisions: Array.isArray(state.rewardReviewDecisions) ? state.rewardReviewDecisions : []
  };
}

function countRows(state = {}) {
  return Object.values(normalizeState(state)).reduce((sum, rows) => {
    if (!Array.isArray(rows)) return sum;
    return sum + rows.length;
  }, 0);
}

function readSnapshot() {
  const body = JSON.parse(fs.readFileSync(snapshotPath, 'utf8'));
  const state = normalizeState(body.state || {});
  const totalRows = countRows(state);
  if (!body.ok) throw new Error('Mongo read snapshot is not marked ok.');
  if (totalRows !== Number(body.totalDocuments || 0)) {
    throw new Error(`Mongo read snapshot row count mismatch: ${totalRows} != ${body.totalDocuments}`);
  }
  return { ...body, state, totalRows, path: snapshotPath };
}

function getStatus() {
  try {
    const stat = fs.statSync(snapshotPath);
    const snapshot = readSnapshot();
    return {
      exists: true,
      ok: true,
      path: snapshotPath,
      mode: snapshot.mode || 'mongo-read-snapshot',
      totalDocuments: snapshot.totalRows,
      sourceReadAt: snapshot.sourceReadAt || null,
      createdAt: snapshot.createdAt || null,
      fileUpdatedAt: stat.mtime.toISOString()
    };
  } catch (err) {
    return {
      exists: fs.existsSync(snapshotPath),
      ok: false,
      path: snapshotPath,
      mode: 'not-ready',
      totalDocuments: 0,
      sourceReadAt: null,
      createdAt: null,
      error: err.message
    };
  }
}

function writeSnapshotFromState(state = {}, options = {}) {
  const normalized = normalizeState(state);
  const totalDocuments = countRows(normalized);
  const output = {
    ok: true,
    mode: 'mongo-read-snapshot',
    source: options.source || 'persistentStore.writeState',
    sourceReadAt: options.sourceReadAt || new Date().toISOString(),
    compareCheckedAt: options.compareCheckedAt || null,
    totalDocuments,
    state: normalized,
    createdAt: new Date().toISOString(),
    path: snapshotPath
  };
  fs.mkdirSync(path.dirname(snapshotPath), { recursive: true });
  fs.writeFileSync(snapshotPath, `${JSON.stringify(output, null, 2)}\n`);
  return { ...output, state: undefined };
}
function readSnapshotState() {
  return readSnapshot().state;
}

module.exports = {
  snapshotPath,
  normalizeState,
  countRows,
  getStatus,
  readSnapshot,
  writeSnapshotFromState,
  readSnapshotState
};
