import sql from "../sql.mjs";

const allowedMimes = [ "audio", "image", "video", "%" ];
const auth = async (req, res, next) => {
  if(!req.session) {
    return res.reply({
      code: 401,
      body: "401 - Unauthorized"
    });
  }
  return next();
};

const getTags = async itemid => await sql("tags_assign")
  .leftJoin("tags", "tags.id", "tags_assign.tag_id")
  .where("tags_assign.item_id", itemid)
  .select("tags.id", "tags.tag", "tags_assign.prefix");

const cleanTags = async () => {
  const tags = await sql("tags").leftJoin("tags_assign", "tags_assign.tag_id", "tags.id").whereNull("tags_assign.item_id");
  if(tags.length === 0)
    return;
  
  let deleteTag = sql("tags");
  tags.forEach(tag => {
    if(["sfw", "nsfw"].includes(tag.tag.toLowerCase()))
      return;
    deleteTag = deleteTag.orWhere("id", tag.id);
  });
  await deleteTag.del();
};

export default (router, tpl) => {
  router.group(/^\/api\/v2/, group => {

    group.get(/$/, (req, res) => {
      res.end("api lol");
    });
  
    group.get(/\/random(\/user\/.+|\/image|\/video|\/audio)?$/, async (req, res) => {
      const user = req.url.split[3] === "user" ? req.url.split[4] : "%";
      const mime = (allowedMimes.filter(n => req.url.split[3]?.startsWith(n))[0] ? req.url.split[3] : "") + "%";
  
      const rows = await sql("items").orderByRaw("rand()").limit(1).where("mime", "like", mime).andWhere("username", "like", user);
  
      res
        .writeHead(200, { "Content-Type": "application/json" })
        .end(JSON.stringify(rows.length > 0 ? rows[0] : []), "utf-8");
    });
  
    group.get(/\/p\/([0-9]+)/, async (req, res) => { // legacy
      let eps = 100;
      let id = +req.url.split[3];
  
      const rows = await sql("items").where("id", "<", id).orderBy("id", "desc").limit(eps);
  
      const items = {
        items: rows,
        last: rows[rows.length - 1].id
      };
  
      res.writeHead(200, { "Content-Type": "application/json" });
      res.end(JSON.stringify(items), "utf-8");
    });
  
    group.get(/\/item\/[0-9]+$/, async (req, res) => {
      const id = +req.url.split[3];
  
      const item = await sql("items").where("id", id).limit(1);
      const next = await sql("items").select("id").where("id", ">", id).orderBy("id").limit(1);
      const prev = await sql("items").select("id").where("id", "<", id).orderBy("id", "desc").limit(1);
  
      if(item.length === 0)
        return "nope";
  
      const rows = {
        ...item[0],
        ...{
          next: next[0]?.id ?? null,
          prev: prev[0]?.id ?? null
        }
      };
      res.reply({
        type: "application/json",
        body: JSON.stringify(rows)
      });
    });
  
    group.get(/\/user\/.*(\/\d+)?$/, async (req, res) => { // auf qs umstellen
      const user = req.url.split[3];
      const eps = +req.url.split[4] || 50;
  
      const rows = await sql("items")
        .select("id", "mime", "size", "src", "stamp", "userchannel", "username", "usernetwork")
        .where("username", user)
        .orderBy("stamp", "desc")
        .limit(eps);
        
      res.reply({
        type: "application/json",
        body: JSON.stringify(rows.length > 0 ? rows : [])
      });
    });
  
    // adminzeugs
    group.post(/\/admin\/tags\/add$/, auth, async (req, res) => {
      if(!req.post.postid || !req.post.tag) {
        return res.reply({ body: JSON.stringify({
          success: false,
          msg: "missing postid or tag"
        })});
      }
  
      const postid = +req.post.postid;
      const tag = req.post.tag;
  
      if(tag.length >= 45) {
        return res.reply({ body: JSON.stringify({
          success: false,
          msg: "tag is too long!"
        })});
      }
  
      try {
        let tagid;
        const tag_exists = await sql("tags").select("id", "tag").where("tag", tag);
        if(tag_exists.length === 0) { // create new tag
          tagid = (await sql("tags").insert({
            tag: tag
          }))[0];
        }
        else {
          tagid = tag_exists[0].id;
        }
        await sql("tags_assign").insert({
          tag_id: tagid,
          item_id: postid,
          prefix: `${req.session.user}@webinterface`
        });
      } catch(err) {
        return res.reply({ body: JSON.stringify({
          success: false,
          msg: err.message,
          tags: await getTags(postid)
        })});
      }
  
      return res.reply({ body: JSON.stringify({
        success: true,
        postid: req.post.postid,
        tag: req.post.tag,
        tags: await getTags(postid)
      })});
    });
  
    group.post(/\/admin\/tags\/delete$/, auth, async (req, res) => {
      if(!req.post.postid || !req.post.tag) {
        return res.reply({ body: JSON.stringify({
          success: false,
          msg: "missing postid or tag"
        })});
      }
  
      const postid = +req.post.postid;
      const tag = req.post.tag;
  
      const tags = await getTags(postid);
  
      const tagid = tags.filter(t => t.tag === tag)[0]?.id ?? null;
      if(!tagid || tagid?.length === 0) {
        return res.reply({ body: JSON.stringify({
          success: false,
          tag: tag,
          msg: "tag is not assigned",
          tags: await getTags(postid)
        })});
      }
      
      let q = sql("tags_assign").where("tag_id", tagid).andWhere("item_id", postid).del();
      if(req.session.level < 50)
        q = q.andWhere("prefix", `${req.session.user}@webinterface`);
      const reply = !!(await q);
  
      //await cleanTags();
  
      return res.reply({ body: JSON.stringify({
        success: reply,
        tag: tag,
        tagid: tagid,
        tags: await getTags(postid)
      })});
    });
  
    group.get(/\/admin\/tags\/get\/\d+$/, auth, async (req, res) => {
      return res.reply({ body: JSON.stringify({
        tags: await getTags(+req.url.split[5])
      })});
    });
  
    group.get(/\/admin\/deletepost\/\d+$/, auth, async (req, res) => {
      if(!req.url.split[4]) {
        return res.reply({ body: JSON.stringify({
          success: true,
          msg: "no postid"
        })});
      }
      const postid = +req.url.split[4];
  
      await sql("items").where("id", postid).del();
      res.reply({ body: JSON.stringify({
        success: true
      })});
    });

  });

  return router;
};
