import type { VendorStatus } from './types.js'

export class VendorNotFoundError extends Error {
  override readonly name = 'VendorNotFoundError'
  readonly code = 'VENDOR_NOT_FOUND' as const
  readonly httpStatus = 404 as const

  constructor(readonly context: { vendorId?: string } = {}) {
    super(context.vendorId ? `vendor not found: ${context.vendorId}` : 'vendor not found')
  }
}

export class VendorProductNotFoundError extends Error {
  override readonly name = 'VendorProductNotFoundError'
  readonly code = 'VENDOR_PRODUCT_NOT_FOUND' as const
  readonly httpStatus = 404 as const

  constructor(readonly context: { productId?: string } = {}) {
    super(context.productId ? `vendor product not found: ${context.productId}` : 'vendor product not found')
  }
}

export class VendorAuthorizationError extends Error {
  override readonly name = 'VendorAuthorizationError'
  readonly code = 'VENDOR_FORBIDDEN' as const
  readonly httpStatus = 403 as const

  constructor() {
    super('vendor authorization failed')
  }
}

export class VendorStateError extends Error {
  override readonly name = 'VendorStateError'
  readonly code = 'VENDOR_STATE' as const
  readonly httpStatus = 409 as const

  constructor(readonly context: { vendorId: string; from: VendorStatus; to: VendorStatus }) {
    super(`vendor state transition invalid: ${context.from} -> ${context.to}`)
  }
}

export class CommissionRateError extends Error {
  override readonly name = 'CommissionRateError'
  readonly code = 'COMMISSION_RATE_INVALID' as const
  readonly httpStatus = 422 as const

  constructor(readonly context: { bps: number }) {
    super(`commission rate invalid: ${context.bps}`)
  }
}

export class VendorAlreadyExistsError extends Error {
  override readonly name = 'VendorAlreadyExistsError'
  readonly code = 'VENDOR_ALREADY_EXISTS' as const
  readonly httpStatus = 409 as const

  constructor(readonly context: { ownerUserId: string }) {
    super(`vendor already exists: ${context.ownerUserId}`)
  }
}

export function isVendorNotFoundError(e: unknown): e is VendorNotFoundError {
  return (
    typeof e === 'object' &&
    e !== null &&
    (e as { name?: unknown }).name === 'VendorNotFoundError' &&
    (e as { code?: unknown }).code === 'VENDOR_NOT_FOUND'
  )
}

export function isVendorProductNotFoundError(e: unknown): e is VendorProductNotFoundError {
  return (
    typeof e === 'object' &&
    e !== null &&
    (e as { name?: unknown }).name === 'VendorProductNotFoundError' &&
    (e as { code?: unknown }).code === 'VENDOR_PRODUCT_NOT_FOUND'
  )
}

export function isVendorAuthorizationError(e: unknown): e is VendorAuthorizationError {
  return (
    typeof e === 'object' &&
    e !== null &&
    (e as { name?: unknown }).name === 'VendorAuthorizationError' &&
    (e as { code?: unknown }).code === 'VENDOR_FORBIDDEN'
  )
}

export function isVendorStateError(e: unknown): e is VendorStateError {
  return (
    typeof e === 'object' &&
    e !== null &&
    (e as { name?: unknown }).name === 'VendorStateError' &&
    (e as { code?: unknown }).code === 'VENDOR_STATE'
  )
}

export function isCommissionRateError(e: unknown): e is CommissionRateError {
  return (
    typeof e === 'object' &&
    e !== null &&
    (e as { name?: unknown }).name === 'CommissionRateError' &&
    (e as { code?: unknown }).code === 'COMMISSION_RATE_INVALID'
  )
}

export function isVendorAlreadyExistsError(e: unknown): e is VendorAlreadyExistsError {
  return (
    typeof e === 'object' &&
    e !== null &&
    (e as { name?: unknown }).name === 'VendorAlreadyExistsError' &&
    (e as { code?: unknown }).code === 'VENDOR_ALREADY_EXISTS'
  )
}

export class SplitIntegrityError extends Error {
  override readonly name = 'SplitIntegrityError'
  readonly code = 'SPLIT_INTEGRITY' as const
  readonly httpStatus = 422 as const

  constructor(readonly context: { reason: string; vendorId?: string }) {
    super(`computeVendorSplits: ${context.reason}`)
  }
}

export function isSplitIntegrityError(e: unknown): e is SplitIntegrityError {
  return (
    typeof e === 'object' &&
    e !== null &&
    (e as { name?: unknown }).name === 'SplitIntegrityError' &&
    (e as { code?: unknown }).code === 'SPLIT_INTEGRITY'
  )
}
