import { unlink } from "fs";
import { join } from "path";
import { promisify } from "util";
import { getDate, getDatetime } from "taehui-ts/date";

import DB from "src/system/DB";
import { getFileNames, getTitle, isBannedIP } from "src/Utility";
import Configure from "src/system/Configure";

const wipeFile = promisify(unlink);

export const getEssay = async (
  essayID: number,
  language: string,
  avatarIP: string,
) => {
  if (!isBannedIP(avatarIP)) {
    await DB.postEssayHit(essayID, avatarIP, getDate());
  }
  const essay = await DB.getEssay(essayID);
  if (essay) {
    const { forumTitle, forumTitle1042, ...restEssay } = essay;
    return {
      ...restEssay,
      forumTitle: getTitle(language, {
        title: forumTitle,
        title1042: forumTitle1042,
      }),
    };
  }
};

export const getEssayHit = async (essayID: number) => {
  return DB.getEssayHit(essayID);
};

export const doModifyEssay = async (
  essayID: number,
  avatarID: string,
  title: string,
  text: string,
  level: number,
) => {
  return (
    title &&
    text &&
    DB.ta(async (db) => {
      if (await DB.doModifyEssay(db, essayID, avatarID, title, text, level)) {
        const lastFileNames = await DB.getFileNames(db, essayID);
        const fileNames = getFileNames(text);
        const hrefs = fileNames.map(([fileName]) => fileName);

        await wipeFiles(
          lastFileNames.filter((lastFileName) => !hrefs.includes(lastFileName)),
        );

        await DB.putFileNames(
          avatarID,
          essayID,
          fileNames.filter(([fileName]) => !lastFileNames.includes(fileName)),
        );

        return true;
      } else {
        return false;
      }
    })
  );
};

export const wipeEssay = async (
  essayID: number,
  avatarID: string,
  level: number,
) => {
  return DB.ta(async (db) => {
    const fileNames = await DB.getFileNames(db, essayID);
    if (await DB.wipeEssay(essayID, avatarID, level)) {
      await wipeFiles(fileNames);
      return true;
    } else {
      return false;
    }
  });
};

export const getLatestEssays = async (language: string) => {
  return (await DB.getLatestEssays()).map(
    ({ forumTitle, forumTitle1042, ...restLatestEssay }) => {
      return {
        ...restLatestEssay,
        forumTitle: getTitle(language, {
          title: forumTitle,
          title1042: forumTitle1042,
        }),
      };
    },
  );
};

const wipeFiles = async (fileNames: string[]) => {
  await DB.wipeFileNames(fileNames);
  for await (const fileName of fileNames) {
    try {
      await wipeFile(join(Configure.path.essay, fileName));
    } catch {}
  }
};

export const postEssay = async (
  forumID: string,
  avatarID: string,
  level: number,
  title: string,
  text: string,
) => {
  return title && text
    ? DB.ta(async (db) => {
        const forum = await DB.getForum(db, forumID);
        if (forum) {
          if (forum.level <= level) {
            const fileNames = getFileNames(text);

            const essayID = await DB.postEssay(
              db,
              forumID,
              avatarID,
              getDatetime(),
              title,
              text,
            );
            await DB.putFileNames(avatarID, essayID, fileNames);
            return essayID;
          }
        }

        return -1;
      })
    : -1;
};
