import dotenv from 'dotenv';
import { installPlatformEventHandlers } from './utils/platformEventHandling.js';
import { mkdir, readFile, rename, writeFile, chmod, unlink } from 'node:fs/promises';
import path from 'node:path';
import { existsSync } from 'node:fs';
import { v4 as uuidv4 } from 'uuid';
import { setTimeout } from 'node:timers/promises';
dotenv.config();

installPlatformEventHandlers();

const syncLoopYtDlp = async () => {
  const stateDir = process.env.YT_DLP_STATE_DIR;
  if (!stateDir) {
    console.error('No YT_DLP_STATE_DIR env variable set');
  }
  const pollInterval = Number(process.env.YT_DLP_POLL_INTERVAL) || 300;
  try {
    await mkdir(stateDir);
  } catch (e) {
    if (e.code !== 'EEXIST') {
      throw e;
    }
  }

  while (true) {
    await pollYtDlp(stateDir);
    await setTimeout(pollInterval * 1000);
  }
};

const pollYtDlp = async (stateDir: string) => {
  const stateFile = path.join(stateDir, 'state.json');
  let lastReleaseId: number = 0;
  if (existsSync(stateFile)) {
    try {
      const stateData = JSON.parse(await readFile(stateFile, 'utf-8'));
      lastReleaseId = stateData.lastReleaseId || 0;
    } catch (e) {
      console.warn('Error reading state file', e);
    }
  }

  const latestRelease = await (await fetch('https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest')).json();
  const { id: newReleaseId, assets } = latestRelease;
  if (newReleaseId <= lastReleaseId) {
    return;
  }

  console.log('New yt-dlp release found', {
    newReleaseId,
    lastReleaseId,
  });

  const downloadUrl = assets.find((asset) => asset.name === 'yt-dlp')?.browser_download_url;
  if (!downloadUrl) {
    console.error('No download url found for yt-dlp');
    return;
  }

  await downloadYtDlp(stateDir, downloadUrl);

  const newState = { lastReleaseId: newReleaseId };
  await writeFile(stateFile, JSON.stringify(newState), 'utf-8');
};

const downloadYtDlp = async (stateDir: string, downloadUrl: string) => {
  const tempName = path.join(stateDir, uuidv4());
  const res = await fetch(downloadUrl, { redirect: 'follow' });
  if (!res.ok) {
    throw new Error(`HTTP error downloading ${downloadUrl}: ${res.status}`);
  }
  try {
    await writeFile(tempName, res.body as any);
    await chmod(tempName, '755');
    const dest = path.join(stateDir, 'yt-dlp');
    await rename(tempName, dest);
  } finally {
    try {
      await unlink(tempName);
    } catch (e) {}
  }
};

await syncLoopYtDlp();
