const fs = require('fs');
const path = require('path');
const dbLedgerAdapter = require('./dbLedgerAdapter');
const mongoLedgerObservationAdapter = require('./mongoLedgerObservationAdapter');
const mongoLedgerReadAdapter = require('./mongoLedgerReadAdapter');
const mongoReadSnapshotService = require('./mongoReadSnapshotService');
const mongoLedgerLiveWriterAdapter = require('./mongoLedgerLiveWriterAdapter');

const dataDir = path.join(__dirname, '..', 'data');
const ledgerPath = path.join(dataDir, 'ledger.json');

const defaultState = {
  proofs: [],
  transactions: [],
  pointEntries: [],
  blocks: [],
  nodes: [],
  nodeEconomyEntries: [],
  validatorVotes: [],
  callbackEvents: [],
  backupIndexes: [],
  distributedChunks: [],
  wallets: [],
  walletTransactions: [],
  trxCollateralAccounts: [],
  trxCollateralEvents: [],
  settings: {},
  rewardEntries: [],
  rewardAuditEntries: [],
  rewardReviewDecisions: []
};

let currentState = null;

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 ensureDataDir() {
  fs.mkdirSync(dataDir, { recursive: true });
}

function shouldReadMongoSnapshot() {
  const status = mongoLedgerReadAdapter.getStatus();
  return Boolean(status.enabled);
}

function readJsonLedgerState() {
  if (!fs.existsSync(ledgerPath)) {
    writeState(defaultState);
    return normalizeState(defaultState);
  }

  try {
    return normalizeState(JSON.parse(fs.readFileSync(ledgerPath, 'utf8')));
  } catch (err) {
    const backupPath = `${ledgerPath}.broken-${Date.now()}`;
    fs.copyFileSync(ledgerPath, backupPath);
    console.warn(`[persistentStore] Broken ledger backed up to ${backupPath}`);
    writeState(defaultState);
    return normalizeState(defaultState);
  }
}
function readState() {
  if (currentState) return currentState;

  ensureDataDir();

  if (shouldReadMongoSnapshot()) {
    currentState = normalizeState(mongoReadSnapshotService.readSnapshotState());
    return currentState;
  }

  currentState = readJsonLedgerState();
  return currentState;
}

function writeState(state) {
  ensureDataDir();
  const nextState = normalizeState(state);
  const tmpPath = `${ledgerPath}.tmp`;

  fs.writeFileSync(tmpPath, `${JSON.stringify(nextState, null, 2)}\n`);
  fs.renameSync(tmpPath, ledgerPath);
  currentState = nextState;
  try {
    dbLedgerAdapter.writeShadowCollections(nextState);
  } catch (err) {
    console.warn(`[persistentStore] DB shadow dual-write skipped: ${err.message}`);
  }

  mongoLedgerObservationAdapter.writeObservationCollections(nextState).catch((err) => {
    console.warn(`[persistentStore] Mongo observation dual-write skipped: ${err.message}`);
  });

  if (mongoLedgerReadAdapter.isReadEnabled()) {
    try {
      mongoReadSnapshotService.writeSnapshotFromState(nextState, { source: 'persistentStore.writeState' });
    } catch (err) {
      console.warn(`[persistentStore] Mongo read snapshot refresh failed: ${err.message}`);
    }
  }

  mongoLedgerLiveWriterAdapter.writeLiveCollections(nextState, { reason: 'persistentStore.writeState' }).catch((err) => {
    console.warn(`[persistentStore] Mongo live writer sync skipped: ${err.message}`);
  });
}

function getLedgerPath() {
  return ledgerPath;
}

function getStorageInfo() {
  return {
    backend: process.env.AISFOR_CHAIN_LEDGER_BACKEND || 'json-file',
    dataDir,
    ledgerPath,
    writable: true,
    dualWriteRequested: process.env.AISFOR_CHAIN_LEDGER_DUAL_WRITE === '1',
    dbWriteEnabled: process.env.AISFOR_CHAIN_LEDGER_DB_WRITE === '1',
    dbAdapter: dbLedgerAdapter.getStatus(),
    mongoObservation: mongoLedgerObservationAdapter.getStatus(),
    mongoReadBackend: mongoLedgerReadAdapter.getStatus(),
    mongoReadSnapshot: mongoReadSnapshotService.getStatus(),
    mongoLiveWriter: mongoLedgerLiveWriterAdapter.getStatus()
  };
}

module.exports = {
  readState,
  writeState,
  getLedgerPath,
  getStorageInfo
};






