const tokenomicsService = require('./tokenomicsService');

const CATEGORY_POLICIES = [
  {
    key: 'service',
    label: 'Service Usage',
    description: 'AISFOR service usage, proof creation, and verified app activity.',
    sampleEvents: ['APP_ACTIVITY', 'PROOF_ACCEPTED', 'SERVICE_CONFIRMATION'],
    defaultScore: 10,
    abuseControls: ['daily user cap', 'duplicate proof guard', 'idempotency key check']
  },
  {
    key: 'content',
    label: 'Content Contribution',
    description: 'Content creation, meaningful usage, views, reactions, and AI-assisted output.',
    sampleEvents: ['CONTENT_CREATED', 'CONTENT_USED', 'AI_OUTPUT_ACCEPTED'],
    defaultScore: 8,
    abuseControls: ['spam detection', 'quality review', 'same-content duplicate check']
  },
  {
    key: 'storage',
    label: 'Storage Capacity',
    description: 'User or node opens storage capacity for AISFOR distributed storage.',
    sampleEvents: ['STORAGE_CAPACITY_OPENED', 'DATA_STORED'],
    defaultScore: 12,
    abuseControls: ['capacity verification', 'minimum retention window', 'storage proof challenge']
  },
  {
    key: 'uptime',
    label: 'Node Uptime',
    description: 'Node remains online and available for service or storage responsibilities.',
    sampleEvents: ['NODE_HEARTBEAT', 'UPTIME_WINDOW_OK'],
    defaultScore: 6,
    abuseControls: ['heartbeat interval check', 'uptime window cap', 'node identity check']
  },
  {
    key: 'verification',
    label: 'File Custody Verification',
    description: 'Stored file custody challenge is answered correctly.',
    sampleEvents: ['FILE_CHALLENGE_OK', 'CUSTODY_VERIFIED'],
    defaultScore: 15,
    abuseControls: ['random challenge', 'proof hash match', 'failed challenge penalty']
  },
  {
    key: 'commerce',
    label: 'Commerce',
    description: 'Shopping purchase and sale activity in AISFOR ecosystem commerce.',
    sampleEvents: ['SHOP_PURCHASE', 'SHOP_SALE_SETTLED'],
    defaultScore: 7,
    abuseControls: ['refund exclusion', 'self-trading review', 'repeated counterparty cap']
  },
  {
    key: 'emoticon',
    label: 'AISTALK Emoticon',
    description: 'Emoticon pack creation, registration, sale, and buyer satisfaction.',
    sampleEvents: ['EMOTICON_PACK_CREATED', 'EMOTICON_PACK_SOLD'],
    defaultScore: 9,
    abuseControls: ['fake sale detection', 'quality/report review', 'refund exclusion']
  },
  {
    key: 'ecosystem',
    label: 'Ecosystem Participation',
    description: 'General community, promotion, governance, or partner activity.',
    sampleEvents: ['ECOSYSTEM_PARTICIPATION', 'PARTNER_CONTRIBUTION'],
    defaultScore: 5,
    abuseControls: ['manual review', 'daily cap', 'campaign rule check']
  }
];

const SOURCE_INTEGRATION_POLICIES = [
  {
    serviceName: 'AISFOR',
    status: 'connected',
    categories: ['service', 'activity', 'storage', 'uptime', 'verification', 'ecosystem'],
    eventTypes: [
      'ACTIVITY_MEMO_REWARD',
      'ACTIVITY_RECORDING_REWARD',
      'ACTIVITY_CLOUD_REWARD',
      'ACTIVITY_PET_REWARD',
      'NODE_ONLINE_REWARD',
      'CHUNK_STORED_REWARD',
      'CHUNK_VERIFIED_REWARD',
      'STORAGE_CAPACITY_REWARD',
      'PENALTY_OFFLINE'
    ],
    endpoint: '/api/reward',
    idempotency: 'AISFOR:POINT:{eventKey}',
    note: 'AISFOR PointLedger events are mirrored into Reward Ledger.'
  },
  {
    serviceName: 'AISTALK',
    status: 'connected',
    categories: ['content', 'emoticon', 'ecosystem'],
    eventTypes: ['CHAT_ACTIVITY_REWARD', 'EMOTICON_PACK_CREATED', 'EMOTICON_PACK_SOLD'],
    endpoint: '/api/reward',
    idempotency: 'AISTALK:{eventType}:{eventId}',
    note: 'AISTALK submits chat activity, emoticon pack listing, and emoticon sale reward events through the reward client.'
  },
  {
    serviceName: 'AISMALL',
    status: 'connected',
    categories: ['commerce', 'ecosystem'],
    eventTypes: ['SHOP_PURCHASE', 'SHOP_SALE_SETTLED', 'REFUND_EXCLUDED'],
    endpoint: '/api/reward',
    idempotency: 'AISMALL:{eventType}:{orderId}',
    note: 'AISMALL submits order purchase and seller payment-confirmation reward events; refunds and self-trading remain guarded.'
  },
  {
    serviceName: 'AISGROUP',
    status: 'connected',
    categories: ['content', 'ecosystem'],
    eventTypes: ['GROUP_POST_CREATED', 'GROUP_EVENT_PARTICIPATION', 'GROUP_ADMIN_CONTRIBUTION'],
    endpoint: '/api/reward',
    idempotency: 'AISGROUP:{eventType}:{eventId}',
    note: 'AISGROUP submits event-record and comment participation reward events through the reward client.'
  },
  {
    serviceName: 'AISFOR_CHAIN',
    status: 'internal',
    categories: ['verification', 'ecosystem'],
    eventTypes: ['PROOF_ACCEPTED', 'SERVICE_CONFIRMATION', 'POLICY_SIMULATION'],
    endpoint: '/api/reward',
    idempotency: 'AISFOR_CHAIN:{eventType}:{refId}',
    note: 'Internal chain events and admin simulations stay in simulation mode.'
  }
];

function getPolicy() {
  const tokenomics = tokenomicsService.getStatus();
  return {
    tokenomics,
    rewardFormula: [
      'serviceScore',
      'contentScore',
      'storageScore',
      'uptimeScore',
      'verificationScore',
      'commerceScore',
      'emoticonScore',
      'ecosystemScore'
    ],
    sources: SOURCE_INTEGRATION_POLICIES,
    categories: CATEGORY_POLICIES,
    settlement: {
      currentMode: tokenomics.config.rewardMode,
      simulationOnly: tokenomics.guardrails.simulationOnly,
      delayedSettlement: true,
      publicIssuanceDisabled: tokenomics.guardrails.publicIssuanceDisabled,
      note: 'Rewards are simulated until testnet token policy is explicitly approved.'
    }
  };
}

function getCategoryPolicy(category) {
  const key = String(category || '').trim();
  return CATEGORY_POLICIES.find((row) => row.key === key) || CATEGORY_POLICIES.find((row) => row.key === 'ecosystem');
}

function getSourcePolicy(sourceService) {
  const serviceName = String(sourceService || '').trim().toUpperCase();
  return SOURCE_INTEGRATION_POLICIES.find((row) => row.serviceName === serviceName) || null;
}

function validateRewardSubmission(payload = {}) {
  const sourceService = String(payload.sourceService || '').trim().toUpperCase();
  const category = String(payload.category || payload.pointCategory || '').trim();
  const actionType = String(payload.actionType || payload.eventType || '').trim();
  const idempotencyKey = String(payload.idempotencyKey || '').trim();
  const policy = getSourcePolicy(sourceService);
  const flags = [];
  const warnings = [];

  if (!policy) {
    flags.push('UNKNOWN_REWARD_SOURCE');
  } else {
    if (category && !policy.categories.includes(category)) {
      flags.push('SOURCE_CATEGORY_NOT_ALLOWED');
    }

    if (actionType && !policy.eventTypes.includes(actionType)) {
      warnings.push('SOURCE_EVENT_NOT_LISTED');
    }

    if (policy.status !== 'connected' && policy.status !== 'internal') {
      warnings.push('SOURCE_READY_NOT_CONNECTED');
    }
  }

  if (!idempotencyKey) {
    flags.push('IDEMPOTENCY_KEY_MISSING');
  } else if (policy && !idempotencyKey.startsWith(`${policy.serviceName}:`)) {
    flags.push('IDEMPOTENCY_SOURCE_PREFIX_MISMATCH');
  }

  return {
    ok: flags.length === 0,
    sourceService,
    category,
    actionType,
    sourcePolicy: policy,
    flags,
    warnings
  };
}

function buildSimulationPayload({ actorId, sourceService, category, actionType, baseScore, note, flags = {} } = {}) {
  const policy = getCategoryPolicy(category);
  const score = Number.isFinite(Number(baseScore)) ? Number(baseScore) : policy.defaultScore;
  const payload = {
    actorId: actorId || 'policy-simulated-user',
    sourceService: sourceService || 'AISFOR_CHAIN',
    category: policy.key,
    actionType: actionType || policy.sampleEvents[0] || 'POLICY_SIMULATION',
    note: note || `${policy.label} policy simulation`,
    refund: Boolean(flags.refund),
    cancelled: Boolean(flags.cancelled),
    selfTrade: Boolean(flags.selfTrade)
  };
  payload[`${policy.key}Score`] = score;
  return payload;
}

function buildSamplePayload(source, category, eventType) {
  const categoryPolicy = getCategoryPolicy(category);
  const eventKey = `${String(eventType || categoryPolicy.sampleEvents[0] || 'EVENT').toLowerCase()}-example-001`;
  const payload = {
    sourceService: source.serviceName,
    actorId: `${source.serviceName.toLowerCase()}-user-001`,
    category: categoryPolicy.key,
    actionType: eventType || source.eventTypes[0],
    idempotencyKey: source.idempotency
      .replace('{eventType}', eventType || source.eventTypes[0])
      .replace('{eventId}', eventKey)
      .replace('{orderId}', eventKey)
      .replace('{eventKey}', eventKey)
      .replace('{refId}', eventKey),
    eventKey,
    refType: `${source.serviceName}_REWARD_EVENT`,
    refId: eventKey,
    externalProofHash: `${source.serviceName.toLowerCase()}-${eventKey}-proof`,
    pointAmount: categoryPolicy.defaultScore,
    note: `${source.serviceName} ${categoryPolicy.label} reward event`,
    sourceCreatedAt: 'ISO-8601 timestamp'
  };
  payload[`${categoryPolicy.key}Score`] = categoryPolicy.defaultScore;
  return payload;
}

function getIntegrationManifest() {
  const policy = getPolicy();
  return {
    version: 'reward-integration-v1',
    endpoint: '/api/reward',
    dryRunEndpoint: '/api/reward/dry-run',
    method: 'POST',
    auth: {
      required: true,
      mode: 'hmac-signature-v2',
      note: 'Use registered service authentication headers configured for AISFOR-CHAIN.',
      headers: [
        'X-AISFOR-SERVICE',
        'X-AISFOR-TIMESTAMP',
        'X-AISFOR-NONCE',
        'X-AISFOR-SIGNATURE'
      ],
      helper: 'lib/rewardIntegrationClient.js'
    },
    settlement: policy.settlement,
    requiredFields: [
      'sourceService',
      'actorId',
      'category',
      'actionType',
      'idempotencyKey'
    ],
    recommendedFields: [
      'eventKey',
      'refType',
      'refId',
      'externalProofHash',
      'pointAmount',
      'sourceCreatedAt',
      'note'
    ],
    scoreFields: policy.rewardFormula,
    guardrails: [
      'Use one stable idempotencyKey per source event.',
      'Exclude refunds and cancelled events.',
      'Mark self-trading or suspicious commerce for review.',
      'Do not submit public-coin settlement claims while rewardMode is simulation.'
    ],
    services: policy.sources.map((source) => ({
      serviceName: source.serviceName,
      status: source.status,
      endpoint: source.endpoint,
      idempotency: source.idempotency,
      categories: source.categories,
      eventTypes: source.eventTypes,
      note: source.note,
      samplePayloads: source.eventTypes.slice(0, 3).map((eventType, index) => buildSamplePayload(
        source,
        source.categories[index % source.categories.length],
        eventType
      ))
    })),
    categories: policy.categories,
    generatedAt: new Date().toISOString()
  };
}

function validateIntegrationManifestSamples() {
  const manifest = getIntegrationManifest();
  const rows = manifest.services.flatMap((source) => (
    (source.samplePayloads || []).map((payload) => {
      const validation = validateRewardSubmission(payload);
      return {
        serviceName: source.serviceName,
        category: payload.category,
        actionType: payload.actionType,
        idempotencyKey: payload.idempotencyKey,
        ok: validation.ok,
        flags: validation.flags,
        warnings: validation.warnings
      };
    })
  ));
  const failed = rows.filter((row) => !row.ok);
  const warnings = rows.filter((row) => (row.warnings || []).length > 0);

  return {
    ok: failed.length === 0,
    totalSamples: rows.length,
    passedSamples: rows.length - failed.length,
    failedSamples: failed.length,
    warningSamples: warnings.length,
    rows,
    failed,
    warnings,
    checkedAt: new Date().toISOString()
  };
}

module.exports = {
  CATEGORY_POLICIES,
  SOURCE_INTEGRATION_POLICIES,
  buildSimulationPayload,
  getIntegrationManifest,
  getCategoryPolicy,
  getPolicy,
  getSourcePolicy,
  validateIntegrationManifestSamples,
  validateRewardSubmission
};
