import { vi } from 'vitest'

type CookieStore = Record<string, { value: string; options?: Record<string, any> }>

declare global {
  // eslint-disable-next-line no-var
  var __testCookies__: WeakMap<any, CookieStore>
}

if (!global.__testCookies__) {
  global.__testCookies__ = new WeakMap()
}

const getCookieStore = (event: any): CookieStore => {
  if (!global.__testCookies__.has(event)) {
    global.__testCookies__.set(event, {})
  }
  return global.__testCookies__.get(event) as CookieStore
}

global.readBody = vi.fn(async (event: any) => event.__body ?? null)
global.getQuery = (event: any) => event.__query ?? {}
global.getRouterParam = (event: any, name: string) => {
  return event.context?.params?.[name] ?? null
}
global.getHeader = (event: any, name: string) => {
  const headers = event.node?.req?.headers || {}
  const key = Object.keys(headers).find(h => h.toLowerCase() === name.toLowerCase())
  return key ? headers[key] : undefined
}
global.setHeader = vi.fn((event: any, name: string, value: string) => {
  if (event.node?.res) {
    event.node.res.headers = event.node.res.headers || {}
    event.node.res.headers[name] = value
  }
})

global.setCookie = (event: any, name: string, value: string, options = {}) => {
  const store = getCookieStore(event)
  store[name] = { value, options }
}

global.getCookie = (event: any, name: string) => {
  const store = getCookieStore(event)
  return store[name]?.value ?? null
}

global.deleteCookie = (event: any, name: string) => {
  const store = getCookieStore(event)
  if (store[name]) {
    delete store[name]
  }
}

global.createError = ({ statusCode = 500, statusMessage, message }: any) => {
  const error = new Error(statusMessage || message || 'Unbekannter Fehler')
  error.name = 'H3Error'
  // @ts-ignore
  error.statusCode = statusCode
  // @ts-ignore
  error.statusMessage = statusMessage || message || 'Fehler'
  return error
}

global.useRuntimeConfig = () => ({
  encryptionKey: 'test-encryption-key',
  smtpHost: 'localhost',
  smtpPort: 1025,
  smtpUser: 'test',
  smtpPass: 'pass',
  smtp: {
    host: 'localhost',
    port: 1025,
    user: 'test',
    pass: 'pass'
  },
  membership: {
    adminEmails: ['admin@test.local']
  }
})

global.defineEventHandler = (handler: any) => handler

export const createEvent = (overrides: Record<string, any> = {}) => {
  const event = {
    context: {},
    node: {
      req: {
        headers: overrides.headers || {},
        method: overrides.method || 'GET'
      },
      res: {
        setHeader: vi.fn(),
        getHeader: vi.fn(),
        end: vi.fn(),
        statusCode: 200
      }
    },
    __body: overrides.body,
    __query: overrides.query,
    ...overrides
  }

  if (overrides.cookies) {
    const store = getCookieStore(event)
    Object.entries(overrides.cookies).forEach(([key, value]) => {
      store[key] = { value: value as string }
    })
  }

  return event
}

export const resetEventMocks = () => {
  (global.readBody as any).mockClear()
  global.__testCookies__ = new WeakMap()
}

export const expectError = async (fn: () => Promise<any>, statusCode: number) => {
  try {
    await fn()
    throw new Error('Erwarteter Fehler wurde nicht ausgelöst')
  } catch (error: any) {
    expect(error.statusCode).toBe(statusCode)
  }
}

export const mockSuccessReadBody = (payload: any) => {
  (global.readBody as any).mockResolvedValue(payload)
}

beforeEach(() => {
  resetEventMocks()
})
