import { describe, it, expect } from 'vitest';
import { detectCitations } from './citations';
import type { Segment } from '../types';

const seg = (start: number, text: string, id?: string): Segment => ({
  id,
  start,
  end: start + 1,
  text,
});

describe('detectCitations', () => {
  it('returns [] for empty input', () => {
    expect(detectCitations([])).toEqual([]);
  });

  it('extracts a bare DOI', () => {
    const out = detectCitations([seg(0, 'See 10.1038/nphys1170 for details.')]);
    const doi = out.find((c) => c.kind === 'doi');
    expect(doi?.value).toBe('10.1038/nphys1170');
  });

  it('extracts a DOI from a doi.org URL and a doi: prefix', () => {
    const a = detectCitations([seg(0, 'https://doi.org/10.1145/3292500.3330701')]);
    expect(a[0]!.value).toBe('10.1145/3292500.3330701');
    const b = detectCitations([seg(0, 'doi: 10.1000/xyz123')]);
    expect(b[0]!.value).toBe('10.1000/xyz123');
  });

  it('trims trailing punctuation from a DOI', () => {
    const out = detectCitations([seg(0, '(see 10.1038/nphys1170).')]);
    expect(out[0]!.value).toBe('10.1038/nphys1170');
  });

  it('extracts an explicit arXiv id', () => {
    const out = detectCitations([seg(0, 'Read arXiv:2103.00020 today.')]);
    const ax = out.find((c) => c.kind === 'arxiv');
    expect(ax?.value).toBe('2103.00020');
  });

  it('extracts a bare arXiv id', () => {
    const out = detectCitations([seg(0, 'the paper 1706.03762 introduced it')]);
    const ax = out.find((c) => c.kind === 'arxiv');
    expect(ax?.value).toBe('1706.03762');
  });

  it('extracts ISBN-13 and ISBN-10, normalized without hyphens', () => {
    const a = detectCitations([seg(0, 'ISBN 978-0-13-468599-1')]);
    expect(a.find((c) => c.kind === 'isbn')?.value).toBe('9780134685991');
    const b = detectCitations([seg(0, 'ISBN-10: 0-262-03384-4')]);
    expect(b.find((c) => c.kind === 'isbn')?.value).toBe('0262033844');
  });

  it('extracts author-year (parenthesized)', () => {
    const out = detectCitations([seg(0, 'As Vaswani (2017) showed,')]);
    const ay = out.find((c) => c.kind === 'author-year');
    expect(ay?.value).toBe('Vaswani (2017)');
  });

  it('extracts "Author et al., Year"', () => {
    const out = detectCitations([seg(0, 'per Smith et al., 2021 this holds')]);
    const ay = out.find((c) => c.kind === 'author-year');
    expect(ay?.value).toBe('Smith et al. (2021)');
  });

  it('dedupes by value', () => {
    const out = detectCitations([
      seg(0, '10.1038/nphys1170'),
      seg(1, 'again 10.1038/nphys1170'),
    ]);
    expect(out.filter((c) => c.kind === 'doi')).toHaveLength(1);
  });

  it('tags sourceSegmentId and start', () => {
    const out = detectCitations([seg(9, 'arXiv:2103.00020', 'segA')]);
    expect(out[0]!.sourceSegmentId).toBe('segA');
    expect(out[0]!.start).toBe(9);
  });

  it('does not treat plain prose years as citations', () => {
    const out = detectCitations([seg(0, 'In 2017 the weather was nice.')]);
    expect(out.filter((c) => c.kind === 'author-year')).toHaveLength(0);
  });
});
