/**
 * @jest-environment node
 */
import { POST as checkIn } from '../check-in/route'
import { POST as checkOut } from '../check-out/route'
import { GET as history } from '../history/route'
import { NextRequest } from 'next/server'

// Mock dependencies
jest.mock('@clerk/nextjs/server', () => ({
    auth: jest.fn(() => Promise.resolve({ userId: 'test_user_id' })),
    currentUser: jest.fn(() => Promise.resolve({ id: 'test_user_id', emailAddresses: [{ emailAddress: 'test@example.com' }] }))
}))

jest.mock('@/lib/sync-user', () => ({
    ensureUserSynced: jest.fn()
}))

const mockDb = {
    checkIn: jest.fn(),
    checkOut: jest.fn(),
    getAttendanceHistory: jest.fn(),
    getActiveCheckIn: jest.fn(),
    getUserById: jest.fn(),
    createUser: jest.fn(),
    getClientByUserId: jest.fn(),
    createClient: jest.fn(),
    getFitnessProfileByUserId: jest.fn(),
    createFitnessProfile: jest.fn(),
}

jest.mock('@/lib/database', () => ({
    getDatabase: jest.fn(() => Promise.resolve(mockDb))
}))

describe('Attendance API', () => {
    beforeEach(() => {
        jest.clearAllMocks()
    })

    describe('POST /api/attendance/check-in', () => {
        it('should successfully check in', async () => {
            mockDb.getUserById.mockResolvedValue({ id: 'test_user_id' })
            mockDb.getActiveCheckIn.mockResolvedValue(null)
            mockDb.checkIn.mockResolvedValue({
                id: 'attendance_id',
                userId: 'test_user_id',
                checkInTime: new Date(),
                type: 'gym'
            })

            const req = new NextRequest('http://localhost/api/attendance/check-in', {
                method: 'POST',
                body: JSON.stringify({ type: 'gym', notes: 'Test check-in' })
            })

            const res = await checkIn(req)
            const data = await res.json()

            expect(res.status).toBe(200)
            expect(data.id).toBe('attendance_id')
            expect(data.userId).toBe('test_user_id')
            expect(mockDb.checkIn).toHaveBeenCalledWith('test_user_id', 'gym', 'Test check-in')
        })

        it('should fail if already checked in', async () => {
            mockDb.getUserById.mockResolvedValue({ id: 'test_user_id' })
            mockDb.getActiveCheckIn.mockResolvedValue({ id: 'existing_id' })

            const req = new NextRequest('http://localhost/api/attendance/check-in', {
                method: 'POST',
                body: JSON.stringify({ type: 'gym' })
            })

            const res = await checkIn(req)
            const text = await res.text()

            expect(res.status).toBe(400)
            expect(text).toBe('Already checked in')
        })
    })

    describe('POST /api/attendance/check-out', () => {
        it('should successfully check out', async () => {
            mockDb.getActiveCheckIn.mockResolvedValue({ id: 'attendance_id' })
            mockDb.checkOut.mockResolvedValue({
                id: 'attendance_id',
                checkOutTime: new Date()
            })

            const req = new NextRequest('http://localhost/api/attendance/check-out', {
                method: 'POST'
            })

            const res = await checkOut(req)
            const data = await res.json()

            expect(res.status).toBe(200)
            expect(data.id).toBe('attendance_id')
            expect(data.checkOutTime).toBeDefined()
            expect(mockDb.checkOut).toHaveBeenCalledWith('attendance_id')
        })

        it('should fail if not checked in', async () => {
            mockDb.getActiveCheckIn.mockResolvedValue(null)

            const req = new NextRequest('http://localhost/api/attendance/check-out', {
                method: 'POST'
            })

            const res = await checkOut(req)
            const text = await res.text()

            expect(res.status).toBe(404)
            expect(text).toBe('No active check-in found')
        })
    })

    describe('GET /api/attendance/history', () => {
        it('should return attendance history', async () => {
            const historyData = [
                { id: '1', checkInTime: new Date() },
                { id: '2', checkInTime: new Date() }
            ]
            mockDb.getUserById.mockResolvedValue({ id: 'test_user_id' })
            mockDb.getAttendanceHistory.mockResolvedValue(historyData)

            const req = new NextRequest('http://localhost/api/attendance/history')
            const res = await history(req)
            const data = await res.json()

            expect(res.status).toBe(200)
            expect(data).toEqual(JSON.parse(JSON.stringify(historyData))) // Handle date serialization
            expect(mockDb.getAttendanceHistory).toHaveBeenCalledWith('test_user_id')
        })
    })
})
