const { Controller } = require('libflitter')

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

    async get_providers(req, res, next) {
        const ServiceProvider = this.models.get('saml:ServiceProvider')
        const providers = await ServiceProvider.find({ active: true })

        const visible = providers.filter(x => req.user.can(`saml:provider:${x.id}:view`))
            .map(x => x.to_api())

        return res.api(visible)
    }

    async get_provider(req, res, next) {
        const ServiceProvider = this.models.get('saml:ServiceProvider')
        const provider = await ServiceProvider.findById(req.params.id)

        if ( !provider || !provider.active )
            return res.status(404).api()

        if ( !req.user.can(`saml:provider:${provider.id}:view`) )
            return res.status(401).api()

        return res.api(provider.to_api())
    }

    async create_provider(req, res, next) {
        const ServiceProvider = this.models.get('saml:ServiceProvider')
        const required_fields = ['name', 'entity_id', 'acs_url']
        for ( const field of required_fields ) {
            if ( !req.body[field]?.trim() )
                return res.status(400)
                    .message(`${req.T('api.missing_field')} ${field}`)
                    .api()
        }

        // The entity_id must be unique
        const existing_provider = await ServiceProvider.findOne({
            entity_id: req.body.entity_id,
            active: true,
        })

        if ( existing_provider )
            return res.status(400)
                .send(req.T('api.provider_already_exists'))
                .api()

        const data = {
            name: req.body.name,
            entity_id: req.body.entity_id,
            acs_url: req.body.acs_url,
            active: true,
        }

        if ( req.body.slo_url )
            data.slo_url = req.body.slo_url

        const provider = new ServiceProvider(data)
        await provider.save()

        req.user.allow(`saml:provider:${provider.id}`)
        await req.user.save()

        return res.api(provider.to_api())
    }

    async update_provider(req, res, next) {
        const ServiceProvider = this.models.get('saml:ServiceProvider')
        const provider = await ServiceProvider.findById(req.params.id)

        if ( !provider || !provider.active )
            return res.status(404).api()

        if ( !req.user.can(`saml:provider:${provider.id}:update`) )
            return res.status(401).api()

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

        // Make sure the entity_id won't cause a collision
        const duplicate_providers = await ServiceProvider.find({
            entity_id: req.body.entity_id,
            _id: { $ne: provider._id },
        })

        if ( duplicate_providers.length > 0 )
            return res.status(400)
                .message(api.T('api.provider_already_exists'))
                .api()

        // Update the record
        provider.name = req.body.name
        provider.entity_id = req.body.entity_id
        provider.acs_url = req.body.acs_url
        provider.slo_url = req.body.slo_url

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

    async delete_provider(req, res, next) {
        const ServiceProvider = this.models.get('saml:ServiceProvider')
        const provider = await ServiceProvider.findById(req.params.id)

        if ( !provider || !provider.active )
            return res.status(404).api()

        if ( !req.user.can(`saml:provider:${provider.id}:delete`) )
            return res.status(401).api()

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

module.exports = exports = SAMLController
