/**
 * Tests for github/issue module
 *
 * Tests parsing and formatting functions.
 * checkGhCli/fetchIssue/resolveIssueTask are integration functions
 * that call `gh` CLI, so they are not unit-tested here.
 */

import { describe, it, expect } from 'vitest';
import {
  parseIssueNumbers,
  isIssueReference,
  formatIssueAsTask,
  type GitHubIssue,
} from '../infra/github/issue.js';

describe('parseIssueNumbers', () => {
  it('should parse single issue reference', () => {
    expect(parseIssueNumbers(['#6'])).toEqual([6]);
  });

  it('should parse multiple issue references', () => {
    expect(parseIssueNumbers(['#6', '#7'])).toEqual([6, 7]);
  });

  it('should parse large issue numbers', () => {
    expect(parseIssueNumbers(['#123'])).toEqual([123]);
  });

  it('should return empty for non-issue args', () => {
    expect(parseIssueNumbers(['Fix bug'])).toEqual([]);
  });

  it('should return empty when mixed issue and non-issue args', () => {
    expect(parseIssueNumbers(['#6', 'and', '#7'])).toEqual([]);
  });

  it('should return empty for empty args', () => {
    expect(parseIssueNumbers([])).toEqual([]);
  });

  it('should not match partial issue patterns', () => {
    expect(parseIssueNumbers(['#abc'])).toEqual([]);
    expect(parseIssueNumbers(['#'])).toEqual([]);
    expect(parseIssueNumbers(['##6'])).toEqual([]);
    expect(parseIssueNumbers(['6'])).toEqual([]);
    expect(parseIssueNumbers(['issue#6'])).toEqual([]);
  });

  it('should handle #0', () => {
    expect(parseIssueNumbers(['#0'])).toEqual([0]);
  });
});

describe('isIssueReference', () => {
  it('should return true for #N patterns', () => {
    expect(isIssueReference('#6')).toBe(true);
    expect(isIssueReference('#123')).toBe(true);
  });

  it('should return true with whitespace trim', () => {
    expect(isIssueReference(' #6 ')).toBe(true);
  });

  it('should return false for non-issue text', () => {
    expect(isIssueReference('Fix bug')).toBe(false);
    expect(isIssueReference('#abc')).toBe(false);
    expect(isIssueReference('')).toBe(false);
    expect(isIssueReference('#')).toBe(false);
    expect(isIssueReference('6')).toBe(false);
  });

  it('should return false for issue number followed by text (issue #32)', () => {
    expect(isIssueReference('#32あああ')).toBe(false);
    expect(isIssueReference('#10abc')).toBe(false);
    expect(isIssueReference('#123text')).toBe(false);
  });

  it('should return false for multiple issues (single string)', () => {
    expect(isIssueReference('#6 #7')).toBe(false);
  });
});

describe('formatIssueAsTask', () => {
  it('should format issue with all fields', () => {
    const issue: GitHubIssue = {
      number: 6,
      title: 'Fix authentication bug',
      body: 'The login flow is broken.',
      labels: ['bug', 'priority:high'],
      comments: [
        { author: 'user1', body: 'I can reproduce this.' },
        { author: 'user2', body: 'Fixed in PR #7.' },
      ],
    };

    const result = formatIssueAsTask(issue);

    expect(result).toContain('## GitHub Issue #6: Fix authentication bug');
    expect(result).toContain('The login flow is broken.');
    expect(result).toContain('### Labels');
    expect(result).toContain('bug, priority:high');
    expect(result).toContain('### Comments');
    expect(result).toContain('**user1**: I can reproduce this.');
    expect(result).toContain('**user2**: Fixed in PR #7.');
  });

  it('should format issue with no body', () => {
    const issue: GitHubIssue = {
      number: 10,
      title: 'Empty issue',
      body: '',
      labels: [],
      comments: [],
    };

    const result = formatIssueAsTask(issue);

    expect(result).toBe('## GitHub Issue #10: Empty issue');
    expect(result).not.toContain('### Labels');
    expect(result).not.toContain('### Comments');
  });

  it('should format issue with labels but no comments', () => {
    const issue: GitHubIssue = {
      number: 5,
      title: 'Feature request',
      body: 'Add dark mode.',
      labels: ['enhancement'],
      comments: [],
    };

    const result = formatIssueAsTask(issue);

    expect(result).toContain('### Labels');
    expect(result).toContain('enhancement');
    expect(result).not.toContain('### Comments');
  });

  it('should format issue with comments but no labels', () => {
    const issue: GitHubIssue = {
      number: 3,
      title: 'Discussion',
      body: 'Thoughts?',
      labels: [],
      comments: [
        { author: 'dev', body: 'LGTM' },
      ],
    };

    const result = formatIssueAsTask(issue);

    expect(result).not.toContain('### Labels');
    expect(result).toContain('### Comments');
    expect(result).toContain('**dev**: LGTM');
  });

  it('should handle multiline body', () => {
    const issue: GitHubIssue = {
      number: 1,
      title: 'Multi-line',
      body: 'Line 1\nLine 2\n\nLine 4',
      labels: [],
      comments: [],
    };

    const result = formatIssueAsTask(issue);

    expect(result).toContain('Line 1\nLine 2\n\nLine 4');
  });
});
