import { z } from "zod";

export const MalAnimeListStatusEnum = z.enum([
	"watching",
	"completed",
	"on_hold",
	"dropped",
	"plan_to_watch",
]);
export type MalAnimeListStatus = z.infer<typeof MalAnimeListStatusEnum>;

export const MalAnimeListSortEnum = z.enum([
	"list_score",
	"list_updated_at",
	"anime_title",
	"anime_start_date",
	"anime_id",
]);
export type MalAnimeListSort = z.infer<typeof MalAnimeListSortEnum>;

const NumericQueryParamSchema = z
	.union([z.number(), z.string()])
	.transform((v) => (typeof v === "string" ? Number(v) : v));

export const MalAnimeListQuerySchema = z
	.object({
		status: MalAnimeListStatusEnum.optional(),
		sort: MalAnimeListSortEnum.optional(),
		limit: NumericQueryParamSchema.pipe(
			z.number().int().min(1).max(1000),
		).optional(),
		offset: NumericQueryParamSchema.pipe(z.number().int().min(0)).optional(),
	})
	.strict();
export type MalAnimeListQuery = z.infer<typeof MalAnimeListQuerySchema>;

export const MalAnimeEntry = z
	.object({
		id: z.number().int().positive(),
		title: z.string(),
		main_picture: z
			.object({
				medium: z.string(),
				large: z.string(),
			})
			.strict()
			.optional(),
	})
	.strict();

export const MalAnimeListEntry = z
	.object({
		status: MalAnimeListStatusEnum,
		score: z.number().int().min(0).max(10),
		num_episodes_watched: z.number().int().min(0),
		is_rewatching: z.boolean(),
		updated_at: z.iso.datetime({ offset: true }),
		start_date: z.iso.date().optional(),
		finish_date: z.iso.date().optional(),
	})
	.strict();

export const MalAnimeListResponseSchema = z
	.object({
		data: z.array(
			z
				.object({
					node: MalAnimeEntry,
					list_status: MalAnimeListEntry,
				})
				.strict(),
		),
		paging: z
			.object({
				next: z.string().optional(),
				previous: z.string().optional(),
			})
			.strict(),
	})
	.strict();
export type MalAnimeListResponse = z.infer<typeof MalAnimeListResponseSchema>;
