const { Controller } = require('libflitter')
const is_absolute_url = require('is-absolute-url')

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

    async get_clients(req, res, next) {
        const Client = this.models.get('oauth:Client')
        const clients = await Client.find({ active: true })
        const data = []

        for ( const client of clients ) {
            if ( req.user.can(`oauth:client:${client.id}:view`) ) {
                data.push(await client.to_api())
            }
        }

        return res.api(data)
    }

    async get_client(req, res, next) {
        const Client = this.models.get('oauth:Client')
        const client = await Client.findById(req.params.id)

        if ( !client || !client.active )
            return res.status(404)
                .message(req.T('api.client_not_found'))
                .api()

        if ( !req.user.can(`oauth:client:${client.id}:view`) )
            return res.status(401)
                .message(req.T('api.insufficient_permissions'))
                .api()

        return res.api(await client.to_api())
    }

    async create_client(req, res, next) {
        if ( !req.user.can('oauth:client:create') )
            return res.status(401)
                .message(req.T('api.insufficient_permissions'))
                .api()

        const required_fields = ['name', 'api_scopes', 'redirect_url']
        for ( const field of required_fields ) {
            if ( !req.body[field] )
                return res.status(400)
                    .message(`${req.T('api.missing_field')} ${field}`)
                    .api()
        }

        if ( !Array.isArray(req.body.api_scopes) ) {
            return res.status(400)
                .message(`${req.T('api.improper_field')} api_scopes ${req.T('api.array')}`)
                .api()
        }

        if ( !is_absolute_url(req.body.redirect_url) )
            return res.status(400)
                .message(`${req.T('api.improper_field')} redirect_url ${req.T('api.absolute_url')}`)
                .api()

        const Client = this.models.get('oauth:Client')
        const client = new Client({
            name: req.body.name,
            api_scopes: req.body.api_scopes,
            redirect_url: req.body.redirect_url,
        })

        await client.save()
        return res.api(await client.to_api())
    }

    async update_client(req, res, next) {
        const Client = this.models.get('oauth:Client')
        const client = await Client.findById(req.params.id)

        if ( !client || !client.active )
            return res.status(404)
                .message(req.T('api.client_not_found'))
                .api()

        if ( !req.user.can(`oauth:client:${client.id}:update`) )
            return res.status(401)
                .message(req.T('api.insufficient_permissions'))
                .api()

        const required_fields = ['name', 'api_scopes', 'redirect_url']
        for ( const field of required_fields ) {
            if ( !req.body[field] )
                return res.status(400)
                    .message(`${req.T('api.missing_field')} ${field}`)
                    .api()
        }

        if ( !Array.isArray(req.body.api_scopes) )
            return res.status(400)
                .message(`${req.T('api.improper_field')} api_scopes ${req.T('api.array')}`)
                .api()

        if ( !is_absolute_url(req.body.redirect_url) )
            return res.status(400)
                .message(`${req.T('api.improper_field')} redirect_url ${req.T('api.absolute_url')}`)
                .api()

        client.name = req.body.name
        client.api_scopes = req.body.api_scopes
        client.redirect_url = req.body.redirect_url

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

    async delete_client(req, res, next) {
        const Client = this.models.get('oauth:Client')
        const client = await Client.findById(req.params.id)

        if ( !client || !client.active )
            return res.status(404)
                .message(req.T('api.client_not_found'))
                .api()

        if ( !req.user.can(`oauth:client:${client.id}:delete`) )
            return res.status(401)
                .message(req.T('api.insufficient_permissions'))
                .api()

        client.active = false
        await client.save()
        return res.api()
    }
}

module.exports = exports = OAuthController
