import { z } from 'zod'

export const problemTypeSchema = z.enum([
  'validation', 'business-rule', 'conflict', 'permission', 'not-found', 'integration', 'system',
])

const validationErrorSchema = z.object({
  field: z.string().nullable().optional(),
  rowKey: z.string().nullable().optional(),
  code: z.string().min(1),
  message: z.string().min(1),
}).strict()

const problemActionSchema = z.object({ id: z.string().min(1), label: z.string().min(1) }).strict()

export interface ProblemDetails {
  type?: string
  title: string
  status: number
  detail?: string
  traceId?: string
  correlationId?: string
  code?: string
  retryable?: boolean
  currentVersion?: number | null
  actions?: Array<{ id: string; label: string }>
  errors?: Record<string, string[]>
  validationErrors?: Array<{ field?: string | null; rowKey?: string | null; code: string; message: string }>
}

export const problemDetailsSchema = z.object({
  type: z.string().optional(),
  title: z.string().min(1),
  status: z.number().int().min(400).max(599),
  detail: z.string().optional(),
  traceId: z.string().optional(),
  correlationId: z.string().optional(),
  code: z.string().min(1).optional(),
  retryable: z.boolean().optional(),
  currentVersion: z.number().int().min(1).nullable().optional(),
  actions: z.array(problemActionSchema).optional(),
  errors: z.record(z.string(), z.array(z.string())).optional(),
  validationErrors: z.array(validationErrorSchema).optional(),
}).strict()

export type ProblemInteraction = 'UNAUTHORIZED' | 'FORBIDDEN' | 'CONFLICT' | 'VALIDATION' | 'RETRYABLE' | 'ERROR'

export function resolveProblemInteraction(problem: Pick<ProblemDetails, 'status' | 'type' | 'retryable'>): ProblemInteraction {
  if (problem.status === 401) return 'UNAUTHORIZED'
  if (problem.status === 403 || problem.type === 'permission') return 'FORBIDDEN'
  if (problem.status === 409 || problem.type === 'conflict') return 'CONFLICT'
  if (problem.status === 422 || problem.type === 'validation') return 'VALIDATION'
  if (problem.retryable === true || problem.type === 'integration' || problem.status === 429 || problem.status === 503) return 'RETRYABLE'
  return 'ERROR'
}

export class ApiProblem extends Error {
  constructor(public readonly problem: ProblemDetails) {
    super(problem.title)
  }

  get status(): number { return this.problem.status }
}
