export interface KbxProblemBase {
  type: string
  title: string
  detail?: string | null
  correlationId?: string | null
}

export interface KbxValidationError {
  field?: string | null
  rowKey?: string | null
  code: string
  message: string
}

export interface KbxValidationProblem extends KbxProblemBase {
  type: 'validation'
  errors: KbxValidationError[]
}

export interface KbxProblemAction { id: string; label: string }

export interface KbxBusinessProblem extends KbxProblemBase {
  type: 'business-rule'
  code: string
  actions?: KbxProblemAction[]
}

export interface KbxConflictProblem extends KbxProblemBase {
  type: 'conflict'
  code: string
  currentVersion?: number | null
}

export interface KbxPermissionProblem extends KbxProblemBase {
  type: 'permission'
  code: string
}

export interface KbxNotFoundProblem extends KbxProblemBase {
  type: 'not-found'
  code: string
}

export interface KbxIntegrationProblem extends KbxProblemBase {
  type: 'integration'
  code: string
  retryable: boolean
}

export interface KbxSystemProblem extends KbxProblemBase {
  type: 'system'
  code: string
  correlationId: string
  retryable?: boolean
}

export type KbxProblem =
  | KbxValidationProblem
  | KbxBusinessProblem
  | KbxConflictProblem
  | KbxPermissionProblem
  | KbxNotFoundProblem
  | KbxIntegrationProblem
  | KbxSystemProblem

const problemTypes = new Set<KbxProblem['type']>([
  'validation', 'business-rule', 'conflict', 'permission', 'not-found', 'integration', 'system',
])

export function isKbxProblem(value: unknown): value is KbxProblem {
  if (!value || typeof value !== 'object') return false
  const problem = value as Record<string, unknown>
  return typeof problem.type === 'string'
    && problemTypes.has(problem.type as KbxProblem['type'])
    && typeof problem.title === 'string'
}

export function kbxUnexpectedProblem(correlationId: string, detail?: string, retryable = false): KbxSystemProblem {
  return {
    type: 'system',
    code: 'UNEXPECTED_ERROR',
    title: '요청을 처리하지 못했습니다.',
    detail,
    correlationId,
    retryable,
  }
}


export function isRetryableKbxProblem(value: unknown): boolean {
  return isKbxProblem(value)
    && ((value.type === 'system' && value.retryable === true)
      || (value.type === 'integration' && value.retryable === true))
}
