const SOURCE_SERVICES = Object.freeze([
  'AISFOR',
  'AISTALK',
  'AISGROUP',
  'AISMALL'
]);

const PROOF_TYPES = Object.freeze({
  SYNC_BACKUP: {
    description: 'AISFOR sync-client backup completed.',
    baseRewardPoints: 5,
    requiredFields: ['actorId', 'deviceId']
  },
  NODE_ONLINE: {
    description: 'AISFOR node participant is online.',
    baseRewardPoints: 1,
    requiredFields: ['actorId', 'nodeId']
  },
  CHUNK_STORED: {
    description: 'Encrypted chunk was stored by a node.',
    baseRewardPoints: 2,
    requiredFields: ['actorId', 'nodeId', 'chunkHash']
  },
  CHUNK_VERIFIED: {
    description: 'Chunk SHA256 verification succeeded.',
    baseRewardPoints: 3,
    requiredFields: ['actorId', 'chunkHash']
  },
  CHUNK_REPAIRED: {
    description: 'Missing or damaged chunk was repaired.',
    baseRewardPoints: 4,
    requiredFields: ['actorId', 'chunkHash']
  },
  APP_ACTIVITY: {
    description: 'General activity from an AISFOR network service.',
    baseRewardPoints: 1,
    requiredFields: ['actorId']
  },
  MESSAGE_CREATED: {
    description: 'AISTALK message activity proof.',
    baseRewardPoints: 1,
    requiredFields: ['actorId']
  },
  GROUP_ACTIVITY: {
    description: 'AISGROUP collaboration activity proof.',
    baseRewardPoints: 1,
    requiredFields: ['actorId']
  },
  MALL_ACTIVITY: {
    description: 'AISMALL commerce activity proof.',
    baseRewardPoints: 1,
    requiredFields: ['actorId']
  },
  POINT_REWARD: {
    description: 'AISFOR Point simulation reward proof.',
    baseRewardPoints: 0,
    requiredFields: ['actorId']
  },
  STORAGE_PROOF_LOG: {
    description: 'AISFOR storage proof ledger row reference.',
    baseRewardPoints: 0,
    requiredFields: ['externalProofId', 'proofHash']
  },
  POINT_LEDGER_EVENT: {
    description: 'AISFOR point ledger row reference.',
    baseRewardPoints: 0,
    requiredFields: ['actorId', 'externalProofId', 'proofHash']
  },
  BLOCKCHAIN_PROOF_BUNDLE: {
    description: 'AISFOR bundled storage and point proof root anchor.',
    baseRewardPoints: 0,
    requiredFields: ['externalProofId', 'bundleHash', 'contentHash']
  }
});

function createValidationError(message, details = []) {
  const error = new Error(message);
  error.status = 400;
  error.code = 'INVALID_PROOF_PAYLOAD';
  error.details = details;
  return error;
}

function normalizeProofPayload(payload = {}) {
  const proofType = String(payload.proofType || '').trim().toUpperCase();
  const sourceService = String(payload.sourceService || '').trim().toUpperCase();

  return {
    sourceService,
    proofType,
    actorId: normalizeOptionalString(payload.actorId),
    targetId: normalizeOptionalString(payload.targetId),
    deviceId: normalizeOptionalString(payload.deviceId),
    nodeId: normalizeOptionalString(payload.nodeId),
    externalProofId: normalizeOptionalString(payload.externalProofId),
    idempotencyKey: normalizeOptionalString(payload.idempotencyKey),
    userIdHash: normalizeOptionalString(payload.userIdHash),
    contentHash: normalizeOptionalString(payload.contentHash),
    chunkHash: normalizeOptionalString(payload.chunkHash),
    payloadHash: normalizeOptionalString(payload.payloadHash),
    proofHash: normalizeOptionalString(payload.proofHash),
    bundleHash: normalizeOptionalString(payload.bundleHash),
    merkleRoot: normalizeOptionalString(payload.merkleRoot),
    metadata: payload.metadata && typeof payload.metadata === 'object' ? payload.metadata : {}
  };
}

function validateProofPayload(payload = {}) {
  const normalized = normalizeProofPayload(payload);
  const errors = [];

  if (!SOURCE_SERVICES.includes(normalized.sourceService)) {
    errors.push({
      field: 'sourceService',
      message: `sourceService must be one of: ${SOURCE_SERVICES.join(', ')}`
    });
  }

  if (!PROOF_TYPES[normalized.proofType]) {
    errors.push({
      field: 'proofType',
      message: `proofType must be one of: ${Object.keys(PROOF_TYPES).join(', ')}`
    });
  }

  if (normalized.proofType && PROOF_TYPES[normalized.proofType]) {
    for (const field of PROOF_TYPES[normalized.proofType].requiredFields) {
      if (!normalized[field]) {
        errors.push({
          field,
          message: `${field} is required for ${normalized.proofType}`
        });
      }
    }
  }

  if (errors.length > 0) {
    throw createValidationError('Invalid proof payload', errors);
  }

  return normalized;
}

function getProofRewardPoints(proofType) {
  return PROOF_TYPES[proofType]?.baseRewardPoints || 0;
}

function normalizeOptionalString(value) {
  if (value === undefined || value === null) {
    return null;
  }

  const normalized = String(value).trim();
  return normalized.length > 0 ? normalized : null;
}

module.exports = {
  SOURCE_SERVICES,
  PROOF_TYPES,
  validateProofPayload,
  getProofRewardPoints
};
