import fs from 'node:fs'
import path from 'node:path'

import { ImageResponse } from '@vercel/og'

import { urlWithParams } from '../lib/urls'

import type { Prettify } from 'ts-essentials'

export type GenericOgImageProps = Partial<Record<string, string>>

//////////////////////////////////////////////////////
//                    NOTE                          //
// Use this website to create and preview templates //
//         https://og-playground.vercel.app/        //
//////////////////////////////////////////////////////

const defaultOptions = {
  width: 1200,
  height: 630,
  fonts: [
    {
      name: 'Inter',
      weight: 400,
      style: 'normal',
      data: fs.readFileSync(
        path.resolve(
          process.cwd(),
          'node_modules',
          '@fontsource',
          'inter',
          'files',
          'inter-latin-400-normal.woff'
        )
      ),
    },
    {
      name: 'Inter',
      weight: 700,
      style: 'normal',
      data: fs.readFileSync(
        path.resolve(
          process.cwd(),
          'node_modules',
          '@fontsource',
          'inter',
          'files',
          'inter-latin-700-normal.woff'
        )
      ),
    },
  ],
} as const satisfies ConstructorParameters<typeof ImageResponse>[1]

const defaultOGImageData = fs.readFileSync(path.resolve(process.cwd(), 'src', 'assets', 'ogimage.png'))

export const ogImageTemplates = {
  default: () => {
    return new Response(Buffer.from(defaultOGImageData), {
      status: 200,
      headers: {
        'Content-Type': 'image/png',
        'Cache-Control': 'public, max-age=604800', // Cache for 1 week
      },
    })
  },
  generic: ({ title }: { title?: string }) => {
    return new ImageResponse(
      (
        <div
          style={{
            fontSize: 100,
            fontWeight: 'bold',
            color: 'white',
            backgroundImage: 'linear-gradient(135deg, #061b21, #152619)',
            width: '100%',
            height: '100%',
            padding: '50px 200px',
            textAlign: 'center',
            justifyContent: 'space-around',
            alignItems: 'center',
            display: 'flex',
            flexDirection: 'column',
          }}
        >
          <span>{title}</span>
          <svg viewBox="0 0 640 128" width="480" height="96">
            <path
              fill="#7CFF00"
              d="M66 0a20 20 0 0 0-3 1h-4l-2 1H44a30 30 0 0 0-18 10 22 22 0 0 1-4 5l-1-1a38 38 0 0 0-8-4l-3-1-2-1-1-1-2-1-1 1-2 4-1 2-1 3v1l2 1 2 1 3 1h2a237 237 0 0 0 4 1 17 17 0 0 0-3 5 11 11 0 0 0-1 4l-1 3v2l-1 2a37 37 0 0 1-2 3 21 21 0 0 0-3 4l-1 2v2l-1 1v3a185 185 0 0 0 1 8 22 22 0 0 1 0 7 24 24 0 0 0 1 10 42 42 0 0 0 2 5l1 2a170 170 0 0 1 2 5l1 3a88 88 0 0 0 4 6l1 1 1 2 2 1 2 3a26 26 0 0 0 4 4l2 2 3 2 2 1 3 2 2 1a378 378 0 0 1 4 2l3 2a99 99 0 0 0 5 2 30 30 0 0 0 4 1h2a72 72 0 0 0 20 1l2-1h3l4-1a37 37 0 0 0 6-2l3-2 2-1a26 26 0 0 0 4-2 18 18 0 0 0 3-2l2-2 2-1 1-1 1-1 3-1 1-2h1l3 3a76 76 0 0 0 5 6l1 2h4l2-2 1-1 1-2 1-1-1-2-1-2v-2l-1-1-3-2a54 54 0 0 1-6-4 51 51 0 0 0 4-5 71 71 0 0 0 3-8 179 179 0 0 1 3-8l1-2a56 56 0 0 0 0-6l1-4v-8a70 70 0 0 1-2-11 22 22 0 0 0-2-9l-1-1-1-1a20 20 0 0 1-3-5v-1l-1-2-2-2-1-2a25 25 0 0 1-3-3l-2-2-1-2-1-1a15 15 0 0 0-3-3l-2-1-3-2-3-3-1-1a46 46 0 0 0-15-6h-6l-3-1h-6zm6 10a61 61 0 0 1 6 0 51 51 0 0 1 5 2l2 1 2 1h2l1 1 1 1 1 2 2 1 2 1 3 2a108 108 0 0 0 6 8l3 2 1 2 1 2 2 2a62 62 0 0 1 3 4l1 2 1 2v2l1 4v4l1 2v10a24 24 0 0 1 0 6v5a22 22 0 0 1-2 5l-1 1-1 2-1 1-1 1-1 2-1 1-1 2-3-3-3-2-2-1-1-1-2-1 1-2a59 59 0 0 1-2 1 99 99 0 0 1-2-1 152 152 0 0 0 3-3l1-2v-1l1-1 1-2v-1h-1a29 29 0 0 1-4 6l-2 2a99 99 0 0 1-2-1 72 72 0 0 0 4-4 26 26 0 0 0 3-6 21 21 0 0 0 1-4h-1a63 63 0 0 1-5 8l-2 2a60 60 0 0 1-2 2 469 469 0 0 0-2-1 52 52 0 0 0 5-4 70 70 0 0 0 3-5l1-2a36 36 0 0 0 2-5 29 29 0 0 0 1-6v-1l-1 2a57 57 0 0 1-3 8l-2 3-1 2-1 1-2 1-2 2-2 2h-1a469 469 0 0 0-2-1l-1-1a191 191 0 0 0 1 0l2-1 2-1 3-2a13 13 0 0 0 4-4 11 11 0 0 0 2-3 64 64 0 0 0 3-11v-9a27 27 0 0 0-2-6 26 26 0 0 0-4-5l-2-2-2-2a85 85 0 0 0-11-7l-4-2-2-1-2-1h-2a29 29 0 0 0-6-1l-3 1a46 46 0 0 0-9 1 68 68 0 0 0-5 2 15 15 0 0 0-5 3l-2 2-2 2a15 15 0 0 0-2 3 292 292 0 0 0-6-7 31 31 0 0 0 2-2l1-1 1-1 2-2 2-2 2-1a124 124 0 0 1 22-4h5a61 61 0 0 1 6 0zm-9 9a20 20 0 0 1 9 2l2 1a39 39 0 0 1 8 4l2 1a104 104 0 0 1 6 4 24 24 0 0 1 4 5 97 97 0 0 1 3 7v10l-1 7-2 3-1 2-1 1h-2a30 30 0 0 0-3 3l-3 2a52 52 0 0 1-4 1 43 43 0 0 1-2-1 30 30 0 0 0 5-2 106 106 0 0 1 5-4 65 65 0 0 1 3-2l2-1 1-1 1-3a65 65 0 0 0 1-6l-1-4v-3a18 18 0 0 0-1-5l-1-2a36 36 0 0 0-3-4l-2-2-2-2a14 14 0 0 0-4-3l-2-1a29 29 0 0 1-6-2l-3-1a12 12 0 0 0-4-2h-7a33 33 0 0 0-5 1h-2a25 25 0 0 0-7 3l-1 1-3 3-3 3-1 2-1-1v-1l2-2 2-3 3-2a34 34 0 0 1 6-3l1-1a55 55 0 0 1 12-2zm22 2 1 1a29 29 0 0 1 1 0 381 381 0 0 0-2-1zm2 1a381 381 0 0 1 4 4l2 2 2 1 1 1a16 16 0 0 0-2-3l-3-2a29 29 0 0 0-4-3zm-27 2 4 1h4l1 1a37 37 0 0 0 6 2l4 1h1l2 2 3 3 3 3a138 138 0 0 1 4 6v2a37 37 0 0 1 1 8v3l-1 1-2 2a54 54 0 0 0-5 4l-3 3-3 1-2 1a52 52 0 0 0-1 0 43 43 0 0 1-2-1 71 71 0 0 0 2 0l2-1a28 28 0 0 0 6-4l3-3 3-2 1-2 1-2-1-4a11 11 0 0 0-1-4l-1-3a21 21 0 0 0-2-4l-2-2a36 36 0 0 0-6-5l-2-1a113 113 0 0 1-8-2l-2-1-3-1h-6l-1 1h-1a48 48 0 0 0-6 2l-4 1-2 2a26 26 0 0 0-3 4 66 66 0 0 1-1-1l1-1 2-2 2-2 1-1a47 47 0 0 1 7-4 29 29 0 0 1 7-1zm-40 5a18 18 0 0 1 2 4l1 1 1 1 2 1a24 24 0 0 1 3 3 37 37 0 0 1 1 1 89 89 0 0 0-2 6v3l-1 2v4l1-1 1-2a76 76 0 0 0 3-10 37 37 0 0 1 1 1l1 1a85 85 0 0 0-5 17 42 42 0 0 0-1 13l1 3v2a34 34 0 0 0 3 6l1 2a57 57 0 0 0 10 10 16 16 0 0 0 4 3l3 1 3 1 3 1 2 1 2 2a131 131 0 0 1 8-1h6a18 18 0 0 0 8-3h1a42 42 0 0 1 2 0 18 18 0 0 0 4-2 46 46 0 0 0 5-3l1-1h-2a57 57 0 0 1-6 3l-3 1h-2a26 26 0 0 1-5 2h-6l-5 1h-5l-2-2-1-1h-2l-3-1-2-1-3-1-2-1-2-2a41 41 0 0 0-5-5l-2-3a38 38 0 0 1-5-8l-1-2a55 55 0 0 1 0-8 55 55 0 0 1 1-5l1-4a73 73 0 0 1 2-9l1-4 1 2a93 93 0 0 0-1 8l-1 2v3l-1 2-1 1a43 43 0 0 0 0 7v7l1 2 1 2 2 2a56 56 0 0 1 5 5 34 34 0 0 1 3 4l1 1 1 1 2 1a45 45 0 0 0 6 2h4l1 2 1 1h1a32 32 0 0 1 5-1h6a22 22 0 0 0 6-1l2-1 3-1a22 22 0 0 1 2-1l3-1 2-1a21 21 0 0 0 1-1l3 3 1 1 5 4 1 1a83 83 0 0 1-1 0l-1 1a118 118 0 0 0-3 2l-2 2a67 67 0 0 1-4 3 72 72 0 0 1-7 3l-3 1-2 1-3 1-3 2h-3a25 25 0 0 1-5 2 14 14 0 0 1-4-1 21 21 0 0 0-6-1 61 61 0 0 0-3-1l-1-1h-1a215 215 0 0 1-6-2l-2-1-3-2-2-1-3-2-2-1-2-1-2-2a11 11 0 0 1-2-2l-1-1-1-1-1-2-1-1-2-3-2-2a15 15 0 0 1-2-4l-1-2-1-2-2-4a27 27 0 0 1-2-6v-2l1-2v-3l-1-3V52a24 24 0 0 1 2-4l1-2h1l1-2 1-2a28 28 0 0 0 1-6 33 33 0 0 1 1-4l1-2a22 22 0 0 1 1-1zm41 1a44 44 0 0 1 16 3l2 2 3 2a21 21 0 0 1 3 3 70 70 0 0 1 2 4l1 3 1 4v1l-2 2a44 44 0 0 1-4 5l-1 1-3 2-2 1-2 1a57 57 0 0 1-3 1 43 43 0 0 1 0-1 64 64 0 0 0 3-2 16 16 0 0 0 5-2 33 33 0 0 0 4-5l1-1 1-1 1-2v-1a17 17 0 0 0-1-5l-1-2-1-2-2-1a38 38 0 0 0-7-6 43 43 0 0 0-6-2h-3l-4-1-5 1a18 18 0 0 0-5 1l-2 1a16 16 0 0 0-4 3 72 72 0 0 0-1 2 66 66 0 0 1-1-1 87 87 0 0 1 0-1l1-2 2-1a29 29 0 0 1 14-4zm110 1v66h9V59h19v-9h-19V31h-9zm28 19h10V40h-10v10zm10-10h9v-9h-9v9zm-10 19v10h10V59h-10zm10 10v28h9V69h-9zm19-38v9h9v-9h-9zm9 9v10h10V40h-10zm10 10v47h9V50h-9zm9 0h10V40h-10v10zm10-10h9v-9h-9v9zm28-9v9h28v-9h-28zm28 9v10h10V40h-10zm-28 0h-9v48h9V40zm0 48v9h28v-9h-28zm28 0h10V78h-10v10zm147-57v19h-9v9h9v29h10V59h9v-9h-9V31h-10zm10 57v9h19v-9h-19zM61 35a17 17 0 0 1 4 0h2l2 1h2a24 24 0 0 1 5 2 29 29 0 0 1 4 3l1 2 2 2 1 2v2a8 8 0 0 1-1 3 19 19 0 0 1-7 7 66 66 0 0 1-4 2l-2 1a43 43 0 0 1 0-1l-1-1a78 78 0 0 0 6-2 14 14 0 0 0 6-5v-2l1-2-1-3-1-2-1-2-2-1a14 14 0 0 0-4-2 64 64 0 0 1-5-1h-1l-2-1h-7l-3 1-2 1-2 1-1 1v1l-2-1v-1l1-1 2-1a18 18 0 0 1 6-3 17 17 0 0 1 4 0zm-3 5h5a13 13 0 0 1 5 1v1h5l2 1 2 2 1 2 1 2v2l-1 1-1 2a9 9 0 0 1-3 2 45 45 0 0 0-6 2l-1-2h4l3-1 1-1 1-2 1-1v-4a7 7 0 0 0-3-2l-1-1h-2l-3-1h-1l-3-1h-3a21 21 0 0 0-4 2l-2 1a72 72 0 0 0-2-2l2-1 3-2zm4 5h4l2 1 3 1 3 2v1l1 1-1 1a29 29 0 0 1-5 1l-2 1h-2a112 112 0 0 1-1-2 16 16 0 0 1 3-1h6v-1l-1-1-2-1a19 19 0 0 0-5 0 36 36 0 0 0-3 1 112 112 0 0 1-1-1l-3-1a14 14 0 0 1 4-2zm279 5v47h10V59h28v-9h-38zm38 9v38h10V59h-10zm29-9v9h28v-9h-28zm28 9v29h10V59h-10zm0 29h-28v9h28v-9zm-28 0V59h-10v29h10zm124-38v47h9V59h10v-9h-19zm19 9v19h9V59h-9zm9 0h10v-9h-10v9zm10 0v38h9V59h-9zm28-9v9h29v-9h-29zm29 9v10h-29V59h-9v29h9V78h38V59h-9zm-29 29v9h38v-9h-38zM40 51l1 1a33 33 0 0 1 1 0v2l-2 5a45 45 0 0 0-3 8l-1 2a50 50 0 0 0 1 5 20 20 0 0 0 2 5l2 2 1 1 1 1 3 2 2 3a83 83 0 0 0 4 3l1 1 2 1 2 1 2 1h1l5-1a75 75 0 0 0 11 0 35 35 0 0 0 6-1l2-1a19 19 0 0 0 4-2l2 1-2 2-3 1a96 96 0 0 1-2 1h-2l-2 1a38 38 0 0 1-6 1h-3a43 43 0 0 0-7 0l-1 1-2-1-5-1-3-1-1-1h-1a61 61 0 0 1-4-5l-2-2a31 31 0 0 1-3-3 13 13 0 0 1-4-7 94 94 0 0 1-1-5 19 19 0 0 1 0-6v-2l2-4 1-3 1-1v-5zm5 2h1v1l-2 4a68 68 0 0 0-2 9l-1 3v2l1 2 2 2 1 1 2 3 3 3 1 1a50 50 0 0 1 5 3l2 1 2 1 1 1 3-1h4l4-1a101 101 0 0 1 10-1l4 2a13 13 0 0 1-4 1h-3a86 86 0 0 1-7 1h-4l-3 1h-2l-2 1h-1l-1-1h-1a44 44 0 0 0-5-4 17 17 0 0 1-4-3l-2-2-1-1-1-2-2-1-2-3-1-3-1-3a79 79 0 0 1 3-9l1-3 2-4v-1zm4 1 1 1a128 128 0 0 0-2 4l-1 4a31 31 0 0 0-1 7l1 2a45 45 0 0 0 3 4 14 14 0 0 0 3 4l3 1 4 1 2 1h9l3-1a102 102 0 0 0 3 0l1 1 1 1h-2l-3 1-3 1h-8l-3-1-4-2-3-1a27 27 0 0 1-4-4 60 60 0 0 0-3-4l-1-1-1-1 1-3v-3l1-4 1-4 2-4zm3 2 1 1 1 1-1 1-1 2v2l-1 4v3l2 3 1 1 2 2 2 1h2a48 48 0 0 0 9 1l4-1a191 191 0 0 0 1 0l1 2h-2l-3 1h-6a31 31 0 0 1-8-2l-3-2-2-3-1-2v-2a152 152 0 0 1 2-13zm4 4a92 92 0 0 0 1 2 54 54 0 0 0 0 2l-1 4v2l1 2h1l2 1h6l2-1a72 72 0 0 1 1 1 27 27 0 0 1 1 1h-3l-4 1h-2a9 9 0 0 1-3-1 9 9 0 0 1-3-3v-1l-1-3 1-2v-3l1-2zm3 5a92 92 0 0 0 1 2l1 1 2 1a72 72 0 0 1 2 1h-3l-2-1h-1v-4zM32 88v2a34 34 0 0 0 2 5l2 2 2 2 2 2 3 2a62 62 0 0 0 12 6 24 24 0 0 0 6 1h4a180 180 0 0 0 9-1h1l-3-1a225 225 0 0 0-10 0h-3a137 137 0 0 0-7-4l-3-1-1-1h-1l-3-1-2-2a96 96 0 0 1-6-5l-2-3-1-2-1-1zm478 0v9h9v-9h-9z"
            />
          </svg>
        </div>
      ),
      defaultOptions
    )
  },
} as const satisfies Record<string, (props: GenericOgImageProps) => ImageResponse | null>

type OgImageTemplate = keyof typeof ogImageTemplates
type OgImageProps<T extends OgImageTemplate> = Parameters<(typeof ogImageTemplates)[T]>[0]
// eslint-disable-next-line @typescript-eslint/sort-type-constituents
export type OgImageAllTemplatesWithGenericProps = { template: OgImageTemplate } & GenericOgImageProps

export type OgImageAllTemplatesWithProps = Prettify<
  {
    // eslint-disable-next-line @typescript-eslint/sort-type-constituents
    [K in OgImageTemplate]: { template: K } & Omit<OgImageProps<K>, 'template'>
  }[OgImageTemplate]
>

export function makeOgImageUrl(
  ogImage: OgImageAllTemplatesWithProps | string | undefined,
  baseUrl: URL | string
) {
  return typeof ogImage === 'string'
    ? new URL(ogImage, baseUrl).href
    : urlWithParams(new URL('/ogimage.png', baseUrl), ogImage ?? {})
}
