import { describe, expect, it } from 'vitest'
import {
  CreateOrganizationSchema,
  ListOrganizationsQuerySchema,
  UpdateOrganizationAuthConfigSchema,
  UpdateOrganizationSchema
} from '../api-schemas'

// ---------------------------------------------------------------------------
// CreateOrganizationSchema
// ---------------------------------------------------------------------------

describe('CreateOrganizationSchema', () => {
  it('accepts a minimal valid payload (name only)', () => {
    expect(CreateOrganizationSchema.safeParse({ name: 'Acme Corp' }).success).toBe(true)
  })

  it('accepts name at minimum length boundary (2 chars)', () => {
    expect(CreateOrganizationSchema.safeParse({ name: 'AB' }).success).toBe(true)
  })

  it('accepts name at maximum length boundary (100 chars)', () => {
    expect(CreateOrganizationSchema.safeParse({ name: 'A'.repeat(100) }).success).toBe(true)
  })

  it('rejects name shorter than 2 characters', () => {
    expect(CreateOrganizationSchema.safeParse({ name: 'A' }).success).toBe(false)
    expect(CreateOrganizationSchema.safeParse({ name: '' }).success).toBe(false)
  })

  it('rejects name longer than 100 characters', () => {
    expect(CreateOrganizationSchema.safeParse({ name: 'A'.repeat(101) }).success).toBe(false)
  })

  it('accepts names with letters, numbers, spaces, hyphens, and underscores', () => {
    expect(CreateOrganizationSchema.safeParse({ name: 'My Org-123_Test' }).success).toBe(true)
  })

  it('rejects names with disallowed characters (special symbols)', () => {
    expect(CreateOrganizationSchema.safeParse({ name: 'Acme@Corp' }).success).toBe(false)
    expect(CreateOrganizationSchema.safeParse({ name: 'Acme.Corp' }).success).toBe(false)
    expect(CreateOrganizationSchema.safeParse({ name: 'Acme/Corp' }).success).toBe(false)
    expect(CreateOrganizationSchema.safeParse({ name: 'Acme+Corp' }).success).toBe(false)
  })

  it('accepts optional domainData array with valid entries', () => {
    const result = CreateOrganizationSchema.safeParse({
      name: 'Acme Corp',
      domainData: [{ domain: 'acme.com', state: 'verified' }]
    })
    expect(result.success).toBe(true)
  })

  it('accepts domainData up to 10 entries', () => {
    const domains = Array.from({ length: 10 }, (_, i) => ({ domain: `domain${i}.com` }))
    expect(CreateOrganizationSchema.safeParse({ name: 'Acme Corp', domainData: domains }).success).toBe(true)
  })

  it('rejects domainData with more than 10 entries', () => {
    const domains = Array.from({ length: 11 }, (_, i) => ({ domain: `domain${i}.com` }))
    expect(CreateOrganizationSchema.safeParse({ name: 'Acme Corp', domainData: domains }).success).toBe(false)
  })

  it('accepts optional metadata as a record under 10KB', () => {
    const result = CreateOrganizationSchema.safeParse({
      name: 'Acme Corp',
      metadata: { plan: 'pro', region: 'us-west' }
    })
    expect(result.success).toBe(true)
  })

  it('rejects metadata exceeding 10KB (10240 bytes)', () => {
    // Build a metadata object whose JSON representation exceeds 10240 bytes
    const largeValue = 'x'.repeat(10241)
    const result = CreateOrganizationSchema.safeParse({
      name: 'Acme Corp',
      metadata: { big: largeValue }
    })
    expect(result.success).toBe(false)
  })

  it('rejects unknown top-level fields (.strict() mode)', () => {
    expect(CreateOrganizationSchema.safeParse({ name: 'Acme Corp', unknownField: 'value' }).success).toBe(false)
  })

  it('rejects missing name field', () => {
    expect(CreateOrganizationSchema.safeParse({}).success).toBe(false)
  })
})

// ---------------------------------------------------------------------------
// UpdateOrganizationSchema
// ---------------------------------------------------------------------------

describe('UpdateOrganizationSchema', () => {
  it('rejects an empty object (at least one field required)', () => {
    // UpdateOrganizationSchema is CreateOrganizationSchema.partial().strict().refine(...)
    // The .refine() enforces the documented "at least one field" convention
    // (see .claude/rules/core-package.md → "api-schemas.ts Pattern")
    const result = UpdateOrganizationSchema.safeParse({})
    expect(result.success).toBe(false)
    if (!result.success) {
      expect(result.error.issues[0].message).toMatch(/at least one field/i)
    }
  })

  it('accepts updating only name', () => {
    expect(UpdateOrganizationSchema.safeParse({ name: 'New Name' }).success).toBe(true)
  })

  it('accepts updating only domainData', () => {
    expect(UpdateOrganizationSchema.safeParse({ domainData: [{ domain: 'newdomain.com' }] }).success).toBe(true)
  })

  it('accepts updating only metadata', () => {
    expect(UpdateOrganizationSchema.safeParse({ metadata: { key: 'value' } }).success).toBe(true)
  })

  it('applies same name validation as CreateOrganizationSchema when name is provided', () => {
    // Too short
    expect(UpdateOrganizationSchema.safeParse({ name: 'A' }).success).toBe(false)
    // Too long
    expect(UpdateOrganizationSchema.safeParse({ name: 'A'.repeat(101) }).success).toBe(false)
    // Invalid charset
    expect(UpdateOrganizationSchema.safeParse({ name: 'Bad@Name' }).success).toBe(false)
    // Valid
    expect(UpdateOrganizationSchema.safeParse({ name: 'Good Name-123' }).success).toBe(true)
  })

  it('applies same domainData max-10 validation when provided', () => {
    const tooMany = Array.from({ length: 11 }, (_, i) => ({ domain: `d${i}.com` }))
    expect(UpdateOrganizationSchema.safeParse({ domainData: tooMany }).success).toBe(false)
  })

  it('applies same metadata 10KB cap validation when provided', () => {
    const largeValue = 'x'.repeat(10241)
    expect(UpdateOrganizationSchema.safeParse({ metadata: { big: largeValue } }).success).toBe(false)
  })

  it('rejects unknown top-level fields (.strict() mode)', () => {
    expect(UpdateOrganizationSchema.safeParse({ name: 'Valid Name', unknownField: 'bad' }).success).toBe(false)
  })
})

// ---------------------------------------------------------------------------
// UpdateOrganizationAuthConfigSchema
// ---------------------------------------------------------------------------

describe('UpdateOrganizationAuthConfigSchema', () => {
  it('accepts an HTTPS app origin', () => {
    expect(UpdateOrganizationAuthConfigSchema.safeParse({ appOrigin: 'https://app.example.com' }).success).toBe(true)
  })

  it('rejects app origins with paths, query strings, or hashes', () => {
    expect(UpdateOrganizationAuthConfigSchema.safeParse({ appOrigin: 'https://app.example.com/login' }).success).toBe(
      false
    )
    expect(UpdateOrganizationAuthConfigSchema.safeParse({ appOrigin: 'https://app.example.com?x=1' }).success).toBe(
      false
    )
    expect(UpdateOrganizationAuthConfigSchema.safeParse({ appOrigin: 'https://app.example.com#hash' }).success).toBe(
      false
    )
  })

  it('rejects unknown config fields', () => {
    expect(
      UpdateOrganizationAuthConfigSchema.safeParse({
        appOrigin: 'https://app.example.com',
        other: true
      }).success
    ).toBe(false)
  })
})

// ---------------------------------------------------------------------------
// ListOrganizationsQuerySchema
// ---------------------------------------------------------------------------

describe('ListOrganizationsQuerySchema', () => {
  it('accepts an empty query and applies default limit of 20', () => {
    const result = ListOrganizationsQuerySchema.safeParse({})
    expect(result.success).toBe(true)
    if (result.success) {
      expect(result.data.limit).toBe(20)
    }
  })

  it('coerces limit from string "50" to number 50', () => {
    const result = ListOrganizationsQuerySchema.safeParse({ limit: '50' })
    expect(result.success).toBe(true)
    if (result.success) expect(result.data.limit).toBe(50)
  })

  it('accepts limit at upper boundary (100)', () => {
    const result = ListOrganizationsQuerySchema.safeParse({ limit: '100' })
    expect(result.success).toBe(true)
    if (result.success) expect(result.data.limit).toBe(100)
  })

  it('accepts limit at lower boundary (1)', () => {
    const result = ListOrganizationsQuerySchema.safeParse({ limit: '1' })
    expect(result.success).toBe(true)
    if (result.success) expect(result.data.limit).toBe(1)
  })

  it('rejects limit of 101 (above max 100)', () => {
    expect(ListOrganizationsQuerySchema.safeParse({ limit: '101' }).success).toBe(false)
  })

  it('rejects limit of 0 (below min 1)', () => {
    expect(ListOrganizationsQuerySchema.safeParse({ limit: '0' }).success).toBe(false)
  })

  it('accepts optional before cursor string', () => {
    const result = ListOrganizationsQuerySchema.safeParse({ before: 'cursor_abc123' })
    expect(result.success).toBe(true)
    if (result.success) expect(result.data.before).toBe('cursor_abc123')
  })

  it('accepts optional after cursor string', () => {
    const result = ListOrganizationsQuerySchema.safeParse({ after: 'cursor_xyz789' })
    expect(result.success).toBe(true)
    if (result.success) expect(result.data.after).toBe('cursor_xyz789')
  })

  it('accepts both before and after cursors together', () => {
    expect(ListOrganizationsQuerySchema.safeParse({ before: 'a', after: 'b' }).success).toBe(true)
  })
})
