import { zValidator } from '@hono/zod-validator';
import type { ZodSchema } from 'zod';
import { validationProblem } from './problem-builders';
import { zodIssuesToRecord } from './zod-issues';

type ValidationTarget = 'json' | 'query' | 'param' | 'header' | 'form';

function makeValidator<TSchema extends ZodSchema>(target: ValidationTarget, schema: TSchema) {
  return zValidator(target, schema, (result, c) => {
    if (result.success) {
      return;
    }

    const requestId = c.get('requestId') as string | undefined;
    const instance = requestId ? `/requests/${requestId}` : undefined;

    return c.json(
      validationProblem({
        detail: `Invalid ${target} data`,
        instance,
        errors: zodIssuesToRecord(result.error.issues),
      }),
      400
    );
  });
}

export const validate = {
  json<TSchema extends ZodSchema>(schema: TSchema) {
    return makeValidator('json', schema);
  },

  query<TSchema extends ZodSchema>(schema: TSchema) {
    return makeValidator('query', schema);
  },

  param<TSchema extends ZodSchema>(schema: TSchema) {
    return makeValidator('param', schema);
  },

  header<TSchema extends ZodSchema>(schema: TSchema) {
    return makeValidator('header', schema);
  },

  form<TSchema extends ZodSchema>(schema: TSchema) {
    return makeValidator('form', schema);
  },
};
