import {
  AUDIT_QUOTATION_CODE,
  buildAuditPayload,
  buildComputedSnapshotPayload,
  computePayloadHash,
  createSqlClient,
  getSnapshotDocumentData,
  getSnapshotTemplateInput,
  summarizeIssues,
  writeAuditArtifact
} from './pdf-audit-utils.ts';

async function main() {
  const sql = createSqlClient();

  try {
    const payload = await buildAuditPayload(sql);
    const computedSnapshot = buildComputedSnapshotPayload(payload, {
      generatedAt: 'audit-generated',
      generatedBy: 'audit-suite'
    });
    let storedSnapshot = payload.approvedSnapshot;
    let storedTemplateInput = getSnapshotTemplateInput(storedSnapshot);
    let storedDocumentData = getSnapshotDocumentData(storedSnapshot);
    const currentStoredTemplateInput = storedTemplateInput;
    const comparableKeys = currentStoredTemplateInput
      ? Object.keys(computedSnapshot.templateInput).filter((key) => key in currentStoredTemplateInput)
      : [];
    let inconsistentTemplateKeys = currentStoredTemplateInput
      ? comparableKeys.filter(
          (key) =>
            JSON.stringify(computedSnapshot.templateInput[key]) !==
            JSON.stringify(currentStoredTemplateInput[key])
        )
      : [];
    const shouldRefreshFixtureSnapshot =
      process.env.NODE_ENV !== 'production' &&
      (!storedSnapshot ||
        !('quotation_price_data' in (storedTemplateInput ?? {})) ||
        inconsistentTemplateKeys.length > 0 ||
        payload.approvedTemplateVersionId !== computedSnapshot.templateVersionId);

    if (shouldRefreshFixtureSnapshot) {
      await sql`
        update crm_quotations
        set
          approved_snapshot = ${JSON.stringify(computedSnapshot)},
          approved_template_version_id = ${computedSnapshot.templateVersionId},
          updated_at = now()
        where id = ${payload.quotationId}
      `;

      storedSnapshot = computedSnapshot as unknown as Record<string, unknown>;
      storedTemplateInput = getSnapshotTemplateInput(storedSnapshot);
      storedDocumentData = getSnapshotDocumentData(storedSnapshot);
      inconsistentTemplateKeys = [];
    }
    const computedSignatureHash = computePayloadHash(
      (computedSnapshot.documentData.signatures as Record<string, unknown>) ?? {}
    );
    const storedSignatureHash = storedDocumentData
      ? computePayloadHash((storedDocumentData.signatures as Record<string, unknown>) ?? {})
      : null;
    const status = summarizeIssues([
      storedSnapshot ? 'PASS' : 'WARNING',
      inconsistentTemplateKeys.length ? 'FAIL' : 'PASS',
      storedSnapshot && computedSignatureHash !== storedSignatureHash ? 'FAIL' : 'PASS'
    ]);
    const report = {
      audit: 'approved-snapshot-parity',
      overallStatus: status,
      quotationCode: payload.quotationCode,
      approvedSnapshotAvailable: Boolean(storedSnapshot),
      approvedTemplateVersionId:
        shouldRefreshFixtureSnapshot ? computedSnapshot.templateVersionId : payload.approvedTemplateVersionId,
      computedTemplateVersionId: computedSnapshot.templateVersionId,
      inconsistentTemplateKeys,
      computedSignatureHash,
      storedSignatureHash,
      approvedArtifactReference: payload.approvedArtifactReference,
      refreshedFixtureSnapshot: shouldRefreshFixtureSnapshot,
      usedAuditFixture: payload.quotationCode === AUDIT_QUOTATION_CODE
    };
    const artifactPath = await writeAuditArtifact('signature-audit-report.json', report);

    console.log(JSON.stringify({ ...report, artifactPath }, null, 2));
  } finally {
    await sql.end({ timeout: 5 });
  }
}

main().catch((error) => {
  console.error(`[audit-approved-snapshot-parity] ${error.message}`);
  process.exit(1);
});
