'use strict';

const { getDialect } = require('../dialect');
const { getReservedKeywords, isSupportedDialect } = require('./reserved-keywords');

/** @typedef {import('./validator-types').Issue} Issue */

/**
 * Naming convention validator. Emits warnings for table / field names that
 * collide with reserved keywords or exceed the identifier length limit
 * supported by the chosen dialect.
 *
 * Identifier length limits are read from the existing dialect modules
 * (lib/dbschema-kit/dialect/*) so the warning fires at the exact limit
 * the DDL emitter would otherwise truncate or reject at.
 *
 * No-op when `dialect` is null / undefined / unsupported — naming
 * conventions are dialect-specific and the user must opt in via
 * `--dialect` to surface them.
 *
 * @param {Map<string, object>} models
 * @param {string | null | undefined} dialect
 * @returns {Issue[]}
 */
function validateNamingConventions(models, dialect) {
  if (!dialect || !isSupportedDialect(dialect)) return [];

  const reserved = getReservedKeywords(dialect);
  const limit = getIdentifierLimit(dialect);
  const issues = [];

  for (const [, ir] of models) {
    checkIdentifier(issues, ir, ir.tableName, reserved, limit, dialect, 'table');

    for (const fieldName of Object.keys(ir.fields)) {
      checkIdentifier(issues, ir, fieldName, reserved, limit, dialect, 'field');
    }
  }

  return issues;
}

function getIdentifierLimit(dialect) {
  try {
    const def = getDialect(dialect);
    return typeof def.maxIdentifierLength === 'number' ? def.maxIdentifierLength : null;
  } catch (_) {
    return null;
  }
}

function checkIdentifier(issues, ir, name, reserved, limit, dialect, kind) {
  if (reserved.has(name.toLowerCase())) {
    issues.push(decorate({
      severity: 'warning',
      code: kind === 'table' ? 'reserved-keyword-table' : 'reserved-keyword-field',
      message: `${kind === 'table' ? 'Table' : `Field '${name}' in table '${qualified(ir)}': field`} name '${name}' is a reserved keyword in ${dialect}`
    }, ir, kind === 'field' ? name : null));
  }

  if (limit !== null && name.length > limit) {
    issues.push(decorate({
      severity: 'warning',
      code: 'identifier-too-long',
      message: `${kind === 'table' ? 'Table' : `Field '${name}' in table '${qualified(ir)}': field`} name '${name}' has length ${name.length}, exceeds ${dialect} limit ${limit}`
    }, ir, kind === 'field' ? name : null));
  }
}

function qualified(ir) {
  return ir.qualifiedName || ir.tableName;
}

function decorate(issue, ir, fieldName) {
  const decorated = {
    severity: issue.severity,
    code: issue.code,
    message: issue.message
  };
  if (ir._filePath) decorated.file = ir._filePath;
  if (ir.qualifiedName) decorated.table = ir.qualifiedName;
  if (fieldName) decorated.field = fieldName;
  return decorated;
}

module.exports = { validateNamingConventions };
