import { describe, it, expect } from 'vitest'
import { getDealOwnership } from './deal-ownership'

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------

function makeEvent(type: string, timestamp: string): Record<string, unknown> {
  return { type, timestamp }
}

// ---------------------------------------------------------------------------
// Closed deals
// ---------------------------------------------------------------------------

describe('getDealOwnership — closed deals', () => {
  it('returns null for closed_won regardless of activity_log', () => {
    const deal = {
      state_key: 'closed_won',
      activity_log: [makeEvent('reply_received', '2026-01-10T10:00:00Z')]
    }
    expect(getDealOwnership(deal)).toBeNull()
  })

  it('returns null for closed_lost regardless of activity_log', () => {
    const deal = {
      state_key: 'closed_lost',
      activity_log: [makeEvent('reply_received', '2026-01-10T10:00:00Z')]
    }
    expect(getDealOwnership(deal)).toBeNull()
  })
})

// ---------------------------------------------------------------------------
// Empty / missing activity log
// ---------------------------------------------------------------------------

describe('getDealOwnership — empty activity log', () => {
  it('returns null when activity_log is an empty array', () => {
    expect(getDealOwnership({ state_key: 'discovery_replied', activity_log: [] })).toBeNull()
  })

  it('returns null when activity_log is null', () => {
    expect(getDealOwnership({ state_key: 'discovery_replied', activity_log: null })).toBeNull()
  })

  it('returns null when activity_log is undefined', () => {
    expect(getDealOwnership({ state_key: 'discovery_replied', activity_log: undefined })).toBeNull()
  })

  it('returns null when activity_log is a non-array value', () => {
    expect(getDealOwnership({ state_key: 'discovery_replied', activity_log: 'bad' })).toBeNull()
  })

  it('returns null when activity_log contains no inbound or outbound events', () => {
    const deal = {
      state_key: 'discovery_replied',
      activity_log: [
        makeEvent('deal_created', '2026-01-01T00:00:00Z'),
        makeEvent('stage_change', '2026-01-02T00:00:00Z')
      ]
    }
    expect(getDealOwnership(deal)).toBeNull()
  })
})

// ---------------------------------------------------------------------------
// us ownership (inbound is most recent)
// ---------------------------------------------------------------------------

describe('getDealOwnership — us ownership', () => {
  it('returns "us" when inbound event is newer than outbound event', () => {
    const deal = {
      state_key: 'discovery_replied',
      activity_log: [
        makeEvent('reply_sent_to_lead', '2026-01-10T10:00:00Z'),
        makeEvent('reply_received', '2026-01-11T10:00:00Z')
      ]
    }
    expect(getDealOwnership(deal)).toBe('us')
  })

  it('returns "us" when only a reply_received event exists', () => {
    const deal = {
      state_key: 'discovery_replied',
      activity_log: [makeEvent('reply_received', '2026-01-10T10:00:00Z')]
    }
    expect(getDealOwnership(deal)).toBe('us')
  })

  it('returns "us" with mixed irrelevant events present', () => {
    const deal = {
      state_key: 'discovery_replied',
      activity_log: [
        makeEvent('deal_created', '2026-01-01T00:00:00Z'),
        makeEvent('reply_sent_to_lead', '2026-01-10T08:00:00Z'),
        makeEvent('state_change', '2026-01-10T09:00:00Z'),
        makeEvent('reply_received', '2026-01-10T12:00:00Z')
      ]
    }
    expect(getDealOwnership(deal)).toBe('us')
  })

  it('returns "us" picking the latest of multiple inbound events', () => {
    const deal = {
      state_key: 'discovery_replied',
      activity_log: [
        makeEvent('reply_sent_to_lead', '2026-01-10T10:00:00Z'),
        makeEvent('reply_received', '2026-01-09T10:00:00Z'),
        makeEvent('reply_received', '2026-01-11T10:00:00Z')
      ]
    }
    expect(getDealOwnership(deal)).toBe('us')
  })
})

// ---------------------------------------------------------------------------
// them ownership (outbound is most recent or tied)
// ---------------------------------------------------------------------------

describe('getDealOwnership — them ownership', () => {
  it('returns "them" when outbound event is newer than inbound event', () => {
    const deal = {
      state_key: 'discovery_replied',
      activity_log: [
        makeEvent('reply_received', '2026-01-10T10:00:00Z'),
        makeEvent('reply_sent_to_lead', '2026-01-11T10:00:00Z')
      ]
    }
    expect(getDealOwnership(deal)).toBe('them')
  })

  it('returns "them" on exact timestamp tie (outbound wins tie-break)', () => {
    const deal = {
      state_key: 'discovery_replied',
      activity_log: [
        makeEvent('reply_received', '2026-01-10T10:00:00Z'),
        makeEvent('reply_sent_to_lead', '2026-01-10T10:00:00Z')
      ]
    }
    expect(getDealOwnership(deal)).toBe('them')
  })

  it('returns "them" when only outbound events exist', () => {
    const deal = {
      state_key: 'discovery_replied',
      activity_log: [makeEvent('booking_nudge_sent', '2026-01-10T10:00:00Z')]
    }
    expect(getDealOwnership(deal)).toBe('them')
  })

  it('returns "them" for each outbound type independently', () => {
    const outboundTypes = [
      'reply_sent_to_lead',
      'booking_nudge_sent',
      'reminder_sent',
      'rebook_sent',
      'followup_email_sent',
      'reply_followup_sent',
      'lead_deferred_next_step'
    ] as const

    for (const type of outboundTypes) {
      const deal = {
        state_key: 'discovery_replied',
        activity_log: [makeEvent(type, '2026-01-10T10:00:00Z')]
      }
      expect(getDealOwnership(deal), `expected "them" for outbound type: ${type}`).toBe('them')
    }
  })

  it('returns "them" picking the latest of multiple outbound events', () => {
    const deal = {
      state_key: 'discovery_replied',
      activity_log: [
        makeEvent('reply_received', '2026-01-10T10:00:00Z'),
        makeEvent('reply_sent_to_lead', '2026-01-09T10:00:00Z'),
        makeEvent('booking_nudge_sent', '2026-01-11T10:00:00Z')
      ]
    }
    expect(getDealOwnership(deal)).toBe('them')
  })

  it('treats canonical and legacy follow-up events as outbound ownership inputs', () => {
    const canonical = {
      state_key: 'followup_1_sent',
      activity_log: [
        makeEvent('reply_received', '2026-01-10T10:00:00Z'),
        makeEvent('followup_email_sent', '2026-01-11T10:00:00Z')
      ]
    }
    const legacy = {
      state_key: 'followup_1_sent',
      activity_log: [
        makeEvent('reply_received', '2026-01-10T10:00:00Z'),
        makeEvent('reply_followup_sent', '2026-01-11T10:00:00Z')
      ]
    }

    expect(getDealOwnership(canonical)).toBe('them')
    expect(getDealOwnership(legacy)).toBe('them')
  })
})

// ---------------------------------------------------------------------------
// Timestamp COALESCE — alternate timestamp field names
// ---------------------------------------------------------------------------

describe('getDealOwnership — timestamp field coalesce', () => {
  it('resolves timestamp from occurredAt field', () => {
    const deal = {
      state_key: 'discovery_replied',
      activity_log: [
        { type: 'reply_received', occurredAt: '2026-01-11T10:00:00Z' },
        { type: 'reply_sent_to_lead', occurredAt: '2026-01-10T10:00:00Z' }
      ]
    }
    expect(getDealOwnership(deal)).toBe('us')
  })

  it('resolves timestamp from createdAt field', () => {
    const deal = {
      state_key: 'discovery_replied',
      activity_log: [{ type: 'reply_received', createdAt: '2026-01-10T10:00:00Z' }]
    }
    expect(getDealOwnership(deal)).toBe('us')
  })

  it('resolves timestamp from updatedAt field', () => {
    const deal = {
      state_key: 'discovery_replied',
      activity_log: [{ type: 'reply_sent_to_lead', updatedAt: '2026-01-10T10:00:00Z' }]
    }
    expect(getDealOwnership(deal)).toBe('them')
  })

  it('resolves timestamp from sentAt field', () => {
    const deal = {
      state_key: 'discovery_replied',
      activity_log: [{ type: 'reply_sent_to_lead', sentAt: '2026-01-10T10:00:00Z' }]
    }
    expect(getDealOwnership(deal)).toBe('them')
  })

  it('prefers timestamp over occurredAt when both present', () => {
    // outbound has timestamp=newer, inbound has occurredAt=older → "them"
    const deal = {
      state_key: 'discovery_replied',
      activity_log: [
        { type: 'reply_received', timestamp: '2026-01-09T00:00:00Z', occurredAt: '2026-01-12T00:00:00Z' },
        { type: 'reply_sent_to_lead', timestamp: '2026-01-10T00:00:00Z' }
      ]
    }
    // inbound timestamp=Jan 9, outbound timestamp=Jan 10 → outbound newer → "them"
    expect(getDealOwnership(deal)).toBe('them')
  })
})

// ---------------------------------------------------------------------------
// Malformed entries — must be silently skipped
// ---------------------------------------------------------------------------

describe('getDealOwnership — malformed events skipped', () => {
  it('skips entries with no timestamp field', () => {
    const deal = {
      state_key: 'discovery_replied',
      activity_log: [
        { type: 'reply_received' }, // no timestamp
        makeEvent('reply_sent_to_lead', '2026-01-10T10:00:00Z')
      ]
    }
    // Only the outbound event has a valid timestamp — result is "them"
    expect(getDealOwnership(deal)).toBe('them')
  })

  it('skips entries with an invalid timestamp string', () => {
    const deal = {
      state_key: 'discovery_replied',
      activity_log: [
        { type: 'reply_received', timestamp: 'not-a-date' },
        makeEvent('reply_sent_to_lead', '2026-01-10T10:00:00Z')
      ]
    }
    expect(getDealOwnership(deal)).toBe('them')
  })

  it('skips null entries in the array', () => {
    const deal = {
      state_key: 'discovery_replied',
      activity_log: [null, makeEvent('reply_received', '2026-01-10T10:00:00Z')]
    }
    expect(getDealOwnership(deal)).toBe('us')
  })

  it('skips non-object entries in the array', () => {
    const deal = {
      state_key: 'discovery_replied',
      activity_log: ['string', 42, makeEvent('reply_sent_to_lead', '2026-01-10T10:00:00Z')]
    }
    expect(getDealOwnership(deal)).toBe('them')
  })

  it('skips array-in-array entries', () => {
    const deal = {
      state_key: 'discovery_replied',
      activity_log: [[], makeEvent('reply_received', '2026-01-10T10:00:00Z')]
    }
    expect(getDealOwnership(deal)).toBe('us')
  })

  it('skips entries with missing type field', () => {
    const deal = {
      state_key: 'discovery_replied',
      activity_log: [
        { timestamp: '2026-01-10T10:00:00Z' }, // no type
        makeEvent('reply_sent_to_lead', '2026-01-11T10:00:00Z')
      ]
    }
    expect(getDealOwnership(deal)).toBe('them')
  })

  it('returns null when all entries are malformed', () => {
    const deal = {
      state_key: 'discovery_replied',
      activity_log: [null, 'bad', { type: 'reply_received' }]
    }
    expect(getDealOwnership(deal)).toBeNull()
  })
})

// ---------------------------------------------------------------------------
// state_key variants (non-closed)
// ---------------------------------------------------------------------------

describe('getDealOwnership — non-closed state_key variants', () => {
  it('evaluates ownership for null state_key', () => {
    const deal = {
      state_key: null,
      activity_log: [makeEvent('reply_received', '2026-01-10T10:00:00Z')]
    }
    expect(getDealOwnership(deal)).toBe('us')
  })

  it('evaluates ownership for discovery_link_sent state', () => {
    const deal = {
      state_key: 'discovery_link_sent',
      activity_log: [makeEvent('booking_nudge_sent', '2026-01-10T10:00:00Z')]
    }
    expect(getDealOwnership(deal)).toBe('them')
  })
})
