const { Controller } = require('libflitter')
const Validator = require('email-validator')
const path = require('path')

class ProfileController extends Controller {
    static get services() {
        return [...super.services, 'models', 'utility']
    }

    async fetch(req, res, next) {
        const User = this.models.get('auth:User')

        let user
        if ( req.params.user_id === 'me' ) user = req.user
        else { // if not me, verify that user can view profile
            if ( !req.user.can(`profile:view:${req.params.user_id}`) )
                return res.status(401).api()

            user = await User.findById(req.params.user_id)
        }

        return res.api({
            first_name: user.first_name,
            last_name: user.last_name,
            email: user.email,
            uid: user.uid,
            tagline: user.tagline || '',
            user_id: user.id,
            login_shell: user.login_shell || '',
            ...(user.notify_config ? { notify_config: await user.notify_config.to_api() } : {})
        })
    }

    async fetch_notify(req, res, next) {
        const User = this.models.get('auth:User')

        let user
        if ( req.params.user_id === 'me' ) user = req.user
        else { // If not me, verify that user can modify profile
            if ( !req.user.can(`profile:update:${req.params.user_id}`) )
                return res.status(401).api()

            user = await User.findById(req.params.user_id)
        }

        if ( !user )
            return res.status(404)
                .message(req.T('api.user_not_found'))
                .api()

        if ( user.notify_config ) {
            return res.api({
                has_config: true,
                config: await user.notify_config.to_api(),
            })
        } else {
            return res.api({
                has_config: false,
            })
        }
    }

    async test_notify(req, res, next) {
        const User = this.models.get('auth:User')

        let user
        if ( req.params.user_id === 'me' ) user = req.user
        else { // If not me, verify that user can modify profile
            if ( !req.user.can(`profile:update:${req.params.user_id}`) )
                return res.status(401).api()

            user = await User.findById(req.params.user_id)
        }

        if ( !user )
            return res.status(404)
                .message(req.T('api.user_not_found'))
                .api()

        if ( user.notify_config && user.notify_config.active ) {
            await user.notify_config.log({
                message: req.T('profile.test_notification'),
            })
        }

        return res.api()
    }

    async update_notify(req, res, next) {
        const User = this.models.get('auth:User')
        const NotifyConfig = this.models.get('system:NotifyConfig')

        let user
        if ( req.params.user_id === 'me' ) user = req.user
        else { // If not me, verify that user can modify profile
            if ( !req.user.can(`profile:update:${req.params.user_id}`) )
                return res.status(401).api()

            user = await User.findById(req.params.user_id)
        }

        if ( !user )
            return res.status(404)
                .message(req.T('api.user_not_found'))
                .api()

        if ( !user.notify_config ) {
            user.notify_config = new NotifyConfig({
                user_id: user.id,
                gateway_url: String(req.body.gateway_url),
                application_key: String(req.body.app_key),
                created_on: new Date,
                active: String(req.body.app_key) && String(req.body.gateway_url),
            }, user)
        } else {
            user.notify_config.application_key = String(req.body.app_key)
            user.notify_config.gateway_url = String(req.body.gateway_url)
            user.notify_config.active = String(req.body.app_key) && String(req.body.gateway_url)
        }

        await user.save()
        return res.api()
    }

    async update(req, res, next) {
        const User = this.models.get('auth:User')
        const Message = this.models.get('Message')
        const Setting = this.models.get('Setting')

        let user
        if ( req.params.user_id === 'me' ) user = req.user
        else { // If not me, verify that user can modify profile
            if ( !req.user.can(`profile:update:${req.params.user_id}`) )
                return res.status(401).api()

            user = await User.findById(req.params.user_id)
        }

        if ( !user )
            return res.status(404)
                .message(req.T('api.user_not_found'))
                .api()

        // Make sure the required fields are provided
        const required_fields = ['first_name', 'last_name', 'email']
        for ( const field of required_fields ) {
            if ( !req.body[field]?.trim() )
                return res.status(400)
                    .message(`${req.T('api.missing_field')} ${field}`)
                    .api()
        }

        // Validate the e-mail
        if ( !Validator.validate(req.body.email) )
            return res.status(400)
                .message(`${req.T('api.improper_field')} email ${req.T('api.email')}`)
                .api()

        // Update the user's profile
        if ( user.email !== req.body.email && (await Setting.get('auth.require_email_verify')) ) {
            await req.trap.begin('verify_email', { session_only: false })
            await Message.create(req.user, 'Your e-mail address has changed, and a verification e-mail has been sent. You must complete this process to continue.')
        }

        user.first_name = req.body.first_name
        user.last_name = req.body.last_name
        user.email = req.body.email
        user.tagline = req.body.tagline
        user.login_shell = req.body.login_shell

        // Save the record
        await user.save()
        return res.api({
            force_message_refresh: true,
        })
    }

    async update_photo(req, res, next) {
        const User = this.models.get('auth:User')
        let user
        if ( req.params.user_id === 'me' ) user = req.user
        else user = await User.findById(req.params.user_id)

        if ( !user )
            return res.status(404)
                .message(req.T('api.user_not_found'))
                .api()

        if ( !req?.uploads?.photo )
            return res.status(400)
                .message(`${req.T('api.missing_field')} file`)
                .api()

        user.photo_file_id = req.uploads.photo.id
        await user.save()
        return res.api()
    }

    async get_photo(req, res, next) {
        const User = this.models.get('auth:User')
        let user
        if ( req.params.user_id === 'me' ) user = req.user
        else user = await User.findById(req.params.user_id)

        if ( !user )
            return res.status(404)
                .message(req.T('api.user_not_found'))
                .api()

        const photo = await user.photo()
        if ( photo ) return photo.send(res)

        // The user does not have a profile. Send the default.
        return res.sendFile(this.utility.path('app/assets/people.png'))
    }

}

module.exports = exports = ProfileController
