import { ZASection } from '../../../types'
import { formatZAExt, formatZARecord } from './022-format-za-record'

describe('formatZAExt', () => {
  describe('with undefined or empty ext', () => {
    it('should return 3 spaces when ext is undefined', () => {
      const result = formatZAExt(undefined)
      expect(result).toBe('   ')
      expect(result.length).toBe(3)
    })

    it('should return 3 spaces when ext is empty string', () => {
      const result = formatZAExt('')
      expect(result).toBe('   ')
      expect(result.length).toBe(3)
    })

    it('should return 3 spaces when ext is null', () => {
      const result = formatZAExt(null as any)
      expect(result).toBe('   ')
      expect(result.length).toBe(3)
    })
  })

  describe('with single character ext', () => {
    it('should format single digit correctly', () => {
      const result = formatZAExt('5')
      expect(result).toBe('-05')
      expect(result.length).toBe(3)
    })

    it('should format single letter correctly', () => {
      const result = formatZAExt('A')
      expect(result).toBe('-0A')
      expect(result.length).toBe(3)
    })

    it('should format zero correctly', () => {
      const result = formatZAExt('0')
      expect(result).toBe('-00')
      expect(result.length).toBe(3)
    })

    it('should format nine correctly', () => {
      const result = formatZAExt('9')
      expect(result).toBe('-09')
      expect(result.length).toBe(3)
    })
  })

  describe('with two character ext', () => {
    it('should format two digits correctly', () => {
      const result = formatZAExt('01')
      expect(result).toBe('-01')
      expect(result.length).toBe(3)
    })

    it('should format mixed characters correctly', () => {
      const result = formatZAExt('A1')
      expect(result).toBe('-A1')
      expect(result.length).toBe(3)
    })

    it('should format double zeros correctly', () => {
      const result = formatZAExt('00')
      expect(result).toBe('-00')
      expect(result.length).toBe(3)
    })

    it('should format high numbers correctly', () => {
      const result = formatZAExt('99')
      expect(result).toBe('-99')
      expect(result.length).toBe(3)
    })

    it('should format correctly-formatted "ext" correctly', () => {
      const result = formatZAExt('-01')
      expect(result).toBe('-01')
      expect(result.length).toBe(3)
    })
  })

  describe('with invalid ext lengths', () => {
    it('should throw error for 3 character ext', () => {
      expect(() => formatZAExt('123')).toThrow('Invalid ZA ext length')
    })

    it('should throw error for 4 character ext', () => {
      expect(() => formatZAExt('ABCD')).toThrow('Invalid ZA ext length')
    })

    it('should throw error for very long ext', () => {
      expect(() => formatZAExt('TOOLONG123')).toThrow('Invalid ZA ext length')
    })
  })
})

describe('formatZARecord', () => {
  describe('with all fields provided', () => {
    it('should format a complete ZA record correctly', () => {
      const za: ZASection = {
        date: '01022025',
        code: 'HHFA001',
        ext: '01',
        phase: 'A',
        act: '1',
        diag: '0',
        mod: 'MOD1',
        RE: '1',
        AN: '0',
        qty: '05'
      }

      const result = formatZARecord(za)

      // Total length should be 29 characters (8+7+3+1+1+1+4+1+1+2)
      expect(result.length).toBe(29)
      expect(result).toBe('01022025HHFA001-01A10MOD11005')
    })

    it('should format another complete ZA record correctly', () => {
      const za: ZASection = {
        date: '15122024',
        code: 'ZZHH003',
        ext: '99',
        phase: 'B',
        act: '2',
        diag: '1',
        mod: 'TEST',
        RE: '0',
        AN: '1',
        qty: '10'
      }

      const result = formatZARecord(za)

      expect(result.length).toBe(29)
      expect(result).toBe('15122024ZZHH003-99B21TEST0110')
    })
  })

  describe('with only required fields', () => {
    it('should format a minimal ZA record with proper padding', () => {
      const za: ZASection = {
        date: '01022025',
        code: 'HHFA001'
      }

      const result = formatZARecord(za)

      // Optional fields should be empty strings padded to their expected lengths
      expect(result).toBe('01022025HHFA001            00')
      expect(result.length).toBe(29)
    })

    it('should handle different date and code combinations', () => {
      const za: ZASection = {
        date: '31122023',
        code: 'ABC1234'
      }

      const result = formatZARecord(za)

      expect(result).toBe('31122023ABC1234            00')
      expect(result.length).toBe(29)
    })
  })

  describe('with partial optional fields', () => {
    it('should format ZA record with only ext field', () => {
      const za: ZASection = {
        date: '01022025',
        code: 'HHFA001',
        ext: '5'
      }

      const result = formatZARecord(za)

      // ext should be right-padded with zeros to 3 characters
      expect(result).toBe('01022025HHFA001-05         00')
      expect(result.length).toBe(29)
    })

    it('should format ZA record with only qty field', () => {
      const za: ZASection = {
        date: '01022025',
        code: 'HHFA001',
        qty: '7'
      }

      const result = formatZARecord(za)

      // qty should be right-padded with zeros to 2 characters
      expect(result).toBe('01022025HHFA001            07')
      expect(result.length).toBe(29)
    })

    it('should format ZA record with mixed optional fields', () => {
      const za: ZASection = {
        date: '01022025',
        code: 'HHFA001',
        phase: 'C',
        mod: 'XYZ',
        qty: '3'
      }

      const result = formatZARecord(za)

      expect(result).toBe('01022025HHFA001   C  XYZ   03')
      expect(result.length).toBe(29)
    })
  })

  describe('field padding behavior', () => {
    it('should pad date field to 8 characters', () => {
      const za: ZASection = {
        date: '123',
        code: 'TEST'
      }

      const result = formatZARecord(za)

      // date should be left-padded with spaces to 8 characters (LEFT alignment = padEnd)
      expect(result.substring(0, 8)).toBe('123     ')
    })

    it('should pad code field to 7 characters', () => {
      const za: ZASection = {
        date: '01022025',
        code: 'ABC'
      }

      const result = formatZARecord(za)

      // code should be left-padded with spaces to 7 characters (LEFT alignment = padEnd)
      expect(result.substring(8, 15)).toBe('ABC    ')
    })

    it('should pad ext field with zeros to the right', () => {
      const za: ZASection = {
        date: '01022025',
        code: 'HHFA001',
        ext: '5'
      }

      const result = formatZARecord(za)

      // ext should be right-padded with zeros to 3 characters
      expect(result.substring(15, 18)).toBe('-05')
    })

    it('should pad qty field with zeros to the right', () => {
      const za: ZASection = {
        date: '01022025',
        code: 'HHFA001',
        qty: '9'
      }

      const result = formatZARecord(za)

      // qty should be right-padded with zeros to 2 characters
      expect(result.substring(27, 29)).toBe('09')
    })

    it('should handle maximum length fields without truncation', () => {
      const za: ZASection = {
        date: '12345678', // 8 chars
        code: '1234567', // 7 chars
        ext: '123', // 3 chars
        phase: 'A', // 1 char
        act: '1', // 1 char
        diag: '0', // 1 char
        mod: '1234', // 4 chars
        RE: '1', // 1 char
        AN: '0', // 1 char
        qty: '99' // 2 chars
      }

      expect(() => formatZARecord(za)).toThrow()
    })
  })

  describe('edge cases', () => {
    it('should handle empty strings for optional fields', () => {
      const za: ZASection = {
        date: '01022025',
        code: 'HHFA001',
        ext: '',
        phase: '',
        act: '',
        diag: '',
        mod: '',
        RE: '',
        AN: '',
        qty: ''
      }

      const result = formatZARecord(za)

      expect(result).toBe('01022025HHFA001            00')
      expect(result.length).toBe(29)
    })

    it('should handle single character fields correctly', () => {
      const za: ZASection = {
        date: '01022025',
        code: 'A',
        ext: '01',
        phase: 'X',
        act: '9',
        diag: '2',
        mod: 'Z',
        RE: '8',
        AN: '7',
        qty: '1'
      }

      const result = formatZARecord(za)

      expect(result).toBe('01022025A      -01X92Z   8701')
      expect(result.length).toBe(29)
    })

    it('should handle undefined optional fields (should behave same as not provided)', () => {
      const za: ZASection = {
        date: '01022025',
        code: 'HHFA001',
        ext: undefined,
        phase: undefined,
        act: undefined,
        diag: undefined,
        mod: undefined,
        RE: undefined,
        AN: undefined,
        qty: undefined
      }

      const result = formatZARecord(za)

      expect(result).toBe('01022025HHFA001            00')
      expect(result.length).toBe(29)
    })
  })

  describe('field-by-field validation', () => {
    it('should correctly position each field in the output', () => {
      const za: ZASection = {
        date: '01022025',
        code: 'HHFA001',
        ext: '01',
        phase: 'A',
        act: '1',
        diag: '0',
        mod: 'MOD1',
        RE: '1',
        AN: '0',
        qty: '05'
      }

      const result = formatZARecord(za)

      // Verify each field is in the correct position
      expect(result.substring(0, 8)).toBe('01022025') // date (8 chars)
      expect(result.substring(8, 15)).toBe('HHFA001') // code (7 chars)
      expect(result.substring(15, 18)).toBe('-01') // ext (3 chars, right-padded with zeros)
      expect(result.substring(18, 19)).toBe('A') // phase (1 char)
      expect(result.substring(19, 20)).toBe('1') // act (1 char)
      expect(result.substring(20, 21)).toBe('0') // diag (1 char)
      expect(result.substring(21, 25)).toBe('MOD1') // mod (4 chars)
      expect(result.substring(25, 26)).toBe('1') // RE (1 char)
      expect(result.substring(26, 27)).toBe('0') // AN (1 char)
      expect(result.substring(27, 29)).toBe('05') // qty (2 chars, right-padded with zeros)
    })
  })
})
