import request from 'supertest'
import { createApp } from '../../app'
import {
  authHeader,
  createCompanyNotification,
  createCompanyWithEmployee,
  createRenter,
  createRenterNotification,
  signEmployeeToken,
  signRenterToken,
} from '../helpers/fixtures'

const app = createApp()

describe('Notifications API', () => {
  let companyId: string
  let employeeId: string
  let ownerToken: string
  let renterId: string
  let renterToken: string

  beforeAll(async () => {
    const { company, employee } = await createCompanyWithEmployee({ role: 'OWNER' })
    companyId = company.id
    employeeId = employee.id
    ownerToken = signEmployeeToken(employee.id, companyId, 'OWNER')

    const renter = await createRenter()
    renterId = renter.id
    renterToken = signRenterToken(renter.id)
  })

  describe('Company notifications', () => {
    it('returns unread count', async () => {
      const res = await request(app)
        .get('/api/v1/notifications/unread-count')
        .set(authHeader(ownerToken))

      expect(res.status).toBe(200)
      expect(typeof res.body.data.unread).toBe('number')
    })

    it('lists company notifications and supports unread filtering', async () => {
      const unread = await createCompanyNotification(companyId, employeeId, { title: 'Unread company notice' })
      await createCompanyNotification(companyId, employeeId, {
        title:  'Read company notice',
        readAt: new Date(),
        status: 'READ',
      })

      const res = await request(app)
        .get('/api/v1/notifications/company?unread=true')
        .set(authHeader(ownerToken))

      expect(res.status).toBe(200)
      expect(Array.isArray(res.body.data)).toBe(true)
      expect(res.body.data.some((item: any) => item.id === unread.id)).toBe(true)
      expect(res.body.data.every((item: any) => item.readAt === null)).toBe(true)
    })

    it('marks a company notification as read', async () => {
      const notification = await createCompanyNotification(companyId, employeeId)

      const res = await request(app)
        .post(`/api/v1/notifications/company/${notification.id}/read`)
        .set(authHeader(ownerToken))

      expect(res.status).toBe(200)
      expect(res.body.data.success).toBe(true)
    })

    it('updates company notification preferences', async () => {
      const payload = [
        { notificationType: 'PAYMENT_RECEIVED', channel: 'EMAIL', enabled: false },
      ]

      const patchRes = await request(app)
        .patch('/api/v1/notifications/company/preferences')
        .set(authHeader(ownerToken))
        .send(payload)

      expect(patchRes.status).toBe(200)
      expect(patchRes.body.data.success).toBe(true)

      const getRes = await request(app)
        .get('/api/v1/notifications/company/preferences')
        .set(authHeader(ownerToken))

      expect(getRes.status).toBe(200)
      expect(getRes.body.data).toEqual(
        expect.arrayContaining([
          expect.objectContaining({
            employeeId,
            notificationType: 'PAYMENT_RECEIVED',
            channel: 'EMAIL',
            enabled: false,
          }),
        ]),
      )
    })
  })

  describe('Renter notifications', () => {
    it('lists renter notifications', async () => {
      const notification = await createRenterNotification(renterId)

      const res = await request(app)
        .get('/api/v1/notifications/renter')
        .set(authHeader(renterToken))

      expect(res.status).toBe(200)
      expect(Array.isArray(res.body.data)).toBe(true)
      expect(res.body.data.some((item: any) => item.id === notification.id)).toBe(true)
    })

    it('updates renter notification preferences', async () => {
      const payload = [
        { notificationType: 'BOOKING_CONFIRMED', channel: 'PUSH', enabled: true },
      ]

      const patchRes = await request(app)
        .patch('/api/v1/notifications/renter/preferences')
        .set(authHeader(renterToken))
        .send(payload)

      expect(patchRes.status).toBe(200)
      expect(patchRes.body.data.success).toBe(true)

      const getRes = await request(app)
        .get('/api/v1/notifications/renter/preferences')
        .set(authHeader(renterToken))

      expect(getRes.status).toBe(200)
      expect(getRes.body.data).toEqual(
        expect.arrayContaining([
          expect.objectContaining({
            renterId,
            notificationType: 'BOOKING_CONFIRMED',
            channel: 'PUSH',
            enabled: true,
          }),
        ]),
      )
    })
  })
})
