import { describe, expect, it } from 'vitest'
import {
  BusinessHoursDaySchema,
  BusinessHoursSchema,
  DEFAULT_ORGANIZATION_MODEL_IDENTITY,
  IdentityDomainSchema
} from '../../domains/identity'
import { resolveOrganizationModel } from '../../resolve'

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

describe('IdentityDomainSchema — positive parse', () => {
  it('accepts a fully-populated identity object', () => {
    const result = IdentityDomainSchema.safeParse({
      mission: 'Help businesses automate complex work.',
      vision: 'A world where every team has an AI co-pilot.',
      legalName: 'Acme Corp LLC',
      entityType: 'LLC',
      jurisdiction: 'United States – Delaware',
      industryCategory: 'Software / SaaS',
      geographicFocus: 'North America',
      timeZone: 'America/Los_Angeles',
      businessHours: {
        monday: { open: '09:00', close: '17:00' },
        friday: { open: '09:00', close: '15:00' }
      }
    })
    expect(result.success).toBe(true)
  })

  it('accepts a minimal input (empty object) and applies all defaults', () => {
    const result = IdentityDomainSchema.safeParse({})
    expect(result.success).toBe(true)
    if (result.success) {
      expect(result.data.mission).toBe('')
      expect(result.data.vision).toBe('')
      expect(result.data.legalName).toBe('')
      expect(result.data.entityType).toBe('')
      expect(result.data.jurisdiction).toBe('')
      expect(result.data.industryCategory).toBe('')
      expect(result.data.geographicFocus).toBe('')
      expect(result.data.timeZone).toBe('UTC')
      expect(result.data.businessHours).toEqual({})
    }
  })

  it('accepts a partial object — only mission and timeZone provided', () => {
    const result = IdentityDomainSchema.safeParse({
      mission: 'Ship great software.',
      timeZone: 'Europe/London'
    })
    expect(result.success).toBe(true)
    if (result.success) {
      expect(result.data.mission).toBe('Ship great software.')
      expect(result.data.timeZone).toBe('Europe/London')
      expect(result.data.vision).toBe('')
    }
  })

  it('trims leading/trailing whitespace from string fields', () => {
    const result = IdentityDomainSchema.safeParse({
      mission: '  Trimmed mission.  ',
      legalName: '  Trimmed Name  '
    })
    expect(result.success).toBe(true)
    if (result.success) {
      expect(result.data.mission).toBe('Trimmed mission.')
      expect(result.data.legalName).toBe('Trimmed Name')
    }
  })
})

// ---------------------------------------------------------------------------
// Group 2: Default values
// ---------------------------------------------------------------------------

describe('IdentityDomainSchema — default values', () => {
  it('timeZone defaults to "UTC"', () => {
    const result = IdentityDomainSchema.safeParse({})
    expect(result.success).toBe(true)
    if (result.success) {
      expect(result.data.timeZone).toBe('UTC')
    }
  })

  it('businessHours defaults to empty object', () => {
    const result = IdentityDomainSchema.safeParse({})
    expect(result.success).toBe(true)
    if (result.success) {
      expect(result.data.businessHours).toEqual({})
    }
  })

  it('all string fields default to empty string', () => {
    const result = IdentityDomainSchema.safeParse({})
    expect(result.success).toBe(true)
    if (result.success) {
      const stringDefaults: (keyof typeof result.data)[] = [
        'mission',
        'vision',
        'legalName',
        'entityType',
        'jurisdiction',
        'industryCategory',
        'geographicFocus'
      ]
      for (const field of stringDefaults) {
        expect(result.data[field], `field "${field}" should default to ""`).toBe('')
      }
    }
  })

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

// ---------------------------------------------------------------------------
// Group 3: BusinessHoursSchema — valid shapes
// ---------------------------------------------------------------------------

describe('BusinessHoursSchema — valid shapes', () => {
  it('accepts all seven days populated', () => {
    const result = BusinessHoursSchema.safeParse({
      monday: { open: '08:00', close: '17:00' },
      tuesday: { open: '08:00', close: '17:00' },
      wednesday: { open: '08:00', close: '17:00' },
      thursday: { open: '08:00', close: '17:00' },
      friday: { open: '08:00', close: '17:00' },
      saturday: { open: '10:00', close: '14:00' },
      sunday: { open: '10:00', close: '14:00' }
    })
    expect(result.success).toBe(true)
  })

  it('accepts an object with only some days present (others are optional)', () => {
    const result = BusinessHoursSchema.safeParse({
      monday: { open: '09:00', close: '18:00' }
    })
    expect(result.success).toBe(true)
    if (result.success) {
      expect(result.data.tuesday).toBeUndefined()
      expect(result.data.sunday).toBeUndefined()
    }
  })

  it('defaults to empty object when input is undefined (schema .default({}))', () => {
    const result = BusinessHoursSchema.safeParse(undefined)
    expect(result.success).toBe(true)
    if (result.success) {
      expect(result.data).toEqual({})
    }
  })
})

// ---------------------------------------------------------------------------
// Group 4: BusinessHoursDaySchema — HH:MM format validation
// ---------------------------------------------------------------------------

describe('BusinessHoursDaySchema — HH:MM regex', () => {
  it('accepts valid 24-hour HH:MM values', () => {
    const result = BusinessHoursDaySchema.safeParse({ open: '00:00', close: '23:59' })
    expect(result.success).toBe(true)
  })

  it('rejects time without leading zero (9:00 instead of 09:00)', () => {
    const result = BusinessHoursDaySchema.safeParse({ open: '9:00', close: '17:00' })
    expect(result.success).toBe(false)
  })

  it('rejects time with seconds appended (HH:MM:SS)', () => {
    const result = BusinessHoursDaySchema.safeParse({ open: '09:00:00', close: '17:00:00' })
    expect(result.success).toBe(false)
  })

  it('rejects time with AM/PM suffix', () => {
    const result = BusinessHoursDaySchema.safeParse({ open: '09:00AM', close: '05:00PM' })
    expect(result.success).toBe(false)
  })

  it('rejects missing close field', () => {
    const result = BusinessHoursDaySchema.safeParse({ open: '09:00' })
    expect(result.success).toBe(false)
  })

  it('rejects non-string open value (number)', () => {
    const result = BusinessHoursDaySchema.safeParse({ open: 900, close: '17:00' })
    expect(result.success).toBe(false)
  })
})

// ---------------------------------------------------------------------------
// Group 5: IdentityDomainSchema — negative parse (wrong types / over-max)
// ---------------------------------------------------------------------------

describe('IdentityDomainSchema — negative parse', () => {
  it('rejects mission as a number', () => {
    const result = IdentityDomainSchema.safeParse({ mission: 42 })
    expect(result.success).toBe(false)
  })

  it('rejects timeZone as a number', () => {
    const result = IdentityDomainSchema.safeParse({ timeZone: 0 })
    expect(result.success).toBe(false)
  })

  it('rejects mission exceeding 1000 characters', () => {
    const result = IdentityDomainSchema.safeParse({ mission: 'x'.repeat(1001) })
    expect(result.success).toBe(false)
  })

  it('rejects legalName exceeding 200 characters', () => {
    const result = IdentityDomainSchema.safeParse({ legalName: 'x'.repeat(201) })
    expect(result.success).toBe(false)
  })

  it('rejects entityType exceeding 100 characters', () => {
    const result = IdentityDomainSchema.safeParse({ entityType: 'x'.repeat(101) })
    expect(result.success).toBe(false)
  })

  it('rejects timeZone exceeding 100 characters', () => {
    const result = IdentityDomainSchema.safeParse({ timeZone: 'x'.repeat(101) })
    expect(result.success).toBe(false)
  })
})

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

describe('resolveOrganizationModel — identity domain integration', () => {
  it('merges partial identity override and preserves unset fields as defaults', () => {
    const model = resolveOrganizationModel({
      identity: { mission: 'Build the future.' }
    })
    expect(model.identity.mission).toBe('Build the future.')
    expect(model.identity.timeZone).toBe('UTC')
    expect(model.identity.vision).toBe('')
    expect(model.identity.businessHours).toEqual({})
  })

  it('fully-specified identity override round-trips through resolveOrganizationModel', () => {
    const override = {
      identity: {
        mission: 'Automate everything.',
        vision: 'Zero manual work.',
        legalName: 'Test Corp Inc',
        entityType: 'Corporation',
        jurisdiction: 'United States – California',
        industryCategory: 'Software / SaaS',
        geographicFocus: 'Global',
        timeZone: 'America/Chicago',
        clientBrief: '',
        businessHours: {
          monday: { open: '09:00', close: '17:00' }
        }
      }
    }
    const model = resolveOrganizationModel(override)
    expect(model.identity).toEqual(override.identity)
  })

  it('does not bleed identity changes into other top-level domains', () => {
    const model = resolveOrganizationModel({
      identity: { mission: 'Isolated change.' }
    })
    // Phase 4 (D1, D8): model.navigation and model.statuses removed from top-level OM.
    // Verify other sibling domains still present instead.
    expect(model.systems).toBeDefined()
    expect(model.knowledge).toBeDefined()
    expect(model.navigation).toBeDefined()
  })
})
