'use strict';

const { generateConstraintName, deriveCompositeShortName } = require('../naming');

function collectIndexes(ir, maxLength) {
  const { tableName, fields, primaryKey, indexes, uniques } = ir;

  const implicitColumns = new Set();
  for (const [fieldName, field] of Object.entries(fields)) {
    if (field.unique === true) implicitColumns.add(fieldName);
    if (field.pk === true) implicitColumns.add(fieldName);
  }
  if (Array.isArray(primaryKey)) {
    for (const col of primaryKey) implicitColumns.add(col);
  }

  const implicitComposites = uniques.map((u) => u.columns.slice());

  const candidates = [];

  for (const [fieldName, field] of Object.entries(fields)) {
    if (field.index === true) {
      candidates.push({ columns: [fieldName], composite: false });
    }
  }

  for (const idx of indexes) {
    candidates.push({ columns: idx.columns.slice(), composite: !!idx.composite });
  }

  const seenKeys = new Set();
  const deduped = [];
  for (const c of candidates) {
    const key = c.columns.join('|');
    if (seenKeys.has(key)) continue;
    seenKeys.add(key);
    deduped.push(c);
  }

  const result = [];
  for (const c of deduped) {
    if (c.composite) {
      const matchesUniqueComposite = implicitComposites.some((cs) => arraysEqual(cs, c.columns));
      if (matchesUniqueComposite) continue;
    } else if (implicitColumns.has(c.columns[0])) {
      continue;
    }

    const suffix = c.composite ? deriveCompositeShortName(c.columns, maxLength) : c.columns[0];
    const name = generateConstraintName('idx', tableName, suffix, maxLength);
    result.push({ name, columns: c.columns, composite: c.composite });
  }

  return result;
}

function emitCreateIndexes(ir, dialect) {
  const collected = collectIndexes(ir, dialect.maxIdentifierLength);
  const tableIdentifier = dialect.formatTableIdentifier(ir);
  return collected.map((entry) => {
    const cols = entry.columns.map((c) => dialect.quoteIdentifier(c)).join(', ');
    // Index name TIDAK di-qualified dengan schema: PG/MySQL letakkan index di schema
    // tabelnya secara otomatis. Hanya target `ON <schema>.<table>` yang qualified.
    return `CREATE INDEX ${dialect.quoteIdentifier(entry.name)} ON ${tableIdentifier} (${cols})`;
  });
}

function arraysEqual(a, b) {
  if (a.length !== b.length) return false;
  for (let i = 0; i < a.length; i++) {
    if (a[i] !== b[i]) return false;
  }
  return true;
}

module.exports = { collectIndexes, emitCreateIndexes };
