import {
  createSqlClient,
  extractTemplateFields,
  getActiveTemplateVersions,
  getEffectiveMappedKeys,
  getMappingsForVersion,
  isDesignerLabelField,
  summarizeIssues,
  writeAuditArtifact
} from './pdf-audit-utils.ts';

const TYPO_PATTERNS = [/lable/i, /affter/i, /__+/, /\s{2,}/];
const RESERVED_DYNAMIC_FIELD_NAMES = new Set(['topic', 'data_topic']);

function detectTypo(fieldName: string) {
  return TYPO_PATTERNS.some((pattern) => pattern.test(fieldName));
}

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

  try {
    const templates = await getActiveTemplateVersions(sql);
    const results = [];

    for (const template of templates) {
      const fields = extractTemplateFields(template.schemaJson);
      const { mappings } = await getMappingsForVersion(sql, template.versionId);
      const fieldNames = new Set(fields.map((field) => field.name).filter(Boolean));
      const mappedKeys = getEffectiveMappedKeys(fields, mappings);
      const tokens = [...new Set(fields.flatMap((field) => field.tokens))].sort();
      const duplicateFieldNames = [...fieldNames].filter(
        (fieldName) => fields.filter((field) => field.name === fieldName).length > 1
      );
      const typoFields = fields
        .filter((field) => field.name && detectTypo(field.name) && !isDesignerLabelField(field))
        .map((field) => field.name);
      const unmappedPlaceholders = tokens.filter(
        (token) =>
          token !== 'item_topic' &&
          !token.startsWith('topic_') &&
          !token.startsWith('item_topic_') &&
          !mappedKeys.has(token)
      );
      const deadMappings = mappings
        .filter(
          (mapping) =>
            !fieldNames.has(mapping.placeholderKey) &&
            !tokens.includes(mapping.placeholderKey) &&
            mapping.placeholderKey !== 'items_table'
        )
        .map((mapping) => mapping.placeholderKey);
      const invalidReservedMappings = mappings
        .filter(
          (mapping) =>
            mapping.placeholderKey.startsWith('topic_') ||
            mapping.placeholderKey.startsWith('item_topic_')
        )
        .map((mapping) => mapping.placeholderKey);
      const missingReservedFields = [...RESERVED_DYNAMIC_FIELD_NAMES].filter(
        (name) => !fieldNames.has(name)
      );
      const status = summarizeIssues([
        duplicateFieldNames.length ? 'FAIL' : 'PASS',
        typoFields.length ? 'FAIL' : 'PASS',
        unmappedPlaceholders.length ? 'FAIL' : 'PASS',
        deadMappings.length ? 'FAIL' : 'PASS',
        invalidReservedMappings.length ? 'FAIL' : 'PASS',
        missingReservedFields.length ? 'FAIL' : 'PASS'
      ]);

      results.push({
        templateName: template.templateName,
        organizationId: template.organizationId,
        version: template.version,
        duplicateFieldNames,
        typoFields,
        unmappedPlaceholders,
        deadMappings,
        invalidReservedMappings,
        missingReservedFields,
        status
      });
    }

    const overallStatus = summarizeIssues(
      results.map((result) => result.status) as Array<'PASS' | 'WARNING' | 'FAIL'>
    );
    const report = {
      audit: 'placeholder-integrity',
      overallStatus,
      results
    };
    const artifactPath = await writeAuditArtifact('placeholder-integrity-report.json', report);

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

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