import { defineCollection, reference } from 'astro:content';
import type { SchemaContext } from 'astro:content';
import { glob } from 'astro/loaders';
import { z } from 'astro/zod';

const linkSchema = z.object({
  label: z.string(),
  url: z.string(),
  download: z.boolean().optional(),
});

const thumbnailSchema = ({ image }: SchemaContext) =>
  z.object({
    src: image(),
    alt: z.string(),
  });

const mediaSchema = ({ image }: SchemaContext) =>
  z
    .object({
      type: z.enum(['image', 'video', 'diagram']),
      src: image().optional(),
      poster: image().optional(),
      mp4: z.string().optional(),
      webm: z.string().optional(),
      alt: z.string().optional(),
      decorative: z.boolean().optional(),
      caption: z.string().optional(),
      transcript: z.string().optional(),
    })
    .refine((item) => item.decorative || (Boolean(item.alt) && Boolean(item.caption)), {
      message: 'Meaningful media needs both alt text and a caption.',
    });

const posts = defineCollection({
  loader: glob({ pattern: '**/*.md', base: './src/content/posts' }),
  schema: ({ image }) =>
    z.object({
      title: z.string(),
      description: z.string().max(160),
      date: z.coerce.date(),
      updated: z.coerce.date().optional(),
      draft: z.boolean().default(false),
      thumbnail: thumbnailSchema({ image }),
      tags: z.array(
        z.enum([
          'ai',
          'systems',
          'graphics',
          'simulation',
          'embedded',
          'web',
          'tools',
          'games',
        ])
      ),
      featuredOrder: z.number().optional(),
      projectPeriod: z.string().optional(),
      role: z.string().optional(),
      stack: z.array(z.string()).optional(),
      scale: z.string().optional(),
      outcome: z.string().optional(),
      audience: z
        .enum(['general', 'technical', 'recruiter-relevant'])
        .default('technical'),
      links: z.array(linkSchema).default([]),
      media: z.array(mediaSchema({ image })).default([]),
    }),
});

const projects = defineCollection({
  loader: glob({ pattern: '**/*.md', base: './src/content/projects' }),
  schema: ({ image }) =>
    z.object({
      sourceProjectId: z.string(),
      title: z.string(),
      description: z.string().max(160),
      thumbnail: thumbnailSchema({ image }),
      period: z.string(),
      sortDate: z.coerce.date(),
      technologies: z.array(z.string()).default([]),
      selected: z.boolean().default(false),
      essay: reference('posts').optional(),
      links: z.array(linkSchema).default([]),
    }),
});

export const collections = { posts, projects };
