import { promises as fs } from "fs";
import db from '../../sql.mjs';
import lib from '../../lib.mjs';
import search from '../../routeinc/search.mjs';

const allowedMimes = [ "audio", "image", "video", "%" ];
export default router => {
  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 db`
        select *
        from "items"
        where
          mime ilike ${mime} and
          username ilike ${user} and
          active = 'true'
        order by random()
        limit 1
      `;
  
      return res.json({
        success: rows.length > 0,
        items: rows.length > 0 ? rows[0] : []
      });
    });
  
    group.get(/\/items\/get/, async (req, res) => {
      let eps = 150;

      const opt = {
        older: req.url.qs.older ?? null,
        newer: req.url.qs.newer ?? null,
        mode: +req.url.qs.mode ?? 0 // 0 sfw, 1 nsfw, 2 untagged, 3 all
      };

      const newest = (await db`select max(id) as id from "items"`)[0].id;
      const oldest = (await db`select min(id) as id from "items"`)[0].id;
      const modequery = lib.getMode(opt.mode);

      const rows = (await db`
        select "items".id, "items".mime, coalesce("tags_assign".tag_id, 0) as tag_id
        from "items"
        left join "tags_assign" on "tags_assign".item_id = "items".id and ("tags_assign".tag_id = 1 or "tags_assign".tag_id = 2)
        where
          ${db.unsafe(modequery)} and
          active = 'true'
          ${
            opt.older
              ? db`and id <= ${opt.older}`
              : opt.newer
                ? db`and id >= ${opt.newer}`
                : db``
          }
        order by id ${
          opt.newer
            ? db`asc`
            : db`desc`
        }
        limit ${eps}
      `).sort((a, b) => b.id - a.id);

      return res.json({
        atEnd: rows[0].id === newest,
        atStart: rows[rows.length - 1].id === oldest,
        success: true,
        items: rows
      }, 200);
    });
  
    group.get(/\/item\/[0-9]+$/, async (req, res) => {
      const id = +req.url.split[3];
  
      const item = await db`
        select *
        from "items"
        where id = ${+id} and active = 'true'
        limit 1
      `;
      const next = await db`
        select id
        from "items"
        where id > ${+id} and active = 'true'
        order by id
        limit 1
      `;
      const prev = await db`
        select id
        from "items"
        where id < ${+id} and active = 'true'
        order by id desc
        limit 1
      `;
  
      if(item.length === 0) {
        return res.json({
          success: false,
          msg: 'no items found'
        });
      }
  
      const rows = {
        ...item[0],
        ...{
          next: next[0]?.id ?? null,
          prev: prev[0]?.id ?? null
        }
      };

      return res.json({
        success: true,
        rows
      });
    });
  
    group.get(/\/user\/.*(\/\d+)?$/, async (req, res) => {
      const user = req.url.split[3];
      const eps = +req.url.split[4] || 50;
  
      const rows = db`
        select id, mime, size, src, stamp, userchannel, username, usernetwork
        from "items"
        where username = ${user} and active = 'true'
        order by stamp desc
        limit ${+eps}
      `;
        
      return res.json({
        success: rows.length > 0,
        items: rows.length > 0 ? rows : []
      });
    });

    // tags lol

    group.put(/\/admin\/tags\/(?<tagname>.*)/, lib.loggedin, async (req, res) => {
      if(!req.params.tagname || !req.post.newtag) {
        return res.json({
          success: false,
          msg: 'missing tagname or newtag',
          debug: {
            params: req.params.tagname,
            post: req.post
          }
        }, 400); // bad request
      }

      const tagname = decodeURIComponent(req.params.tagname);
      const newtag = req.post.newtag;

      if(['sfw', 'nsfw'].includes(tagname) || ['sfw', 'nsfw'].includes(newtag)) {
        return res.json({
          msg: 'f0ck you'
        }, 405); // method not allowed
      }

      const tmptag = (await db`
        select *
        from "tags"
        where tag = ${tagname}
        limit 1
      `)[0];
      
      if(!tmptag) {
        return res.json({
          success: false,
          msg: 'no tag found'
        }, 404); // not found
      }

      const q = (await db`
        update "tags" set ${
          db({
            tag: newtag
          }, 'tag')
        }
        where tag = ${tagname}
        returning *
      `)?.[0];

      return res.json(q, tagname === newtag ? 200 : 201); // created (modified)
    });

    group.get(/\/admin\/tags\/suggest$/, lib.loggedin, async (req, res) => {
      const reply = {
        success: false,
        suggestions: {}
      };

      const searchString = req.url.qs.q;

      if(searchString?.length <= 1) {
        reply.error = 'too short lol';
        return res.json(reply);
      }

      try {
        const q = await db`
          select tag, count(tags_assign.tag_id) as tagged
          from "tags"
          left join "tags_assign" on "tags_assign".tag_id = "tags".id
          where normalized like '%' || slugify(${searchString}) || '%'
          group by "tags".id
          order by tagged desc
          limit 15
        `;
        reply.success = true;
        reply.suggestions = search(q, searchString);
      } catch(err) {
        reply.error = err.msg;
      }

      return res.json(reply);
    });

    group.post(/\/admin\/deletepost$/, lib.auth, async (req, res) => {
      if(!req.post.postid) {
        return res.json({
          success: false,
          msg: 'no postid'
        });
      }
      const id = +req.post.postid;

      if(id <= 1) {
        return res.json({
          success: false
        });
      }

      const f0ck = await db`
        select dest, mime
        from "items"
        where
          id = ${id} and
          active = 'true'
        limit 1
      `;

      if(f0ck.length === 0) {
        return res.json({
          success: false,
          msg: `f0ck ${id}: f0ck not found`
        });
      }

      await db`update "items" set active = 'false' where id = ${id}`;
  
      await fs.copyFile(`./public/b/${f0ck[0].dest}`, `./deleted/b/${f0ck[0].dest}`).catch(_=>{});
      await fs.copyFile(`./public/t/${id}.webp`, `./deleted/t/${id}.webp`).catch(_=>{});
      await fs.unlink(`./public/b/${f0ck[0].dest}`).catch(_=>{});
      await fs.unlink(`./public/t/${id}.webp`).catch(_=>{});

      if(f0ck[0].mime.startsWith('audio')) {
        await fs.copyFile(`./public/ca/${id}.webp`, `./deleted/ca/${id}.webp`).catch(_=>{});
        await fs.unlink(`./public/ca/${id}.webp`).catch(_=>{});
      }

      res.json({
        success: true
      });
    });

    group.post(/\/admin\/togglefav$/, lib.loggedin, async (req, res) => {
      const postid = +req.post.postid;
      
      let favs = await db`
        select user_id
        from "favorites"
        where item_id = ${+postid}
      `;

      if(Object.values(favs).filter(u => u.user_id === req.session.id)[0]) {
        // del fav
        await db`
          delete from "favorites"
          where user_id = ${+req.session.id}
          and item_id = ${+postid}
        `;
      }
      else {
        // add fav
        await db`
          insert into "favorites" ${
            db({
              item_id: +postid,
              user_id: +req.session.id
            }, 'item_id', 'user_id')
          }
        `;
      }

      favs = await db`
        select "user".user, "user_options".avatar
        from "favorites"
        left join "user" on "user".id = "favorites".user_id
        left join "user_options" on "user_options".user_id = "favorites".user_id
        where "favorites".item_id = ${+postid}
      `;

      return res.json({
        success: true,
        itemid: postid,
        favs
      });
    });
  
  });

  return router;
};
