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

export const UserInit = User.omit({
  _id: true,
});
export type UserInit = z.infer<typeof UserInit>;

export const UserFilter = User.pick({
  name: true,
  username: true,
  email: true,
})
  .merge(QueryPagination)
  .partial();
export type UserFilter = z.infer<typeof UserFilter>;

export const UserQuery = UserFilter;

export const CreateUserDto = User.pick({
  name: true,
  username: true,
  email: true,
}).extend({
  password: z.string(),
});
export type CreateUserDto = z.infer<typeof CreateUserDto>;

export const UpdateProfileDto = User.pick({
  name: true,
  email: true,
}).partial();
export type UpdateProfileDto = z.infer<typeof UpdateProfileDto>;

export const UpdatePasswordDto = z.object({ password: z.string() });
export type UpdatePasswordDto = z.infer<typeof UpdatePasswordDto>;

export const ActivateUserDto = User.pick({
  activationCode: true,
});
export type ActivateUserDto = z.infer<typeof ActivateUserDto>;

export const RemoveUserResult = z.object({
  removedUser: z.string(),
  removedPrivileges: z.number().int(),
});
export type RemoveUserResult = z.infer<typeof RemoveUserResult>;

export const userContract = buildContract((c) =>
  c
    .prefix('users')
    .parse((p) =>
      p.error.text(500).error.text(400).error.text(401).error.text(403),
    )
    .endpoints({
      listUser: (e) =>
        e
          .method('GET')
          .prepare((p) => p.query(UserQuery))
          .parse(
            (p) => p.success.object(200, z.array(z.object({}).passthrough())), // TODO: set zod schema
          ),
      registerUser: (e) =>
        e
          .method('POST')
          .prepare((p) => p.body.json(CreateUserDto))
          .parse((p) => p.success.object(201, User)),
      updateProfile: (e) =>
        e
          .method('PATCH')
          .path(':username/profile')
          .prepare((p) => p.param('username').body.json(UpdateProfileDto))
          .parse((p) => p.success.object(200, User)),
      updatePassword: (e) =>
        e
          .method('PUT')
          .path(':username/password')
          .prepare((p) => p.param('username').body.json(UpdatePasswordDto))
          .parse((p) => p.success.object(200, User)),
      activateUser: (e) =>
        e
          .method('GET')
          .path(':username/activation')
          .prepare((p) => p.param('username').query(ActivateUserDto))
          .parse((p) => p.success.text(200).error.text(402)),
      removeUser: (e) =>
        e
          .method('DELETE')
          .path(':username')
          .prepare((p) => p.param('username'))
          .parse((p) => p.success.object(200, RemoveUserResult)),
    }),
);
