import type { PaperExtractionMatrix } from './types';

export type PaperResearchIntent =
  | { kind: 'ask' }
  | { kind: 'snapshot' }
  | { kind: 'compare' }
  | { kind: 'extract'; fields: string[] }
  | { kind: 'contradictions' }
  | { kind: 'evidence-balance' }
  | { kind: 'verify' }
  | { kind: 'deep-research' }
  | { kind: 'insights' }
  | { kind: 'notes-synthesis' };

const CLEAN_FIELD = /[^\p{L}\p{N}\s%+/_-]+/gu;

function compactField(value: string): string {
  return value.replace(CLEAN_FIELD, ' ').replace(/\s+/gu, ' ').trim().slice(0, 80);
}

export function requestedExtractionFields(question: string): string[] {
  const normalized = question.replace(/\s+/gu, ' ').trim();
  const match = normalized.match(/\bextract\b\s+(?:the\s+)?(.+?)(?:\s+from\s+(?:these|the|my|selected|all)\s+papers?|[.?!]|$)/iu);
  if (!match?.[1]) return [];
  const candidate = match[1]
    .replace(/\b(?:please|for me|values?|fields?|details?)\b/giu, ' ')
    .replace(/\s+and\s+/giu, ',');
  const fields = candidate.split(/[,;]+/u).map(compactField).filter(Boolean);
  return [...new Set(fields)].slice(0, 12);
}

export function detectPaperResearchIntent(question: string): PaperResearchIntent {
  const value = question.replace(/\s+/gu, ' ').trim();
  if (!value) return { kind: 'ask' };
  if (/\b(?:draft|write|synthesi[sz]e|summari[sz]e).{0,40}\b(?:my\s+)?(?:research\s+)?notes?\b/iu.test(value)) {
    return { kind: 'notes-synthesis' };
  }
  if (/\b(?:deep\s+research|research\s+whether|research\s+if|investigate\s+whether)\b/iu.test(value)) {
    return { kind: 'deep-research' };
  }
  if (/\b(?:chain\s+of\s+verification|independent(?:ly)?\s+verify|verify\s+(?:this|the)\s+(?:claim|conclusion|finding)|fact[- ]?check)\b/iu.test(value)) {
    return { kind: 'verify' };
  }
  if (/\b(?:research\s+insights?|potential\s+gaps?|novelty\s+signals?|hypotheses?|current\s+approaches)\b/iu.test(value)) {
    return { kind: 'insights' };
  }
  if (/\b(?:study\s+snapshot|snapshot\s+(?:of|for)|summari[sz]e\s+(?:the\s+)?study\s+(?:design|details))\b/iu.test(value)) {
    return { kind: 'snapshot' };
  }
  if (/\b(?:which\s+papers?\s+(?:disagree|conflict)|papers?\s+(?:disagree|conflict)|contradict(?:ion|ory|ing)?\s+(?:evidence|papers?)|find\s+disagreements?)\b/iu.test(value)) {
    return { kind: 'contradictions' };
  }
  if (/\b(?:evidence\s+balance|how\s+many\s+(?:papers?|studies)\s+(?:support|oppose)|balance\s+of\s+evidence)\b/iu.test(value)) {
    return { kind: 'evidence-balance' };
  }
  if (/\b(?:compare|comparison|contrast)\b/iu.test(value) && /\b(?:papers?|studies|methods?|results?|approaches?)\b/iu.test(value)) {
    return { kind: 'compare' };
  }
  if (/\bextract\b/iu.test(value)) {
    const fields = requestedExtractionFields(value);
    if (fields.length) return { kind: 'extract', fields };
  }
  return { kind: 'ask' };
}

function quoteCsv(value: string): string {
  return `"${value.replace(/"/gu, '""')}"`;
}

export function extractionMatrixToCsv(matrix: PaperExtractionMatrix): string {
  const header = ['Study', ...matrix.fields].map(quoteCsv).join(',');
  const rows = matrix.rows.map((row) => [row.paperTitle, ...matrix.fields.map((field) => row.cells[field]?.value ?? '')].map(quoteCsv).join(','));
  return [header, ...rows].join('\n');
}

function escapeLatexCell(value: string): string {
  return value
    .replace(/\\/gu, '\\textbackslash{}')
    .replace(/([&%$#_{}])/gu, '\\$1')
    .replace(/~/gu, '\\textasciitilde{}')
    .replace(/\^/gu, '\\textasciicircum{}');
}

export function extractionMatrixToLatex(matrix: PaperExtractionMatrix): string {
  const columns = `l${'l'.repeat(matrix.fields.length)}`;
  const header = ['Study', ...matrix.fields].map(escapeLatexCell).join(' & ');
  const rows = matrix.rows.map((row) => [row.paperTitle, ...matrix.fields.map((field) => row.cells[field]?.value ?? '')].map(escapeLatexCell).join(' & '));
  return [`\\begin{tabular}{${columns}}`, '\\hline', `${header} \\\\`, '\\hline', ...rows.map((row) => `${row} \\\\`), '\\hline', '\\end{tabular}'].join('\n');
}
