import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'

const nextServer = vi.hoisted(() => {
  const redirect = vi.fn((url: URL) => ({ kind: 'redirect', url: url.toString() }))
  const next = vi.fn(() => ({ kind: 'next' }))
  const MockNextResponse = vi.fn((body?: string, init?: { status?: number }) => ({
    kind: 'response',
    body,
    status: init?.status,
  })) as any
  MockNextResponse.redirect = redirect
  MockNextResponse.next = next
  return { redirect, next, MockNextResponse }
})

vi.mock('next/server', () => ({
  NextResponse: nextServer.MockNextResponse,
}))

function cloneableUrl(input: string): URL {
  const url = new URL(input)
  ;(url as URL & { clone: () => URL }).clone = () => cloneableUrl(url.toString())
  return url
}

function request(input: string, options: { token?: string; headers?: Record<string, string> } = {}) {
  const headers = new Map(Object.entries(options.headers ?? {}).map(([key, value]) => [key.toLowerCase(), value]))
  return {
    nextUrl: cloneableUrl(input),
    cookies: {
      get: vi.fn((name: string) => (name === 'employee_session' && options.token ? { value: options.token } : undefined)),
    },
    headers: {
      get: vi.fn((name: string) => headers.get(name.toLowerCase()) ?? null),
      has: vi.fn((name: string) => headers.has(name.toLowerCase())),
    },
  }
}

async function loadMiddleware(websiteUrl = 'https://market.example.com') {
  vi.resetModules()
  process.env.NEXT_PUBLIC_WEBSITE_URL = websiteUrl
  return import('./middleware')
}

beforeEach(() => {
  nextServer.redirect.mockClear()
  nextServer.next.mockClear()
})

afterEach(() => {
  delete process.env.NEXT_PUBLIC_WEBSITE_URL
  vi.resetModules()
})

describe('dashboard middleware', () => {
  it('redirects duplicate dashboard prefixes to the clean dashboard URL', async () => {
    const { default: middleware } = await loadMiddleware()

    const response = middleware(request('https://workspace.example.com/dashboard/dashboard?x=1') as never)

    expect(response).toEqual({ kind: 'redirect', url: 'https://workspace.example.com/dashboard?x=1' })
  })

  it('rejects middleware subrequest headers at the app layer', async () => {
    const { default: middleware } = await loadMiddleware()

    const response = middleware(request('https://workspace.example.com/dashboard', {
      headers: { 'x-middleware-subrequest': 'middleware:middleware' },
    }) as never)

    expect(response).toEqual({ kind: 'response', body: 'Unsupported internal request header', status: 400 })
  })

  it('redirects unauthenticated protected internal-host requests to dashboard sign-in on the resolved origin', async () => {
    const { default: middleware } = await loadMiddleware('https://rentaldrivego.example')

    const response = middleware(request('http://dashboard:3001/dashboard/team') as never)

    expect(response).toEqual({ kind: 'redirect', url: 'https://rentaldrivego.example/dashboard/sign-in?redirect=%2Fdashboard%2Fteam' })
  })

  it('redirects unprefixed internal app paths with a public dashboard return path', async () => {
    const { default: middleware } = await loadMiddleware('https://rentaldrivego.example')

    const response = middleware(request('http://dashboard:3001/reservations') as never)

    expect(response).toEqual({ kind: 'redirect', url: 'https://rentaldrivego.example/dashboard/sign-in?redirect=%2Fdashboard%2Freservations' })
  })

  it('uses trusted forwarded host/proto when building the dashboard sign-in redirect', async () => {
    const { default: middleware } = await loadMiddleware('https://market.example.com')

    const response = middleware(request('http://dashboard:3001/dashboard/billing', {
      headers: {
        'x-forwarded-host': 'workspace.customer.example',
        'x-forwarded-proto': 'https',
      },
    }) as never)

    expect(response).toEqual({ kind: 'redirect', url: 'https://workspace.customer.example/dashboard/sign-in?redirect=%2Fdashboard%2Fbilling' })
  })

  it('ignores internal forwarded hosts when building the dashboard sign-in redirect', async () => {
    const { default: middleware } = await loadMiddleware('https://market.example.com')

    const response = middleware(request('http://dashboard:3001/dashboard/fleet', {
      headers: {
        'x-forwarded-host': 'api:4000',
        'x-forwarded-proto': 'https',
      },
    }) as never)

    expect(response).toEqual({ kind: 'redirect', url: 'https://market.example.com/dashboard/sign-in?redirect=%2Fdashboard%2Ffleet' })
  })

  it('redirects signed-in users away from the sign-in page', async () => {
    const { default: middleware } = await loadMiddleware()

    const response = middleware(request('https://workspace.example.com/dashboard/sign-in?redirect=/dashboard/fleet', { token: 'employee-token' }) as never)

    expect(response).toEqual({ kind: 'redirect', url: 'https://workspace.example.com/dashboard' })
  })

  it('allows public dashboard auth pages without a token', async () => {
    const { default: middleware } = await loadMiddleware()

    const response = middleware(request('https://workspace.example.com/dashboard/forgot-password') as never)

    expect(response).toEqual({ kind: 'next' })
    expect(nextServer.next).toHaveBeenCalledTimes(1)
  })

  it('allows dashboard API requests through so auth endpoints can set and read cookies', async () => {
    const { default: middleware } = await loadMiddleware()

    const response = middleware(request('https://workspace.example.com/dashboard/api/v1/auth/employee/login') as never)

    expect(response).toEqual({ kind: 'next' })
    expect(nextServer.redirect).not.toHaveBeenCalled()
  })
})
