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

const COLLECTIONS = [
  { key: 'proofs', collection: 'chain_proofs' },
  { key: 'transactions', collection: 'chain_transactions' },
  { key: 'blocks', collection: 'chain_blocks' },
  { key: 'callbackEvents', collection: 'chain_callbacks' },
  { key: 'nodes', collection: 'node_participants' },
  { key: 'nodeEconomyEntries', collection: 'node_economy_ledger' },
  { key: 'pointEntries', collection: 'point_ledger' },
  { key: 'validatorVotes', collection: 'validator_votes' },
  { key: 'backupIndexes', collection: 'backup_indexes' },
  { key: 'distributedChunks', collection: 'distributed_chunks' },
  { key: 'wallets', collection: 'wallets' },
  { key: 'walletTransactions', collection: 'wallet_transactions' }
];

const shadowDir = path.join(__dirname, '..', 'data', 'db-shadow');
const statusPath = path.join(shadowDir, '_status.json');

function sha256(value) {
  return crypto.createHash('sha256').update(String(value)).digest('hex');
}

function stableStringify(value) {
  if (value === null || typeof value !== 'object') return JSON.stringify(value);
  if (Array.isArray(value)) return `[${value.map(stableStringify).join(',')}]`;
  return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${stableStringify(value[key])}`).join(',')}}`;
}

function isRequested() {
  return process.env.AISFOR_CHAIN_LEDGER_DUAL_WRITE === '1';
}

function isWriteEnabled() {
  return isRequested() && process.env.AISFOR_CHAIN_LEDGER_DB_WRITE === '1';
}

function ensureShadowDir() {
  fs.mkdirSync(shadowDir, { recursive: true });
}

function getCollectionPath(collection) {
  return path.join(shadowDir, `${collection}.json`);
}

function toDocument(item, row, index, syncedAt) {
  const sourceHash = sha256(stableStringify(row));
  return {
    _shadowId: sha256(`${item.key}:${index}:${sourceHash}`),
    _sourceKey: item.key,
    _sourceIndex: index,
    _sourceHash: sourceHash,
    syncedAt,
    payload: row
  };
}

function writeShadowCollections(state) {
  if (!isWriteEnabled()) return getStatus();

  ensureShadowDir();
  const syncedAt = new Date().toISOString();
  const collections = COLLECTIONS.map((item) => {
    const rows = Array.isArray(state[item.key]) ? state[item.key] : [];
    const docs = rows.map((row, index) => toDocument(item, row, index, syncedAt));
    const filePath = getCollectionPath(item.collection);
    fs.writeFileSync(filePath, `${JSON.stringify(docs, null, 2)}\n`);
    return {
      key: item.key,
      collection: item.collection,
      documents: docs.length,
      filePath,
      hash: sha256(stableStringify(docs))
    };
  });

  const status = {
    backend: 'json-shadow-db',
    active: true,
    syncedAt,
    shadowDir,
    collections,
    totalDocuments: collections.reduce((sum, row) => sum + row.documents, 0)
  };

  fs.writeFileSync(statusPath, `${JSON.stringify(status, null, 2)}\n`);
  return status;
}

function getStatus() {
  let latest = null;
  try {
    latest = JSON.parse(fs.readFileSync(statusPath, 'utf8'));
  } catch (err) {
    latest = null;
  }

  return {
    backend: 'json-shadow-db',
    requested: isRequested(),
    writeEnabled: isWriteEnabled(),
    active: Boolean(latest && latest.active),
    shadowDir,
    statusPath,
    latestSyncedAt: latest ? latest.syncedAt : null,
    totalDocuments: latest ? latest.totalDocuments : 0,
    collections: latest ? latest.collections : []
  };
}

module.exports = {
  writeShadowCollections,
  getStatus,
  isRequested,
  isWriteEnabled
};
