import { describe, it, expect, vi, beforeEach } from 'vitest'
import { ref, computed } from 'vue'
import { MEMBER_STATUSES, MEMBER_STATUS_CONFIG, useMemberStatus } from '../../../app/composables/useMemberStatus.js'

// Stub Vue's computed as a global (Nuxt auto-import)
vi.stubGlobal('computed', computed)

// Shared reactive ref for controlling member status in tests
const memberData = ref({ status: 'active' })
vi.stubGlobal('useAuth', () => ({ memberData }))

describe('MEMBER_STATUSES', () => {
  it('has all four status keys', () => {
    expect(Object.keys(MEMBER_STATUSES)).toEqual([
      'PENDING_PAYMENT', 'ACTIVE', 'SUSPENDED', 'CANCELLED',
    ])
  })

  it('maps to expected string values', () => {
    expect(MEMBER_STATUSES.PENDING_PAYMENT).toBe('pending_payment')
    expect(MEMBER_STATUSES.ACTIVE).toBe('active')
    expect(MEMBER_STATUSES.SUSPENDED).toBe('suspended')
    expect(MEMBER_STATUSES.CANCELLED).toBe('cancelled')
  })
})

describe('MEMBER_STATUS_CONFIG', () => {
  const requiredFields = ['label', 'color', 'canRSVP', 'canAccessMembers', 'canPeerSupport']

  it('has config for every status value', () => {
    for (const status of Object.values(MEMBER_STATUSES)) {
      expect(MEMBER_STATUS_CONFIG).toHaveProperty(status)
    }
  })

  it('each config has required fields', () => {
    for (const [key, config] of Object.entries(MEMBER_STATUS_CONFIG)) {
      for (const field of requiredFields) {
        expect(config, `${key} missing ${field}`).toHaveProperty(field)
      }
    }
  })

  it('active has full permissions', () => {
    const cfg = MEMBER_STATUS_CONFIG.active
    expect(cfg.canRSVP).toBe(true)
    expect(cfg.canAccessMembers).toBe(true)
    expect(cfg.canPeerSupport).toBe(true)
  })

  it('pending_payment can access members but not RSVP or peer support', () => {
    const cfg = MEMBER_STATUS_CONFIG.pending_payment
    expect(cfg.canRSVP).toBe(false)
    expect(cfg.canAccessMembers).toBe(true)
    expect(cfg.canPeerSupport).toBe(false)
  })

  it('suspended has all permissions false', () => {
    const cfg = MEMBER_STATUS_CONFIG.suspended
    expect(cfg.canRSVP).toBe(false)
    expect(cfg.canAccessMembers).toBe(false)
    expect(cfg.canPeerSupport).toBe(false)
  })

  it('cancelled has all permissions false', () => {
    const cfg = MEMBER_STATUS_CONFIG.cancelled
    expect(cfg.canRSVP).toBe(false)
    expect(cfg.canAccessMembers).toBe(false)
    expect(cfg.canPeerSupport).toBe(false)
  })
})

describe('useMemberStatus composable', () => {
  beforeEach(() => {
    memberData.value = { status: 'active' }
  })

  describe('status detection', () => {
    it('defaults to pending_payment when memberData has no status', () => {
      memberData.value = {}
      const { status } = useMemberStatus()
      expect(status.value).toBe('pending_payment')
    })

    it('defaults to pending_payment when memberData is null', () => {
      memberData.value = null
      const { status } = useMemberStatus()
      expect(status.value).toBe('pending_payment')
    })

    it('isActive is true when status is active', () => {
      memberData.value = { status: 'active' }
      const { isActive } = useMemberStatus()
      expect(isActive.value).toBe(true)
    })

    it('isActive is false when status is not active', () => {
      memberData.value = { status: 'suspended' }
      const { isActive, isInactive } = useMemberStatus()
      expect(isActive.value).toBe(false)
      expect(isInactive.value).toBe(true)
    })
  })

  describe('permissions', () => {
    it('canRSVP is true when active', () => {
      memberData.value = { status: 'active' }
      const { canRSVP } = useMemberStatus()
      expect(canRSVP.value).toBe(true)
    })

    it('canRSVP is false when pending_payment', () => {
      memberData.value = { status: 'pending_payment' }
      const { canRSVP } = useMemberStatus()
      expect(canRSVP.value).toBe(false)
    })

    it('canAccessMembers is true for active and pending_payment', () => {
      for (const status of ['active', 'pending_payment']) {
        memberData.value = { status }
        const { canAccessMembers } = useMemberStatus()
        expect(canAccessMembers.value, `expected true for ${status}`).toBe(true)
      }
    })

    it('canAccessMembers is false for suspended and cancelled', () => {
      for (const status of ['suspended', 'cancelled']) {
        memberData.value = { status }
        const { canAccessMembers } = useMemberStatus()
        expect(canAccessMembers.value, `expected false for ${status}`).toBe(false)
      }
    })
  })

  describe('getNextAction', () => {
    it('returns Complete Payment for pending_payment', () => {
      memberData.value = { status: 'pending_payment' }
      const { getNextAction } = useMemberStatus()
      const action = getNextAction()
      expect(action.label).toBe('Complete Payment')
      expect(action.link).toBe('/member/profile#account')
    })

    it('returns Reactivate Membership for cancelled', () => {
      memberData.value = { status: 'cancelled' }
      const { getNextAction } = useMemberStatus()
      const action = getNextAction()
      expect(action.label).toBe('Reactivate Membership')
      expect(action.link).toBe('/member/profile#account')
    })

    it('returns Contact Support for suspended', () => {
      memberData.value = { status: 'suspended' }
      const { getNextAction } = useMemberStatus()
      const action = getNextAction()
      expect(action.label).toBe('Contact Support')
      expect(action.link).toBe('mailto:support@ghostguild.org')
    })

    it('returns null for active', () => {
      memberData.value = { status: 'active' }
      const { getNextAction } = useMemberStatus()
      expect(getNextAction()).toBeNull()
    })
  })

  describe('getBannerMessage', () => {
    it('returns payment message for pending_payment', () => {
      memberData.value = { status: 'pending_payment' }
      const { getBannerMessage } = useMemberStatus()
      expect(getBannerMessage()).toContain('pending payment')
    })

    it('returns suspended message for suspended', () => {
      memberData.value = { status: 'suspended' }
      const { getBannerMessage } = useMemberStatus()
      expect(getBannerMessage()).toContain('suspended')
    })

    it('returns cancelled message for cancelled', () => {
      memberData.value = { status: 'cancelled' }
      const { getBannerMessage } = useMemberStatus()
      expect(getBannerMessage()).toContain('cancelled')
    })

    it('returns null for active', () => {
      memberData.value = { status: 'active' }
      const { getBannerMessage } = useMemberStatus()
      expect(getBannerMessage()).toBeNull()
    })
  })

  describe('getRSVPMessage', () => {
    it('returns payment message for pending_payment', () => {
      memberData.value = { status: 'pending_payment' }
      const { getRSVPMessage } = useMemberStatus()
      expect(getRSVPMessage()).toContain('payment')
    })

    it('returns restriction message for suspended', () => {
      memberData.value = { status: 'suspended' }
      const { getRSVPMessage } = useMemberStatus()
      expect(getRSVPMessage()).toContain('reactivate')
    })

    it('returns restriction message for cancelled', () => {
      memberData.value = { status: 'cancelled' }
      const { getRSVPMessage } = useMemberStatus()
      expect(getRSVPMessage()).toContain('reactivate')
    })

    it('returns null for active', () => {
      memberData.value = { status: 'active' }
      const { getRSVPMessage } = useMemberStatus()
      expect(getRSVPMessage()).toBeNull()
    })
  })
})
