import * as fs from 'fs';
import * as jsdom from 'jsdom';
import * as path from 'path';
import Turndown from 'turndown';
import { error, warn } from './logger';
import urlData from '../data/urls.json';
import { fileURLToPath } from 'url';

const __dirname = path.dirname(fileURLToPath(import.meta.url));

const pathToCache = path.join(__dirname, '../data/urls.json');

const turndown = new Turndown();

// change anchors to plain text so we don't end up with a bunch of relative urls
turndown.addRule('anchor', {
  filter: 'a',
  replacement: (content: string) => content,
});

async function scrapeSummary(url: string): Promise<string | undefined> {
  try {
    const htmlResponse = await fetch(url);
    const htmlContents = await htmlResponse.text();

    const { window } = new jsdom.JSDOM(htmlContents);
    const summaryElement = window.document.querySelector('main :not(.notecard) > p:not(:empty)');
    window.close();

    if (summaryElement) {
      return turndown.turndown(summaryElement.innerHTML);
    }

    throw new Error('Element was not found');
  } catch (e) {
    warn(`Could not fetch summary for '${url}': ${e}`);
  }
}

function saveToFile(): void {
  try {
    const sortedUrlData = (Object.keys(urlData) as (keyof typeof urlData)[])
      .sort()
      .reduce<Record<string, string>>((data, url) => {
        data[url] = urlData[url];
        return data;
      }, {});

    const fileContents = JSON.stringify(sortedUrlData, undefined, 2);
    fs.writeFileSync(pathToCache, fileContents, { encoding: 'utf-8' });
  } catch (e) {
    if (e instanceof Error) {
      error(e.toString());
    } else {
      error('Unknown error');
    }
  }
}

export async function getSummary(url: string): Promise<string | undefined> {
  let summaryData: string | undefined = urlData[url as keyof typeof urlData];

  if (url && !summaryData) {
    console.log('Fetching summary for ' + url);
    summaryData = await scrapeSummary(url);
    if (summaryData) {
      urlData[url as keyof typeof urlData] = summaryData;
      saveToFile();
    }
  }

  if (summaryData) {
    return cleanup(summaryData);
  }
}

function cleanup(summary: string) {
  return summary.replace(/\u2068/g, '').replace(/\u2069/g, '');
}
