import { describe, expect, it } from 'vitest'
import {
  CustomersDomainSchema,
  CustomerSegmentSchema,
  DEFAULT_ORGANIZATION_MODEL_CUSTOMERS,
  FirmographicsSchema
} from '../../domains/customers'
import { resolveOrganizationModel } from '../../resolve'

// ---------------------------------------------------------------------------
// Group 1: CustomerSegmentSchema — positive parse
// ---------------------------------------------------------------------------

describe('CustomerSegmentSchema — positive parse', () => {
  it('accepts a fully-populated segment', () => {
    const result = CustomerSegmentSchema.safeParse({
      id: 'segment-smb-agencies',
      order: 10,
      name: 'SMB Marketing Agencies',
      description: 'Small marketing agencies with 1–50 employees seeking automation.',
      jobsToBeDone: 'Automate client reporting and lead generation workflows.',
      pains: ['Too many manual tasks', 'Clients expect faster turnaround'],
      gains: ['More time for creative work', 'Higher client retention'],
      firmographics: {
        industry: 'Marketing Agency',
        companySize: '1–50',
        region: 'North America'
      },
      valueProp: 'Elevasis reduces manual ops by 80% for agencies under 50 people.'
    })
    expect(result.success).toBe(true)
  })

  it('accepts a minimal segment — only id and order required', () => {
    const result = CustomerSegmentSchema.safeParse({ id: 'seg-minimal', order: 10 })
    expect(result.success).toBe(true)
    if (result.success) {
      expect(result.data.id).toBe('seg-minimal')
      expect(result.data.name).toBe('')
      expect(result.data.description).toBe('')
      expect(result.data.jobsToBeDone).toBe('')
      expect(result.data.pains).toEqual([])
      expect(result.data.gains).toEqual([])
      expect(result.data.firmographics).toEqual({})
      expect(result.data.valueProp).toBe('')
    }
  })

  it('trims whitespace from string fields', () => {
    const result = CustomerSegmentSchema.safeParse({
      id: '  seg-trim  ',
      order: 10,
      name: '  Trimmed Name  ',
      valueProp: '  Trimmed value prop.  '
    })
    expect(result.success).toBe(true)
    if (result.success) {
      expect(result.data.id).toBe('seg-trim')
      expect(result.data.name).toBe('Trimmed Name')
      expect(result.data.valueProp).toBe('Trimmed value prop.')
    }
  })

  it('accepts pains and gains as non-empty arrays', () => {
    const result = CustomerSegmentSchema.safeParse({
      id: 'seg-arrays',
      order: 10,
      pains: ['Pain A', 'Pain B', 'Pain C'],
      gains: ['Gain X', 'Gain Y']
    })
    expect(result.success).toBe(true)
    if (result.success) {
      expect(result.data.pains).toHaveLength(3)
      expect(result.data.gains).toHaveLength(2)
    }
  })
})

// ---------------------------------------------------------------------------
// Group 2: CustomerSegmentSchema — default values
// ---------------------------------------------------------------------------

describe('CustomerSegmentSchema — default values', () => {
  it('pains defaults to empty array', () => {
    const result = CustomerSegmentSchema.safeParse({ id: 'seg-defaults', order: 10 })
    expect(result.success).toBe(true)
    if (result.success) {
      expect(result.data.pains).toEqual([])
    }
  })

  it('gains defaults to empty array', () => {
    const result = CustomerSegmentSchema.safeParse({ id: 'seg-defaults', order: 10 })
    expect(result.success).toBe(true)
    if (result.success) {
      expect(result.data.gains).toEqual([])
    }
  })

  it('firmographics defaults to empty object', () => {
    const result = CustomerSegmentSchema.safeParse({ id: 'seg-defaults', order: 10 })
    expect(result.success).toBe(true)
    if (result.success) {
      expect(result.data.firmographics).toEqual({})
    }
  })

  it('all string fields default to empty string', () => {
    const result = CustomerSegmentSchema.safeParse({ id: 'seg-str-defaults', order: 10 })
    expect(result.success).toBe(true)
    if (result.success) {
      expect(result.data.name).toBe('')
      expect(result.data.description).toBe('')
      expect(result.data.jobsToBeDone).toBe('')
      expect(result.data.valueProp).toBe('')
    }
  })
})

// ---------------------------------------------------------------------------
// Group 3: CustomerSegmentSchema — negative parse (wrong types / constraints)
// ---------------------------------------------------------------------------

describe('CustomerSegmentSchema — negative parse', () => {
  it('rejects missing id', () => {
    const result = CustomerSegmentSchema.safeParse({ order: 10, name: 'No ID Segment' })
    expect(result.success).toBe(false)
  })

  it('rejects empty string id', () => {
    const result = CustomerSegmentSchema.safeParse({ id: '', order: 10 })
    expect(result.success).toBe(false)
  })

  it('rejects whitespace-only id (trims to empty string)', () => {
    const result = CustomerSegmentSchema.safeParse({ id: '   ', order: 10 })
    expect(result.success).toBe(false)
  })

  it('rejects id as a number', () => {
    const result = CustomerSegmentSchema.safeParse({ id: 42, order: 10 })
    expect(result.success).toBe(false)
  })

  it('rejects pains as a non-array value', () => {
    const result = CustomerSegmentSchema.safeParse({ id: 'seg-bad-pains', order: 10, pains: 'not an array' })
    expect(result.success).toBe(false)
  })

  it('rejects gains containing a non-string element', () => {
    const result = CustomerSegmentSchema.safeParse({ id: 'seg-bad-gains', order: 10, gains: [42, 'valid'] })
    expect(result.success).toBe(false)
  })

  it('rejects name exceeding 200 characters', () => {
    const result = CustomerSegmentSchema.safeParse({ id: 'seg-long-name', order: 10, name: 'x'.repeat(201) })
    expect(result.success).toBe(false)
  })

  it('rejects description exceeding 2000 characters', () => {
    const result = CustomerSegmentSchema.safeParse({ id: 'seg-long-desc', order: 10, description: 'x'.repeat(2001) })
    expect(result.success).toBe(false)
  })
})

// ---------------------------------------------------------------------------
// Group 4: FirmographicsSchema
// ---------------------------------------------------------------------------

describe('FirmographicsSchema', () => {
  it('accepts a fully-populated firmographics object', () => {
    const result = FirmographicsSchema.safeParse({
      industry: 'Legal',
      companySize: '11–50',
      region: 'Europe'
    })
    expect(result.success).toBe(true)
  })

  it('accepts an empty object (all fields optional)', () => {
    const result = FirmographicsSchema.safeParse({})
    expect(result.success).toBe(true)
    if (result.success) {
      expect(result.data.industry).toBeUndefined()
      expect(result.data.companySize).toBeUndefined()
      expect(result.data.region).toBeUndefined()
    }
  })

  it('accepts partial firmographics — only industry provided', () => {
    const result = FirmographicsSchema.safeParse({ industry: 'SaaS' })
    expect(result.success).toBe(true)
    if (result.success) {
      expect(result.data.industry).toBe('SaaS')
      expect(result.data.companySize).toBeUndefined()
      expect(result.data.region).toBeUndefined()
    }
  })

  it('rejects industry as a number', () => {
    const result = FirmographicsSchema.safeParse({ industry: 99 })
    expect(result.success).toBe(false)
  })
})

// ---------------------------------------------------------------------------
// Group 5: CustomersDomainSchema
// ---------------------------------------------------------------------------

describe('CustomersDomainSchema — structural', () => {
  it('accepts an empty segments record', () => {
    const result = CustomersDomainSchema.safeParse({})
    expect(result.success).toBe(true)
  })

  it('defaults segments to empty record when omitted', () => {
    const result = CustomersDomainSchema.safeParse({})
    expect(result.success).toBe(true)
    if (result.success) {
      expect(result.data).toEqual({})
    }
  })

  it('accepts multiple valid segments', () => {
    const result = CustomersDomainSchema.safeParse({
      'seg-a': { id: 'seg-a', order: 10, name: 'Segment A' },
      'seg-b': { id: 'seg-b', order: 20, name: 'Segment B', pains: ['Pain 1'] }
    })
    expect(result.success).toBe(true)
    if (result.success) {
      expect(Object.keys(result.data)).toHaveLength(2)
    }
  })

  it('rejects a record where entry id does not match map key', () => {
    const result = CustomersDomainSchema.safeParse({
      'seg-a': { id: 'seg-b', order: 10, name: 'Mismatched' }
    })
    expect(result.success).toBe(false)
  })

  it('DEFAULT_ORGANIZATION_MODEL_CUSTOMERS constant matches schema parse of empty object', () => {
    const result = CustomersDomainSchema.safeParse({})
    expect(result.success).toBe(true)
    if (result.success) {
      expect(result.data).toEqual(DEFAULT_ORGANIZATION_MODEL_CUSTOMERS)
    }
  })
})

// ---------------------------------------------------------------------------
// Group 6: Integration — resolveOrganizationModel
// ---------------------------------------------------------------------------

describe('resolveOrganizationModel — customers domain integration', () => {
  it('merges partial customers override and preserves empty segments default', () => {
    const model = resolveOrganizationModel({
      customers: {}
    })
    expect(Object.keys(model.customers)).toHaveLength(0)
  })

  it('merges a customers override with populated segments into resolved model', () => {
    const model = resolveOrganizationModel({
      customers: {
        'seg-agencies': {
          id: 'seg-agencies',
          order: 10,
          name: 'Agency Owners',
          pains: ['Too much manual work'],
          gains: ['More client capacity'],
          valueProp: 'Automate the repetitive parts of agency ops.'
        }
      }
    })
    expect(Object.keys(model.customers)).toHaveLength(1)
    expect(model.customers['seg-agencies'].id).toBe('seg-agencies')
    expect(model.customers['seg-agencies'].pains).toEqual(['Too much manual work'])
    expect(model.customers['seg-agencies'].description).toBe('')
  })

  it('does not bleed customers changes into other top-level domains', () => {
    const model = resolveOrganizationModel({
      customers: { 'seg-isolated': { id: 'seg-isolated', order: 10 } }
    })
    expect(model.identity).toBeDefined()
    expect(model.systems).toBeDefined()
    // Phase 4 (D1, D8): model.statuses and model.navigation removed from top-level OM.
    // Verify other sibling domains are still intact instead.
    expect(model.knowledge).toBeDefined()
    expect(model.navigation).toBeDefined()
  })

  it('omitting customers key entirely resolves to default empty segments', () => {
    const model = resolveOrganizationModel({})
    expect(model.customers).toBeDefined()
    expect(Object.keys(model.customers)).toHaveLength(0)
  })
})
