import {
    useNuxtDropboxSync,
    getCredentialsFromCookies,
    createNuxtApiHandlers,
} from '../nuxt'
import { createDropboxSyncClient } from '../../core/client'
import type { H3Event } from 'h3'

// Mock dependencies
jest.mock('../../core/client')

// Manual mocks for Nuxt modules
jest.mock('nuxt/app', () => ({
    useRuntimeConfig: jest.fn().mockReturnValue({
        public: {
            dropboxAppKey: 'test-app-key',
            appUrl: 'https://example.com',
        },
        dropboxAppSecret: 'test-app-secret',
        dropboxRedirectUri: 'https://example.com/api/dropbox/auth/callback',
    }),
    useCookie: jest.fn().mockImplementation((name) => {
        if (name === 'dropbox_access_token') {
            return { value: 'test-access-token' }
        }
        if (name === 'dropbox_refresh_token') {
            return { value: 'test-refresh-token' }
        }
        return { value: null }
    }),
}))

// Mock H3 utilities
const mockGetCookie = jest.fn()
const mockSetCookie = jest.fn()
const mockDeleteCookie = jest.fn()
const mockGetQuery = jest.fn()
const mockSendRedirect = jest.fn()

jest.mock('h3', () => ({
    getCookie: mockGetCookie,
    setCookie: mockSetCookie,
    deleteCookie: mockDeleteCookie,
    getQuery: mockGetQuery,
    sendRedirect: mockSendRedirect,
}))

describe('Nuxt.js adapter', () => {
    beforeEach(() => {
        jest.clearAllMocks()

        // Define process.client as a property for client/server detection
        if (!('client' in process)) {
            Object.defineProperty(process, 'client', {
                value: false,
                writable: true,
                configurable: true,
            })
        } else {
            ;(process as any).client = false
        }
    })

    describe('useNuxtDropboxSync', () => {
        it('should create a Dropbox sync client with config values', () => {
            ;(createDropboxSyncClient as jest.Mock).mockReturnValue({
                mock: 'client',
            })

            const result = useNuxtDropboxSync()

            expect(createDropboxSyncClient).toHaveBeenCalledWith({
                clientId: 'test-app-key',
                clientSecret: 'test-app-secret',
            })
            expect(result).toEqual({ mock: 'client' })
        })

        it('should add cookie values on client-side', () => {
            // Set as client-side
            ;(process as any).client = true

            ;(createDropboxSyncClient as jest.Mock).mockReturnValue({
                mock: 'client',
            })

            const result = useNuxtDropboxSync()

            expect(createDropboxSyncClient).toHaveBeenCalledWith(
                expect.objectContaining({
                    clientId: 'test-app-key',
                    clientSecret: 'test-app-secret',
                    accessToken: 'test-access-token',
                    refreshToken: 'test-refresh-token',
                })
            )
        })
    })

    describe('getCredentialsFromCookies', () => {
        it('should get credentials from H3 event', () => {
            const mockEvent = {} as H3Event

            // Set up mock implementation
            mockGetCookie.mockImplementation((event: any, name: string) => {
                if (name === 'dropbox_access_token') return 'h3-access-token'
                if (name === 'dropbox_refresh_token') return 'h3-refresh-token'
                return null
            })

            const credentials = getCredentialsFromCookies(mockEvent)

            expect(mockGetCookie).toHaveBeenCalledWith(
                mockEvent,
                'dropbox_access_token'
            )
            expect(mockGetCookie).toHaveBeenCalledWith(
                mockEvent,
                'dropbox_refresh_token'
            )
            expect(credentials).toEqual({
                clientId: 'test-app-key',
                clientSecret: 'test-app-secret',
                accessToken: 'h3-access-token',
                refreshToken: 'h3-refresh-token',
            })
        })
    })

    describe('createNuxtApiHandlers', () => {
        const mockEvent = {} as H3Event

        beforeEach(() => {
            // Reset H3 mocks for each test
            mockGetCookie.mockReset()
            mockSetCookie.mockReset()
            mockDeleteCookie.mockReset()
            mockGetQuery.mockReset()
            mockSendRedirect.mockReset()
        })

        it('should create Nuxt API handlers with necessary methods', () => {
            const handlers = createNuxtApiHandlers()

            expect(handlers).toHaveProperty('status')
            expect(handlers).toHaveProperty('oauthStart')
            expect(handlers).toHaveProperty('oauthCallback')
            expect(handlers).toHaveProperty('logout')
        })

        it('should check connection status', async () => {
            mockGetCookie.mockReturnValue('h3-access-token')

            const handlers = createNuxtApiHandlers()
            const result = await handlers.status(mockEvent)

            expect(mockGetCookie).toHaveBeenCalledWith(
                mockEvent,
                'dropbox_access_token'
            )
            expect(result).toEqual({ connected: true })
        })

        it('should handle OAuth start', async () => {
            ;(createDropboxSyncClient as jest.Mock).mockReturnValue({
                auth: {
                    getAuthUrl: jest
                        .fn()
                        .mockResolvedValue('https://dropbox.com/oauth'),
                },
            })

            mockSendRedirect.mockImplementation(() => ({ redirected: true }))

            const handlers = createNuxtApiHandlers()
            await handlers.oauthStart(mockEvent)

            expect(createDropboxSyncClient).toHaveBeenCalled()
            expect(mockSendRedirect).toHaveBeenCalledWith(
                mockEvent,
                'https://dropbox.com/oauth'
            )
        })
    })
})
