// admin/post.js
// Copyright (C) 2021 Digital Telepresence, LLC
// License: Apache-2.0

'use strict';

const express = require('express');
const multer = require('multer');

const { SiteController, SiteError } = require('../../../lib/site-lib');

class PostController extends SiteController {

  constructor (dtp) {
    super(dtp, module.exports);
  }

  async start ( ) {
    const upload = multer({ dest: `/tmp/${this.dtp.config.site.domainKey}/uploads/${module.exports.slug}` });

    const router = express.Router();
    router.use(async (req, res, next) => {
      res.locals.currentView = 'admin';
      res.locals.adminView = 'post';
      return next();
    });

    router.param('postId', this.populatePostId.bind(this));

    router.post('/:postId/image', upload.single('imageFile'), this.postUpdateImage.bind(this));
    router.post('/:postId', this.postUpdatePost.bind(this));

    router.get('/compose', this.getComposer.bind(this));
    router.get('/:postId', this.getComposer.bind(this));

    router.get('/', this.getIndex.bind(this));

    router.delete('/:postId', this.deletePost.bind(this));

    return router;
  }

  async populatePostId (req, res, next, postId) {
    const { post: postService } = this.dtp.services;
    try {
      res.locals.post = await postService.getById(postId);
      if (!res.locals.post) {
        throw new SiteError(404, 'Post not found');
      }
      return next();
    } catch (error) {
      this.log.error('failed to populate postId', { postId, error });
      return next(error);
    }
  }

  async postUpdateImage (req, res) {
    const { post: postService } = this.dtp.services;
    try {
      const displayList = this.createDisplayList('post-image');

      await postService.updateImage(req.user, res.locals.post, req.file);

      displayList.showNotification(
        'Profile photo updated successfully.',
        'success',
        'bottom-center',
        2000,
      );
      res.status(200).json({ success: true, displayList });
    } catch (error) {
      this.log.error('failed to update feature image', { error });
      return res.status(error.statusCode || 500).json({
        success: false,
        message: error.message,
      });
    }
  }

  async postUpdatePost (req, res, next) {
    const { post: postService } = this.dtp.services;
    try {
      await postService.update(res.locals.post, req.body);
      res.redirect('/admin/post');
    } catch (error) {
      this.log.error('failed to update post', { newletterId: res.locals.post._id, error });
      return next(error);
    }
  }

  async getComposer (req, res) {
    const { post: postService } = this.dtp.services;
    if (!res.locals.post) {
      res.locals.post = await postService.createPlaceholder(req.user);
    }
    res.render('post/editor');
  }

  async getIndex (req, res, next) {
    const { post: postService } = this.dtp.services;
    try {
      res.locals.pageTitle = `Posts for ${this.dtp.config.site.name}`;
      res.locals.pagination = this.getPaginationParameters(req, 20);
      res.locals.posts = await postService.getAllPosts(res.locals.pagination);
      res.render('admin/post/index');
    } catch (error) {
      this.log.error('failed to fetch posts', { error });
      return next(error);
    }
  }

  async deletePost (req, res) {
    const { post: postService } = this.dtp.services;
    try {
      const displayList = this.createDisplayList('delete-post');

      await postService.deletePost(res.locals.post);

      displayList.removeElement(`li[data-post-id="${res.locals.post._id}"]`);
      displayList.showNotification(
        `Post "${res.locals.post.title}" deleted`,
        'success',
        'bottom-center',
        3000,
      );
      res.status(200).json({ success: true, displayList });
    } catch (error) {
      this.log.error('failed to delete post', {
        postId: res.local.post._id,
        error,
      });
      res.status(error.statusCode || 500).json({
        success: false,
        message: error.message,
      });
    }
  }
}

module.exports = {
  name: 'adminPost',
  slug: 'admin-post',
  create: async (dtp) => { return new PostController(dtp); },
};