import { z } from 'zod';

function createResponseSchema<T extends z.ZodTypeAny>(data: T) {
  return z.union([
    z
      .object({
        code: z.number().min(200).max(299),
        msg: z.string(),
        time: z.coerce.date(),
      })
      .extend({ data: data })
      .transform((raw) =>
        Object.assign(raw, {
          type: 'success',
        } as const),
      ),
    z
      .object({
        code: z.number(),
        msg: z.string(),
        time: z.coerce.date(),
      })
      .transform((raw) =>
        Object.assign(raw, {
          type: 'error',
        } as const),
      ),
  ]);
}

export type SucceedResponseOf<T> = Extract<T, { type: 'success' }>;
export type ErrorResponseOf<T> = Exclude<SucceedResponseOf<T>, T>;
export const ordinarySchema = createResponseSchema(z.literal(true));
export const loginResponseSchema = ordinarySchema;
export const registerResponseSchema = ordinarySchema;
export const idAndNameSchema = z.object({
  id: z.number(),
  name: z.string(),
});

const _authSchema = idAndNameSchema.extend({
  permissions: idAndNameSchema.array(),
});
export const userInfoResponseSchema = createResponseSchema(
  idAndNameSchema.extend({
    avatar: z.nullable(z.string()),
    auth: _authSchema,
    club: z.nullable(
      idAndNameSchema.extend({
        commit: z.string(),
        auth: _authSchema,
      }),
    ),
  }),
);
export type SucceedUserInfoResponse = SucceedResponseOf<z.infer<typeof userInfoResponseSchema>>;
export type UserInfo = SucceedUserInfoResponse['data'];
export const verifyResponseSchema = createResponseSchema(
  z
    .object({
      img: z.string(),
      key: z.string(),
    })
    .transform((raw) => {
      raw.img = `data:image/png;base64,${raw.img}`;
      return raw;
    }),
);
