import "@johnlindquist/kit";
import { Choices } from "@johnlindquist/kit";
const CACHE_SCRIPT_NAME = "cache-starred-repos.ts";
const { isValidCron }: typeof import("cron-validator") = await npm(
  "cron-validator"
);
const installedScripts = await readdir(home(kenvPath("/scripts")));
if (!installedScripts.includes(CACHE_SCRIPT_NAME)) {
  const cronSchedule = await arg({
    placeholder:
      "Choose schedule or define your own schedule using CRON syntax",
    strict: false,
    choices: getCronChoices,
    validate: validateCRON,
  });
  await appendFile(
    home(kenvPath("/scripts"), CACHE_SCRIPT_NAME),
    buildCacheScript({ cronSchedule })
  );
  await div(
    `<div class='p-12 text-lg text-center'>
      <h2 class='mb-8'>
        Looks like this is your first run.
      </h2>
      <h3>I've setup a caching script for you.</h3>
      <p class='mb-20'>
        This script will run on the defined schedule and cache your starred repos for faster searching. If you need to run the caching manually you can do so from Kit.
      </p>
      <p>
        To initialize your cache now, run <code class='text-yellow-400'>Cache starred GitHub repos</code>.
      </p>
    </div>`
  );
  exit(0);
}
let { cachedStars } = await db("starred-repos", { cachedStars: [] });
const star = await arg(
  "Search starred repos...",
  cachedStars.map((star) => {
    return {
      name: star.full_name,
      value: star.html_url,
      description: `⭐ ${star.stargazers_count} ${
        star.description ? " | " + star.description : ""
      }`,
      icon: star.owner.avatar_url,
    };
  })
);
browse(star);
function getCronChoices(): Choices<string> {
  return [
    {
      name: "0 12 * * *",
      value: "0 12 * * *",
      description: "Daily at noon",
    },
    {
      name: "0 8 * * *",
      value: "0 8 * * *",
      description: "Daily at 8:00 am",
    },
    {
      name: "0 8 * * 1",
      value: "0 8 * * 1",
      description: "Weekly on Monday morning",
    },
  ];
}
function validateCRON(cron: string) {
  return isValidCron(cron)
    ? true
    : "<span class='text-red-500'>Invalid CRON syntax. Check <a href='https://crontab.guru/'>crontab.guru</a> for help</span>";
}
function buildCacheScript({ cronSchedule }: { cronSchedule: string }) {
  return `// Name: Cache starred GitHub repos
// Description: Cache starred GitHub repositories for future operations
// Author: Basti Buck
// Twitter: @bastibuck
\/\/ Schedule: ${cronSchedule}
import "@johnlindquist/kit";
const { z }: typeof import("zod") = await npm("zod");
const { Octokit }: typeof import("octokit") = await npm("octokit");
import { Endpoints } from "@octokit/types";
const AUTH_TOKEN = await env("GITHUB_AUTH_TOKEN", {
  hint: md(
    \`Create a [personal access token](https://github.com/settings/tokens) with the \\\`read:user\\\` scope.\`
  ),
  ignoreBlur: true,
  secret: true,
});
const USERNAME = await env("GITHUB_USERNAME", {
  hint: md(\`Your GitHub username\`),
});
type Star = Endpoints["GET /user/starred"]["response"]["data"][number];
const cachedStarSchema = z.array(
  z.object({
    full_name: z.string(),
    html_url: z.string(),
    stargazers_count: z.number(),
    description: z.string().optional().nullish(),
    owner: z.object({
      avatar_url: z.string(),
    }),
  })
);
const octokit = new Octokit({
  auth: AUTH_TOKEN,
});
let { cachedStars, write } = await db("starred-repos", {
  cachedStars: [],
});
const stars = await octokit.paginate<Star>(\`GET /users/\${USERNAME}/starred\`);
_.remove(cachedStars, () => true);
cachedStars.push(...cachedStarSchema.parse(stars));
await write();
`;
}