/**
 * test/origin.test.ts — TDD for src/http/origin.ts (T7)
 *
 * Covers ARCHITECTURE §3.3 and TECH_DOC §7 (CSWSH defence):
 *   - whitelist hit → allow
 *   - wrong hostname → deny
 *   - wrong port → deny
 *   - undefined Origin (non-browser client) → deny
 *   - evil.com → deny
 */

import { describe, it, expect } from 'vitest'
import { isOriginAllowed } from '../src/http/origin.js'

const ALLOWED: readonly string[] = [
  'http://localhost:3000',
  'http://192.168.1.42:3000',
  'http://my-host.local:3000',
]

describe('isOriginAllowed', () => {
  // ── whitelist hits ────────────────────────────────────────────────
  it('allows an exact localhost origin', () => {
    expect(isOriginAllowed('http://localhost:3000', ALLOWED)).toBe(true)
  })

  it('allows an exact LAN IP origin', () => {
    expect(isOriginAllowed('http://192.168.1.42:3000', ALLOWED)).toBe(true)
  })

  it('allows an exact hostname.local origin', () => {
    expect(isOriginAllowed('http://my-host.local:3000', ALLOWED)).toBe(true)
  })

  // ── hostname mismatch ─────────────────────────────────────────────
  it('rejects when the hostname does not match (evil.com)', () => {
    expect(isOriginAllowed('http://evil.com:3000', ALLOWED)).toBe(false)
  })

  it('rejects a subdomain of an allowed hostname', () => {
    expect(isOriginAllowed('http://sub.localhost:3000', ALLOWED)).toBe(false)
  })

  it('rejects a hostname that merely contains an allowed hostname', () => {
    // "evillocalhost:3000" should NOT match "localhost:3000"
    expect(isOriginAllowed('http://evillocalhost:3000', ALLOWED)).toBe(false)
  })

  // ── port mismatch ─────────────────────────────────────────────────
  it('rejects when the port does not match (correct host, wrong port)', () => {
    expect(isOriginAllowed('http://localhost:9999', ALLOWED)).toBe(false)
  })

  it('rejects when port is absent but allowed origin has a port', () => {
    // Browser sends Origin without port only when it is the default (80/443).
    // Our server runs on 3000, so no-port origins must not sneak in.
    expect(isOriginAllowed('http://localhost', ALLOWED)).toBe(false)
  })

  // ── undefined Origin (non-browser clients: curl, scripts) ─────────
  it('rejects undefined Origin by default', () => {
    expect(isOriginAllowed(undefined, ALLOWED)).toBe(false)
  })

  // ── empty / malformed origins ─────────────────────────────────────
  it('rejects an empty string origin', () => {
    expect(isOriginAllowed('', ALLOWED)).toBe(false)
  })

  it('rejects a completely different scheme (https vs http in allowed)', () => {
    // Allowed list uses http://; https:// should not silently match.
    expect(isOriginAllowed('https://localhost:3000', ALLOWED)).toBe(false)
  })

  it('rejects when allowed list is empty', () => {
    expect(isOriginAllowed('http://localhost:3000', [])).toBe(false)
  })
})
