import koaBody from "koa-body";
import Router from "koa-router";
import { join } from "path";
import { readFileSync } from "fs";

import Configure from "src/system/Configure";
import {
  doInvalidateDrawing,
  doModifyAvatar,
  doModifyAvatarIntro,
  getAvatarDrawing,
  getLatestAvatars,
  getTotem,
  postAvatar,
  quitTotem,
} from "src/systems/avatar";
import { validateTotem } from "src/mws/avatar";
import { validateMillis } from "src/mws/millis";

const router = new Router();

router.get("/latest", async (ctx) => {
  ctx.body = await getLatestAvatars();
  ctx.status = 200;
});

router.post("/getTotem", validateMillis, async (ctx) => {
  const {
    request: {
      body: { avatarID, avatarCipher },
    },
  } = ctx;

  const data = await getTotem(avatarID, avatarCipher);
  if (data) {
    ctx.body = data;
    ctx.status = 200;
  } else {
    ctx.status = 403;
  }
});

router.patch("/totem", validateMillis, validateTotem(true), async (ctx) => {
  const {
    request: { headers },
  } = ctx;

  ctx.body = {
    avatarID: headers.avatarID,
    avatarName: headers.avatarName,
    level: Number(headers.level),
    fax: headers.fax,
    avatarIntro: headers.avatarIntro,
  };
  ctx.status = 201;
});

router.delete("/totem", validateMillis, validateTotem(false), async (ctx) => {
  const {
    headers: { avatarID },
  } = ctx;

  if (await quitTotem(avatarID as string)) {
    ctx.status = 204;
  } else {
    ctx.status = 403;
  }
});

router.put("/", validateMillis, validateTotem(false), async (ctx) => {
  const {
    headers: { avatarID },
    request: {
      body: {
        avatarCipher,
        avatarCipherModified,
        avatarName,
        fax,
        avatarIntro,
      },
    },
  } = ctx;

  if (
    await doModifyAvatar(
      avatarID as string,
      avatarCipher,
      avatarCipherModified,
      avatarName,
      fax,
      avatarIntro,
    )
  ) {
    ctx.body = avatarCipherModified;
    ctx.status = 204;
  } else {
    ctx.status = 403;
  }
});

router.put(
  "/avatarIntro",
  validateMillis,
  validateTotem(false),
  async (ctx) => {
    const {
      headers: { avatarID },
      request: { body },
    } = ctx;

    if (await doModifyAvatarIntro(avatarID as string, body)) {
      ctx.status = 204;
    } else {
      ctx.status = 403;
    }
  },
);

router.post("/", validateMillis, async (ctx) => {
  const {
    request: {
      ip,
      body: { avatarID, avatarCipher, avatarName, fax },
    },
  } = ctx;

  if (await postAvatar(avatarID, avatarCipher, avatarName, ip, fax)) {
    ctx.status = 201;
  } else {
    ctx.status = 403;
  }
});

const defaultDrawing = readFileSync("assets/avatar.png");

router.get("/drawing", async (ctx) => {
  ctx.set("content-type", "image/png");
  ctx.body = defaultDrawing;
  ctx.status = 200;
});

router.get("/drawing/:avatarID", async (ctx) => {
  const {
    params: { avatarID },
  } = ctx;

  ctx.set("content-type", "image/png");
  ctx.body = (await getAvatarDrawing(avatarID)) ?? defaultDrawing;
  ctx.status = 200;
});

router.post(
  "/drawing",
  validateMillis,
  validateTotem(false),
  async (ctx, next) => {
    const {
      headers: { avatarID },
    } = ctx;

    await koaBody({
      multipart: true,
      formidable: {
        keepExtensions: true,
        uploadDir: Configure.path.avatar,
        onFileBegin: (_, file) => {
          file.filepath = join(Configure.path.avatar, avatarID + ".png");
        },
      },
    })(ctx, next);
  },
  async (ctx) => {
    const {
      headers: { avatarID },
    } = ctx;

    await doInvalidateDrawing(avatarID as string);
    ctx.status = 201;
  },
);

export default router;
