// hive/user.js
// Copyright (C) 2022 DTP Technologies, LLC
// License: Apache-2.0

'use strict';

const fs = require('fs');

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

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

class HiveUserController extends SiteController {

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

    this.methods = [
      {
        name: 'getResolveUsers',
        url: '/resolve',
        params: {
          'q': 'string',
        },
      },
      {
        name: 'getUserProfile',
        url: '/:userId',
        method: 'GET',
      },
    ];
  }

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

    router.param('userId', this.populateUserId.bind(this));

    router.get('/resolve', this.getResolveUser.bind(this));

    router.get('/:userId/picture', this.getUserPicture.bind(this));
    router.get('/:userId', this.getUserProfile.bind(this));

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

    return router;
  }

  async populateUserId (req, res, next, userId) {
    const { user: userService } = this.dtp.services;
    try {
      userId = mongoose.Types.ObjectId(userId);
      res.locals.userProfile = await userService.getUserProfile(userId);
      if (!res.locals.userProfile) {
        throw new SiteError(404, 'User profile not found');
      }
      res.locals.userProfile = userService.filterUserObject(res.locals.userProfile);
      res.locals.userProfile.picture.large.imageUri = `/image/${res.locals.userProfile.picture.large._id}`;
      res.locals.userProfile.picture.small.imageUri = `/image/${res.locals.userProfile.picture.small._id}`;
      return next();
    } catch (error) {
      this.log.error('failed to provide User profile', { userId, error });
      return res.status(error.statusCode || 500).json({ success: false, message: error.message });
    }
  }

  async getResolveUser (req, res) {
    const { user: userService } = this.dtp.services;
    res.locals.hiveView = 'resolve-user';

    try {
      if (!req.query.q || !req.query.q.length) {
        throw new SiteError(406, 'Must include search term');
      }

      res.locals.q = await userService.filterUsername(req.query.q);
      res.locals.pagination = this.getPaginationParameters(req, 20);
      res.locals.userProfiles = await userService.getUserAccounts(res.locals.pagination, res.locals.q);
      res.locals.userProfiles = res.locals.userProfiles.map((user) => {
        const apiUser = userService.filterUserObject(user);
        apiUser.picture.large = `/image/${user.picture.large}`;
        apiUser.picture.small = `/image/${user.picture.small}`;
        return apiUser;
      });

      res.status(200).json({
        success: true,
        pagination: res.locals.pagination,
        count: res.locals.userProfiles.length,
        params: {
          q: res.locals.q,
        },
        users: res.locals.userProfiles,
      });
    } catch (error) {
      this.log.error("failed to resolve user accounts", { error });
      res.status(error.statusCode || 500).json({ success: false, message: error.message });
    }
  }

  async getUserPicture (req, res) {
    const { hostCache: hostCacheService } = this.dtp.services;
    const image = res.locals.userProfile.picture[req.query.s || 'small'];

    res.locals.hiveView = 'user-picture';

    if (!image) {
      return res.status(404).end('Image not found');
    }

    try {
      const fileInfo = await hostCacheService.getFile(image.file.bucket, image.file.key);
      const stream = fs.createReadStream(fileInfo.file.path);
      res.header('Content-Type', image.type);
      res.header('Content-Length', fileInfo.file.stats.size);
      res.status(200);
      stream.pipe(res);
    } catch (error) {
      this.log.error('failed to fetch image', { image, error });
      return res.status(error.statusCode || 500).json({
        success: false,
        message: error.message,
      });
    }
  }

  async getUserProfile (req, res) {
    res.locals.hiveView = 'user-profile';
    res.status(200).json({
      success: true,
      user: res.locals.userProfile,
    });
  }

  async getCoreUserRoot (req, res) {
    res.locals.hiveView = 'info';
    res.status(200).json({
      component: this.component,
      version: this.dtp.pkg.version,
      services: this.services,
      methods: this.methods,
    });
  }
}

module.exports = {
  name: 'hiveUser',
  slug: 'hive-user',
  create: async (dtp) => {
    let controller = new HiveUserController(dtp);
    return controller;
  },
};