import { describe, expect, test } from 'bun:test'
import { parseConfigString } from '../gitConfigParser'

describe('parseConfigString', () => {
  test('parses simple remote url', () => {
    const config = '[remote "origin"]\n\turl = https://github.com/user/repo.git'
    expect(parseConfigString(config, 'remote', 'origin', 'url')).toBe(
      'https://github.com/user/repo.git',
    )
  })

  test('section matching is case-insensitive', () => {
    const config = '[REMOTE "origin"]\n\turl = https://example.com'
    expect(parseConfigString(config, 'remote', 'origin', 'url')).toBe(
      'https://example.com',
    )
  })

  test('subsection matching is case-sensitive', () => {
    const config = '[remote "Origin"]\n\turl = https://example.com'
    expect(parseConfigString(config, 'remote', 'origin', 'url')).toBeNull()
  })

  test('subsection matching is case-sensitive (positive)', () => {
    const config = '[remote "Origin"]\n\turl = https://example.com'
    expect(parseConfigString(config, 'remote', 'Origin', 'url')).toBe(
      'https://example.com',
    )
  })

  test('key matching is case-insensitive', () => {
    const config = '[remote "origin"]\n\tURL = https://example.com'
    expect(parseConfigString(config, 'remote', 'origin', 'url')).toBe(
      'https://example.com',
    )
  })

  test('parses quoted value with spaces', () => {
    const config = '[user]\n\tname = "John Doe"'
    expect(parseConfigString(config, 'user', null, 'name')).toBe('John Doe')
  })

  test('handles escape sequence \\n inside quotes', () => {
    const config = '[user]\n\tname = "line1\\nline2"'
    expect(parseConfigString(config, 'user', null, 'name')).toBe('line1\nline2')
  })

  test('handles escape sequence \\t inside quotes', () => {
    const config = '[user]\n\tname = "col1\\tcol2"'
    expect(parseConfigString(config, 'user', null, 'name')).toBe('col1\tcol2')
  })

  test('handles escape sequence \\\\ inside quotes', () => {
    const config = '[user]\n\tname = "back\\\\slash"'
    expect(parseConfigString(config, 'user', null, 'name')).toBe('back\\slash')
  })

  test('handles escape sequence \\" inside quotes', () => {
    const config = '[user]\n\tname = "say \\"hello\\""'
    expect(parseConfigString(config, 'user', null, 'name')).toBe('say "hello"')
  })

  test('strips inline comment with #', () => {
    const config = '[remote "origin"]\n\turl = https://example.com # comment'
    expect(parseConfigString(config, 'remote', 'origin', 'url')).toBe(
      'https://example.com',
    )
  })

  test('strips inline comment with ;', () => {
    const config = '[remote "origin"]\n\turl = https://example.com ; comment'
    expect(parseConfigString(config, 'remote', 'origin', 'url')).toBe(
      'https://example.com',
    )
  })

  test('finds value in correct section among multiple sections', () => {
    const config = [
      '[remote "origin"]',
      '\turl = https://origin.example.com',
      '[remote "upstream"]',
      '\turl = https://upstream.example.com',
    ].join('\n')
    expect(parseConfigString(config, 'remote', 'upstream', 'url')).toBe(
      'https://upstream.example.com',
    )
  })

  test('returns null for missing key', () => {
    const config = '[remote "origin"]\n\turl = https://example.com'
    expect(parseConfigString(config, 'remote', 'origin', 'pushurl')).toBeNull()
  })

  test('returns null for missing section', () => {
    const config = '[remote "origin"]\n\turl = https://example.com'
    expect(parseConfigString(config, 'branch', 'main', 'merge')).toBeNull()
  })

  test('returns null for boolean key (no = sign)', () => {
    const config = '[core]\n\tbare'
    expect(parseConfigString(config, 'core', null, 'bare')).toBeNull()
  })

  test('returns null for empty config string', () => {
    expect(parseConfigString('', 'remote', 'origin', 'url')).toBeNull()
  })

  test('handles section without subsection', () => {
    const config = '[core]\n\trepositoryformatversion = 0'
    expect(
      parseConfigString(config, 'core', null, 'repositoryformatversion'),
    ).toBe('0')
  })

  test('does not match section without subsection when subsection is requested', () => {
    const config = '[core]\n\tbare = false'
    // Looking for [core "something"] but config has [core]
    expect(parseConfigString(config, 'core', 'something', 'bare')).toBeNull()
  })

  test('skips comment-only lines', () => {
    const config = [
      '# This is a comment',
      '; This is also a comment',
      '[remote "origin"]',
      '\turl = https://example.com',
    ].join('\n')
    expect(parseConfigString(config, 'remote', 'origin', 'url')).toBe(
      'https://example.com',
    )
  })
})
