import { afterAll, describe, expect, it } from 'vitest'

import {
  buildOAuthCallbackReturnTo,
  parseOAuthCallbackHash,
  sanitizeAuthRedirect,
  validateOAuthUrl,
} from './oauth'

describe('oauth auth helpers', () => {
  it('sanitizes redirect paths to internal routes only', () => {
    expect(sanitizeAuthRedirect('/users')).toBe('/users')
    expect(sanitizeAuthRedirect('https://evil.example.com')).toBe('/dashboard')
    expect(sanitizeAuthRedirect('//evil.example.com')).toBe('/dashboard')
    expect(sanitizeAuthRedirect('users')).toBe('/dashboard')
  })

  it('builds oauth callback return url on current origin', () => {
    expect(buildOAuthCallbackReturnTo('/users')).toBe('http://localhost:3000/login/oauth/callback?redirect=%2Fusers')
  })

  it('parses oauth callback hash payload', () => {
    expect(parseOAuthCallbackHash('#status=success&code=abc&provider=github')).toEqual({
      status: 'success',
      code: 'abc',
      provider: 'github',
      message: '',
    })
  })

  describe('validateOAuthUrl', () => {
    const originalOrigin = window.location.origin

    afterAll(() => {
      // 恢复原始 origin
      Object.defineProperty(window, 'location', {
        value: { origin: originalOrigin },
        writable: true,
      })
    })

    it('allows same-origin URLs', () => {
      Object.defineProperty(window, 'location', {
        value: { origin: 'http://localhost:3000' },
        writable: true,
      })
      expect(validateOAuthUrl('http://localhost:3000/api/v1/auth/oauth/authorize')).toBe(true)
    })

    it('allows trusted OAuth provider origins', () => {
      expect(validateOAuthUrl('https://github.com/login/oauth/authorize')).toBe(true)
      expect(validateOAuthUrl('https://google.com/oauth/authorize')).toBe(true)
      expect(validateOAuthUrl('https://facebook.com/v1.0/oauth/authorize')).toBe(true)
    })

    it('rejects untrusted origins', () => {
      expect(validateOAuthUrl('https://evil.example.com/oauth/authorize')).toBe(false)
      expect(validateOAuthUrl('https://attacker.com/callback')).toBe(false)
    })

    it('rejects invalid URLs', () => {
      expect(validateOAuthUrl('not-a-url')).toBe(false)
      expect(validateOAuthUrl('')).toBe(false)
    })
  })
})
