import { describe, it, expect } from 'vitest'
import {
  asSupabaseOrgId,
  asWorkOsOrgId,
  asSupabaseOrgIdOrNull,
  asWorkOsOrgIdOrNull,
  brandSupabaseOrgId,
  brandWorkOsOrgId,
  isSupabaseOrgId,
  isWorkOsOrgId,
  type SupabaseOrgId,
  type WorkOsOrgId
} from './org-id'

// Real fixtures pulled from the dev `organizations` table so the format checks
// exercise production-shaped values, not invented ones.
const ELEVASIS_UUID = 'f9aa5a56-8c13-4cd1-9161-8827ae7b452b'
const ELEVASIS_WORKOS = 'org_01K64D59CA5J3PJCWJFQV87PPN'
const TESTER_UUID = '1b7a6cb2-d73f-44cb-942b-1fa841085ec0'
const TESTER_WORKOS = 'org_01K4EW076HK9ND7JWPFZKGCNJF'
// A WorkOS test-org id -- still prefixed `org_`, must be treated as a WorkOS id.
const TEST_ORG_WORKOS = 'org_test_1776593934703_6gfvsb_l6nyy6'
const TEST_ORG_UUID = '2ac228f7-a0a1-49f9-920e-8a348f5253d3'

describe('org-id brands: runtime validation', () => {
  it('asSupabaseOrgId accepts real Supabase UUIDs and returns the same value', () => {
    expect(asSupabaseOrgId(ELEVASIS_UUID)).toBe(ELEVASIS_UUID)
    expect(asSupabaseOrgId(TESTER_UUID)).toBe(TESTER_UUID)
    expect(asSupabaseOrgId(TEST_ORG_UUID)).toBe(TEST_ORG_UUID)
  })

  it('asWorkOsOrgId accepts real WorkOS ids (including org_test_*) and returns the same value', () => {
    expect(asWorkOsOrgId(ELEVASIS_WORKOS)).toBe(ELEVASIS_WORKOS)
    expect(asWorkOsOrgId(TESTER_WORKOS)).toBe(TESTER_WORKOS)
    expect(asWorkOsOrgId(TEST_ORG_WORKOS)).toBe(TEST_ORG_WORKOS)
  })

  it('asSupabaseOrgId throws loudly when handed a WorkOS id (the silent footgun, surfaced)', () => {
    expect(() => asSupabaseOrgId(ELEVASIS_WORKOS)).toThrow(/Supabase organization UUID/)
    expect(() => asSupabaseOrgId(TEST_ORG_WORKOS)).toThrow(/Supabase organization UUID/)
  })

  it('asWorkOsOrgId throws loudly when handed a Supabase UUID (the reverse footgun)', () => {
    expect(() => asWorkOsOrgId(ELEVASIS_UUID)).toThrow(/WorkOS organization id/)
    expect(() => asWorkOsOrgId(TESTER_UUID)).toThrow(/WorkOS organization id/)
  })

  it('rejects empty and obviously malformed values', () => {
    expect(() => asSupabaseOrgId('')).toThrow()
    expect(() => asSupabaseOrgId('not-a-uuid')).toThrow()
    expect(() => asWorkOsOrgId('')).toThrow()
    expect(() => asWorkOsOrgId('01K64D59CA5J3PJCWJFQV87PPN')).toThrow() // missing org_ prefix
  })
})

describe('org-id brands: type guards', () => {
  it('isSupabaseOrgId is true only for UUIDs', () => {
    expect(isSupabaseOrgId(ELEVASIS_UUID)).toBe(true)
    expect(isSupabaseOrgId(ELEVASIS_WORKOS)).toBe(false)
  })

  it('isWorkOsOrgId is true only for org_ prefixed values', () => {
    expect(isWorkOsOrgId(ELEVASIS_WORKOS)).toBe(true)
    expect(isWorkOsOrgId(TEST_ORG_WORKOS)).toBe(true)
    expect(isWorkOsOrgId(ELEVASIS_UUID)).toBe(false)
  })
})

describe('org-id brands: nullable mint helpers', () => {
  it('pass null/undefined through unchanged', () => {
    expect(asSupabaseOrgIdOrNull(null)).toBeNull()
    expect(asSupabaseOrgIdOrNull(undefined)).toBeNull()
    expect(asWorkOsOrgIdOrNull(null)).toBeNull()
    expect(asWorkOsOrgIdOrNull(undefined)).toBeNull()
  })

  it('validate non-null values', () => {
    expect(asSupabaseOrgIdOrNull(ELEVASIS_UUID)).toBe(ELEVASIS_UUID)
    expect(asWorkOsOrgIdOrNull(ELEVASIS_WORKOS)).toBe(ELEVASIS_WORKOS)
    expect(() => asSupabaseOrgIdOrNull(ELEVASIS_WORKOS)).toThrow()
  })
})

describe('org-id brands: trusted-source casts', () => {
  it('brand* never throws (trusted values are not re-validated) and preserves the value', () => {
    expect(brandSupabaseOrgId(ELEVASIS_UUID)).toBe(ELEVASIS_UUID)
    expect(brandWorkOsOrgId(ELEVASIS_WORKOS)).toBe(ELEVASIS_WORKOS)
    // Unlike as*, brand* does not validate -- it is the trusted-data path.
    expect(() => brandSupabaseOrgId('anything')).not.toThrow()
    expect(() => brandWorkOsOrgId('anything')).not.toThrow()
  })

  it('brand* maps null/undefined to null', () => {
    expect(brandSupabaseOrgId(null)).toBeNull()
    expect(brandSupabaseOrgId(undefined)).toBeNull()
    expect(brandWorkOsOrgId(null)).toBeNull()
    expect(brandWorkOsOrgId(undefined)).toBeNull()
  })
})

/**
 * Compile-time enforcement. These sinks model the real consumers: a Supabase
 * `.eq('organization_id', ...)` helper (needs SupabaseOrgId) and a query-key
 * factory (needs WorkOsOrgId). The `@ts-expect-error` directives are the actual
 * assertions -- if a brand ever fails to block a swap, the directive becomes
 * "unused" and `tsc` (check-types) fails. The sinks are runtime no-ops, so this
 * block executes harmlessly under vitest; the guarantee is verified by the type
 * checker.
 */
describe('org-id brands: compile-time swap prevention', () => {
  function expectsSupabaseOrgId(_id: SupabaseOrgId): void {}
  function expectsWorkOsOrgId(_id: WorkOsOrgId): void {}

  it('accepts correctly-branded ids and keeps string compatibility', () => {
    // Positive: the right brand flows into the right sink.
    expectsSupabaseOrgId(asSupabaseOrgId(ELEVASIS_UUID))
    expectsWorkOsOrgId(asWorkOsOrgId(ELEVASIS_WORKOS))

    // A branded id is still a string everywhere a plain string is expected.
    const asString: string = asSupabaseOrgId(ELEVASIS_UUID)
    expect(asString).toBe(ELEVASIS_UUID)
  })

  it('rejects cross-brand and raw-string assignment at compile time', () => {
    // @ts-expect-error WorkOsOrgId must not be usable where a SupabaseOrgId is required.
    expectsSupabaseOrgId(asWorkOsOrgId(ELEVASIS_WORKOS))

    // @ts-expect-error SupabaseOrgId must not be usable where a WorkOsOrgId is required.
    expectsWorkOsOrgId(asSupabaseOrgId(ELEVASIS_UUID))

    // @ts-expect-error a raw string cannot reach the sink without minting through the factory.
    expectsSupabaseOrgId(ELEVASIS_UUID)

    // @ts-expect-error a raw string cannot reach the sink without minting through the factory.
    expectsWorkOsOrgId(ELEVASIS_WORKOS)

    expect(true).toBe(true)
  })
})
