import { SECTION_KIND, resolveSectionKind } from "./sectionTypeHelpers.js";

/** Number of ACTION TO BE IMPLEMENTED / WHO / WHEN rows on the audit form. */
export const AUDIT_ACTION_ROW_COUNT = 3;

export const AUDIT_SECTION_DEFAULT_TITLE = "AUDIT (At least one per shift)";

function normalizeLabel(value) {
  return String(value || "")
    .trim()
    .toLowerCase()
    .replace(/\s+/g, " ")
    .replace(/:$/, "");
}

/** Normalize en/em dashes and trailing colons ("WHO :" -> "who"). */
function normalizeAuditLabel(value) {
  return normalizeLabel(value)
    .replace(/[\u2013\u2014]/g, "-")
    .replace(/\s*:\s*$/, "");
}

function isAuditFormTypeName(name) {
  const n = normalizeLabel(name);
  return n === "audit" || n.includes("audit");
}

/** True when the form's ptw_form_type is Audit. */
export function isAuditFormType(form, formTypes = []) {
  if (!form) return false;
  if (isAuditFormTypeName(form.form_type_name)) return true;
  const typeId = form.form_type_id;
  if (typeId == null || typeId === "") return false;
  const match = (formTypes || []).find(
    (row) => String(row.form_type_id) === String(typeId)
  );
  return isAuditFormTypeName(match?.form_type_name);
}

/** True when this section should render the audit table (not the checklist). */
export function shouldUseAuditSectionLayout(section, form, formTypes = []) {
  if (resolveSectionKind(section) === SECTION_KIND.AUDIT) return true;
  if (isAuditFormType(form, formTypes)) {
    const title = normalizeLabel(section?.title);
    return !title || title.includes("audit");
  }
  return false;
}

function findQuestionByLabel(questions, labels) {
  const wanted = new Set(labels.map(normalizeAuditLabel));
  return (questions || []).find((q) => wanted.has(normalizeAuditLabel(q?.question)));
}

function isActionRowQuestion(question) {
  const n = normalizeAuditLabel(question?.question);
  return /^action\s+\d+\s*-/.test(n);
}

function isWhoLabel(question) {
  const n = normalizeAuditLabel(question?.question);
  return n === "who" || n === "auditor" || n === "audit who";
}

function isWhenLabel(question) {
  return normalizeAuditLabel(question?.question) === "when";
}

function isDateLabel(question) {
  const n = normalizeAuditLabel(question?.question);
  return n === "date" || n === "audit date";
}

function isDescriptionLabel(question) {
  const n = normalizeAuditLabel(question?.question);
  if (n === "action to be implemented") return true;
  if (n.includes("implement")) return true;
  return /^action\s+\d+\s*-/.test(n) && n.includes("implement");
}

function classifyAuditQuestion(question) {
  const n = normalizeAuditLabel(question?.question);
  const actionMatch = n.match(/^action\s+(\d+)\s*-\s*(.+)$/);

  if (actionMatch) {
    const rowNum = Number(actionMatch[1]);
    const slotLabel = actionMatch[2];
    if (slotLabel.includes("implement")) {
      return { kind: "action", rowNum, slot: "description" };
    }
    if (slotLabel === "who") {
      return { kind: "action", rowNum, slot: "who" };
    }
    if (slotLabel === "when") {
      return { kind: "action", rowNum, slot: "when" };
    }
    return { kind: "action", rowNum, slot: "description" };
  }

  if (isWhoLabel(question)) return { kind: "metaWho" };
  if (isDateLabel(question)) return { kind: "metaDate" };
  if (isWhenLabel(question)) return { kind: "actionWhen" };
  if (isDescriptionLabel(question)) return { kind: "actionDescription" };

  return { kind: "unknown" };
}

function emptyActionRows() {
  return Array.from({ length: AUDIT_ACTION_ROW_COUNT }, () => ({
    description: null,
    who: null,
    when: null
  }));
}

function collectUsedQuestionIds(metaWho, metaDate, actionRows) {
  const ids = [metaWho?.question_id, metaDate?.question_id];
  for (const row of actionRows) {
    ids.push(row.description?.question_id, row.who?.question_id, row.when?.question_id);
  }
  return new Set(ids.filter(Boolean).map(String));
}

/**
 * Catalog layout used in production: 1 header WHO, optional DATE, then repeated
 * ACTION TO BE IMPLEMENTED / WHO / WHEN labels (same text, distinct question_id rows).
 */
function parseGroupedCatalogQuestions(questions) {
  const list = Array.isArray(questions) ? questions : [];
  const whoAll = list.filter(isWhoLabel).sort((a, b) => Number(a.question_id) - Number(b.question_id));
  const whenAll = list.filter(isWhenLabel).sort((a, b) => Number(a.question_id) - Number(b.question_id));
  const descAll = list.filter(isDescriptionLabel).sort((a, b) => Number(a.question_id) - Number(b.question_id));
  const dateAll = list.filter(isDateLabel).sort((a, b) => Number(a.question_id) - Number(b.question_id));

  if (whoAll.length < 1 || descAll.length < 1 || whenAll.length < 1) {
    return null;
  }

  const metaWho = whoAll[0];
  const metaDate = dateAll[0] || null;
  const actionWhoList = whoAll.slice(1);
  const actionRows = emptyActionRows();

  for (let i = 0; i < AUDIT_ACTION_ROW_COUNT; i += 1) {
    actionRows[i].description = descAll[i] || null;
    actionRows[i].who = actionWhoList[i] || null;
    actionRows[i].when = whenAll[i] || null;
  }

  return { metaWho, metaDate, actionRows };
}

/**
 * Map section questions to audit table slots.
 * Supports numbered Action N labels and repeated WHO/ACTION/WHEN catalog labels.
 */
export function parseAuditSectionQuestions(questions = []) {
  const grouped = parseGroupedCatalogQuestions(questions);
  if (grouped) {
    return grouped;
  }

  const list = Array.isArray(questions) ? questions : [];
  let metaWho = null;
  let metaDate = null;
  const actionRows = emptyActionRows();
  const descriptions = [];
  const actionWhoPool = [];
  const actionWhenPool = [];

  for (const question of list) {
    const classified = classifyAuditQuestion(question);

    if (classified.kind === "metaWho" && !metaWho) {
      metaWho = question;
      continue;
    }
    if (classified.kind === "metaDate" && !metaDate) {
      metaDate = question;
      continue;
    }
    if (classified.kind === "actionDescription") {
      descriptions.push(question);
      continue;
    }
    if (classified.kind === "actionWhen") {
      actionWhenPool.push(question);
      continue;
    }
    if (classified.kind === "metaWho" && metaWho) {
      actionWhoPool.push(question);
      continue;
    }
    if (classified.kind === "action") {
      const rowIndex = classified.rowNum - 1;
      if (rowIndex >= 0 && rowIndex < AUDIT_ACTION_ROW_COUNT && classified.slot) {
        if (!actionRows[rowIndex][classified.slot]) {
          actionRows[rowIndex][classified.slot] = question;
        }
      }
    }
  }

  if (descriptions.length || actionWhoPool.length || actionWhenPool.length) {
    for (let i = 0; i < AUDIT_ACTION_ROW_COUNT; i += 1) {
      if (!actionRows[i].description) actionRows[i].description = descriptions[i] || null;
      if (!actionRows[i].who) actionRows[i].who = actionWhoPool[i] || null;
      if (!actionRows[i].when) actionRows[i].when = actionWhenPool[i] || null;
    }
  }

  const nonActionQuestions = list.filter((q) => !isActionRowQuestion(q));

  if (!metaWho) {
    metaWho =
      findQuestionByLabel(nonActionQuestions, ["who", "auditor", "audit who"]) ||
      nonActionQuestions[0] ||
      null;
  }
  if (!metaDate) {
    metaDate = findQuestionByLabel(nonActionQuestions, ["date", "audit date"]) || null;
  }

  const usedIds = collectUsedQuestionIds(metaWho, metaDate, actionRows);
  const rest = list.filter((q) => !usedIds.has(String(q.question_id)));

  let restIndex = 0;
  for (let rowIndex = 0; rowIndex < AUDIT_ACTION_ROW_COUNT; rowIndex += 1) {
    for (const slot of ["description", "who", "when"]) {
      if (!actionRows[rowIndex][slot] && restIndex < rest.length) {
        actionRows[rowIndex][slot] = rest[restIndex];
        restIndex += 1;
      }
    }
  }

  return { metaWho, metaDate, actionRows };
}

/** Questions actually rendered in the audit table (excludes orphan duplicate rows in DB). */
export function collectAuditDisplayQuestions(questions = []) {
  const { metaWho, metaDate, actionRows } = parseAuditSectionQuestions(questions);
  const display = [];
  if (metaWho) display.push(metaWho);
  if (metaDate) display.push(metaDate);
  for (const row of actionRows) {
    if (row.description) display.push(row.description);
    if (row.who) display.push(row.who);
    if (row.when) display.push(row.when);
  }
  return display;
}

export function auditSectionDisplayTitle(section) {
  const raw = String(section?.title || "").trim();
  return raw || AUDIT_SECTION_DEFAULT_TITLE;
}
