import { z } from 'zod';

const createRespSchema = <T extends z.ZodTypeAny>(data: T) =>
  z.union([
    z
      .object({
        status: z.number().min(200).max(299),
        msg: z.string(),
        timestamp: z.coerce.date(),
      })
      .extend({ data: data })
      .transform((raw) =>
        Object.assign(raw, {
          type: 'success' as const,
        }),
      ),
    z
      .object({
        status: z.number(),
        msg: z.string(),
        timestamp: z.coerce.date(),
      })
      .transform((raw) =>
        Object.assign(raw, {
          type: 'error' as const,
        }),
      ),
  ]);
export type AnyRespSchema = ReturnType<typeof createRespSchema>;
export type SucceedRespOf<T extends z.infer<AnyRespSchema>> = Extract<T, { type: 'success' }>;
export type AnySucceedResp = SucceedRespOf<z.infer<AnyRespSchema>>;
export type ErrorResp = Extract<z.infer<AnyRespSchema>, { type: 'error' }>;
export const createPagedRespSchema = <T extends z.ZodTypeAny>(data: T) =>
  createRespSchema(
    z.object({
      data: data.array(),
      total: z.number(),
    }),
  );
export type SucceedPagedDataOf<T extends z.infer<AnyPagedRespSchema>> = SucceedRespOf<T>['data'];
export type AnyPagedRespSchema = ReturnType<typeof createPagedRespSchema>;
export type AnySucceedPagedResp = SucceedRespOf<z.infer<AnyRespSchema>>;
export const ordinarySchema = createRespSchema(z.literal(true));
export const idAndNameSchema = z.object({
  id: z.number(),
  name: z.string(),
});

const authSchema = idAndNameSchema.extend({
  permissions: idAndNameSchema.array(),
});
export const clubSchema = idAndNameSchema.extend({
  avatar: z.optional(z.string()),
  commit: z.string(),
});
export type Club = z.infer<typeof clubSchema>;
export const clubRespSchema = createRespSchema(clubSchema);
export const clubListRespSchema = createPagedRespSchema(clubSchema);
const userInfoSchema = idAndNameSchema.extend({
  avatar: z.optional(z.string()),
  auth: authSchema,
  club: z.optional(clubSchema),
  clubAuth: z.optional(authSchema),
});
export const userInfoRespSchema = createRespSchema(userInfoSchema);
export type UserInfo = SucceedRespOf<z.infer<typeof userInfoRespSchema>>['data'];
export const userInfoListRespSchema = createPagedRespSchema(userInfoSchema);
export const loginRespSchema = userInfoRespSchema;
export const registerRespSchema = userInfoRespSchema;
export const verifyRespSchema = createRespSchema(
  z
    .object({
      img: z.string(),
      key: z.string(),
    })
    .transform((raw) => {
      raw.img = `data:image/png;base64,${raw.img}`;
      return raw;
    }),
);
export const uploadAvatarRespSchema = createRespSchema(z.string());
