import $j from './lib/jquery';
import { ApiResponse } from './types/api-response';
import FreyaSyncService from './freya-sync-service';

export default class SettingsValidator {
    private static instance: SettingsValidator;

    private constructor() {
        $j('#fssTestConfiguration').on('click', async () => {
            await this.testConfiguration();
        });
    }

    private updateResultLabel(status: boolean, message: string) {
        const verifyMessage = $j('.fss-verify-message');
        $j('.fss-verify-message > p').text(message);

        if (status) {
            verifyMessage.addClass('notice-success').removeClass('notice-error');
        } else {
            verifyMessage.addClass('notice-error').removeClass('notice-success');
        }

        verifyMessage.removeClass('hide-popup');
        $j('#fssTestConfiguration').prop('disabled', false);
        jQuery('html, body').animate({ scrollTop: 0 }, 'fast');
    }

    private async testConfiguration() {
        let apiUrl = FreyaSyncService.sharedInstance.data.api_url;
        if (apiUrl.charAt(apiUrl.length - 1) !== '/') {
            apiUrl = apiUrl.concat('/');
        }
        const url = apiUrl + 'api/wp/verifyPluginConfig';
        $j('#fssTestConfiguration').prop('disabled', true);
        const settings = FreyaSyncService.sharedInstance.settings;

        const data = {
            companyUid: settings.fsCompanyUid,
            defaultLocationUid: settings.fsDefaultLocationUid,
            hasPolygons: !settings.fsNoPolygons,
        };
        const verifyMessage = $j('.fss-verify-message');
        verifyMessage.removeClass('notice-error').removeClass('notice-success').addClass('hide-popup');

        const params = new URLSearchParams();
        params.set('companyUid', data.companyUid);
        params.set('defaultLocationUid', data.defaultLocationUid);
        params.set('hasPolygons', data.hasPolygons ? 'true' : 'false');

        return new Promise(async (resolve, reject) => {
            try {
                const r = await fetch(`${url}?${params.toString()}`, {
                    method: 'GET',
                    headers: {
                        'content-type': 'application/json',
                    },
                });
                const response = (await r.json()) as ApiResponse<any>;

                if (!r.ok) {
                    const message = this.getBadRequestMessage(r.status, response);
                    this.updateResultLabel(false, message);
                    return;
                }

                this.updateResultLabel(true, 'Setările s-au validat cu succes!');
            } catch (e) {
                this.updateResultLabel(
                    false,
                    'URL-ul de API este incorect, sau serviciul Freya Sync nu este disponibil momentan.'
                );
            }
        });
    }

    private getBadRequestMessage(statusCode: number, response: ApiResponse<any>) {
        switch (statusCode) {
            case 400:
                return `${response.message}`;
            case 422:
                return this.getValidationErrorMessage(response);
            case 500:
            default:
                return 'Serviciul Freya Sync a întâmpinat o eroare internă!';
        }
    }

    public static bootstrap() {
        if (this.instance) {
            return;
        }

        this.instance = new SettingsValidator();
    }

    public static get sharedInstance() {
        if (!this.instance) {
            throw new Error('No SettingsValidator instance');
        }

        return this.instance;
    }

    mapFieldToName(field: string) {
        switch (field) {
            case 'companyUid':
                return "'UID Companie'";
            case 'defaultLocationUid':
                return "'UID Locație default'";
            case 'hasPolygons':
                return "'Compania nu are poligoane'";
            default:
                return field;
        }
    }

    getValidationErrorMessage(response: ApiResponse<{ errors: Array<any> }>) {
        const errors = response.payload.errors ?? {};
        let fieldsWithError = '';
        const keys = Object.keys(errors);
        const count = keys.length;
        Object.keys(errors).forEach((key) => {
            fieldsWithError += `${this.mapFieldToName(key)}, `;
        });
        fieldsWithError = fieldsWithError.slice(0, -2);

        if (count > 1) {
            return `Campurile ${fieldsWithError} nu sunt completate`;
        }
        return `Campul ${fieldsWithError} nu este completat`;
    }
}
