import { buildContract } from '@jig-software/trest-core';
import { z } from 'zod';
import { MfaSession } from '../schemas';

export const RejectMfaDto = MfaSession.pick({
  sessionId: true,
});
export type RejectMfaDto = z.infer<typeof RejectMfaDto>;

export const RejectMfaResultDto = z.object({
  rejected: z.number().int(),
});
export type RejectMfaResultDto = z.infer<typeof RejectMfaResultDto>;

export const ConfirmMfaDto = MfaSession.pick({
  otp: true,
  sessionId: true,
}).extend({
  username: z.string(),
  returnToken: z.boolean(),
});
export type ConfirmMfaDto = z.infer<typeof ConfirmMfaDto>;

export const ConfirmMfaResultDto = z
  .object({
    token: z.string(),
  })
  .or(
    z.object({
      ok: z.literal(1),
    }),
  );
export type ConfirmMfaResultDto = z.infer<typeof ConfirmMfaResultDto>;

export const CreateMfaRequestDto = MfaSession.pick({
  token: true,
  otp: true,
  userAgent: true,
  requestedBy: true,
  sessionId: true,
  expiredAt: true,
});
export type CreateMfaRequestDto = z.infer<typeof CreateMfaRequestDto>;

export const mfaContract = buildContract((c) =>
  c
    .prefix('auth')
    .parse((p) =>
      p.error.text(500).error.text(400).error.text(401).error.text(403),
    )
    .endpoints({
      getMFA: (e) =>
        e
          .method('GET')
          .path(':username')
          .prepare((p) => p.param('username'))
          .parse((p) => p.success.object(200, z.array(MfaSession))),
      rejectMfa: (e) =>
        e
          .method('DELETE')
          .path(':username')
          .prepare((p) => p.param('username').body.json(RejectMfaDto))
          .parse((p) => p.success.object(200, RejectMfaResultDto)),
      confirmMfa: (e) =>
        e
          .method('POST')
          .prepare((p) => p.body.json(ConfirmMfaDto))
          .parse((p) =>
            p.success.object(200, ConfirmMfaResultDto).error.text(402),
          ),
    }),
);
