import {
  doModifyEssay as dbModifyEssay,
  getEssay as dbGetEssay,
  getFileNames as dbGetFileNames,
  getForum,
  getLatestEssays as dbGetLatestEssays,
  postEssay as dbPostEssay,
  postEssayHit,
  postFileNames,
  ta,
  wipeEssay as dbWipeEssay,
  wipeFileNames,
} from "@/app/www/system/DB";
import { ESSAY_ENTRY_PATH } from "@/app/www/utilities/Path";
import {
  getFileNames,
  getTitle,
  isBannedIP,
} from "@/app/www/utilities/Utility";
import { unlink } from "fs/promises";
import { join } from "path";
import { getDate, getDatetime } from "taehui-lib/date";

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

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

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

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

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

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

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

const wipeFiles = async (fileNames: string[]) => {
  await wipeFileNames(fileNames);
  for await (const fileName of fileNames) {
    try {
      await unlink(join(ESSAY_ENTRY_PATH, fileName));
    } catch {}
  }
};

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

            const essayID = await dbPostEssay(
              db,
              forumID,
              avatarID,
              getDatetime(),
              title,
              text,
            );
            await postFileNames(avatarID, essayID, fileNames);
            return essayID;
          }
        }

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