import * as mime from 'mime';
import YAML from 'js-yaml';
import multer from 'multer';
import { format as formatDate } from 'date-fns';
import { Request, Response } from 'express';
import Controller from '../controller';
import { ADMIN } from '../../types/permissions';
import { extractUsername } from '../../util/extract-user';
import { IUnleashConfig } from '../../types/option';
import { IUnleashServices } from '../../types/services';
import { Logger } from '../../logger';
import StateService from '../../services/state-service';
import { IAuthRequest } from '../unleash-types';

const upload = multer({ limits: { fileSize: 5242880 } });
const paramToBool = (param, def) => {
    if (param === null || param === undefined) {
        return def;
    }
    const nu = Number.parseInt(param, 10);
    if (Number.isNaN(nu)) {
        return param.toLowerCase() === 'true';
    }
    return Boolean(nu);
};
class StateController extends Controller {
    private logger: Logger;

    private stateService: StateService;

    constructor(
        config: IUnleashConfig,
        { stateService }: Pick<IUnleashServices, 'stateService'>,
    ) {
        super(config);
        this.logger = config.getLogger('/admin-api/state.ts');
        this.stateService = stateService;
        this.fileupload('/import', upload.single('file'), this.import, ADMIN);
        this.post('/import', this.import, ADMIN);
        this.get('/export', this.export, ADMIN);
    }

    async import(req: IAuthRequest, res: Response): Promise<void> {
        const userName = extractUsername(req);
        const { drop, keep } = req.query;
        // TODO: Should override request type so file is a type on request
        let data;
        // @ts-ignore
        if (req.file) {
            // @ts-ignore
            if (mime.getType(req.file.originalname) === 'text/yaml') {
                // @ts-ignore
                data = YAML.load(req.file.buffer);
            } else {
                // @ts-ignore
                data = JSON.parse(req.file.buffer);
            }
        } else {
            data = req.body;
        }

        await this.stateService.import({
            data,
            userName,
            dropBeforeImport: paramToBool(drop, false),
            keepExisting: paramToBool(keep, true),
        });
        res.sendStatus(202);
    }

    async export(req: Request, res: Response): Promise<void> {
        const { format } = req.query;

        const downloadFile = paramToBool(req.query.download, false);
        const includeStrategies = paramToBool(req.query.strategies, true);
        const includeFeatureToggles = paramToBool(
            req.query.featureToggles,
            true,
        );
        const includeProjects = paramToBool(req.query.projects, true);
        const includeTags = paramToBool(req.query.tags, true);
        const includeEnvironments = paramToBool(req.query.environments, true);

        const data = await this.stateService.export({
            includeStrategies,
            includeFeatureToggles,
            includeProjects,
            includeTags,
            includeEnvironments,
        });
        const timestamp = formatDate(Date.now(), 'yyyy-MM-dd_HH-mm-ss');
        if (format === 'yaml') {
            if (downloadFile) {
                res.attachment(`export-${timestamp}.yml`);
            }
            res.type('yaml').send(YAML.dump(data, { skipInvalid: true }));
        } else {
            if (downloadFile) {
                res.attachment(`export-${timestamp}.json`);
            }
            res.json(data);
        }
    }
}
export default StateController;
