"use strict";

import {expect} from "chai"
import {RestAPI} from "../../../../../source/data/datasource/server/restapi.mjs";
import {validateObject} from "../../../../../source/types/validate.mjs";

describe('RestAPI', function () {

    let fetchReference;
    let returnStatus;
    let responseBody;

    afterEach(() => {
        globalThis['fetch'] = fetchReference;
    });

    beforeEach(() => {

        returnStatus = 200;
        responseBody = JSON.stringify({a: "test"});
        fetchReference = globalThis['fetch'];
        globalThis['fetch'] = function (options) {

            return new Promise((resolve, reject) => {
                resolve({
                    text: function () {
                        return new Promise((resolve, reject) => {
                            resolve(responseBody);
                        });
                    },
                    status: returnStatus
                });
            })

        };

    })

    it('should instance of RestAPI ', function () {
        expect(new RestAPI('https://monsterjs.org/assets/world.json')).to.be.instanceof(RestAPI)
    });

    describe('rw', function () {

        it('read should return object', function (done) {
            const ds = new RestAPI({url: 'https://monsterjs.org/assets/world.json'})
            ds.read().then(data => {
                validateObject(data);
                done();
            }).catch(e => done(e));
        });

        it('write should ', function (done) {
            const ds = new RestAPI({
                    read: {
                        url: 'https://monsterjs.org/assets/world.json'
                    },
                    write: {
                        url: 'https://monsterjs.org/assets/world.json',
                        acceptedStatus: [99]
                    }
                }
            )
            ds.write().then(data => {
                done("should not be here");
            }).catch(e => done());
        });
    });


    describe('rw with errors', function () {

        it('read should throw exception', function (done) {
            returnStatus = 400; // fetch response with 400

            const ds = new RestAPI({url: 'https://monsterjs.org/assets/world.json'})
            ds.read().then(data => {
                done("should not run.");
            }).catch(e => done()); // should throw exception because returnStatus=400
        });

        it('write should ', function (done) {
            returnStatus = 400; // fetch response with 400
            const ds = new RestAPI({url: 'https://monsterjs.org/assets/world.json'}, {url: 'https://monsterjs.org/assets/world.json'})
            ds.write().then(data => {
                validateObject(data);
                done("error");
            }).catch(e => done()); // should throw exception because returnStatus=400
        });


    })

    describe('read response parsing', function () {
        it('should reject on invalid json', function (done) {
            responseBody = "{invalid";
            const ds = new RestAPI({url: 'https://monsterjs.org/assets/world.json'})
            ds.read().then(() => {
                done("should not run.");
            }).catch(() => done());
        });

        it('should call responseCallback when provided', function (done) {
            let called = false;
            const ds = new RestAPI({
                read: {
                    url: 'https://monsterjs.org/assets/world.json',
                    responseCallback: () => {
                        called = true;
                    }
                }
            });
            ds.read().then(() => {
                expect(called).to.be.true;
                done();
            }).catch(e => done(e));
        });
    });

    describe('getClone', function () {
        it('should return an independent clone', function () {
            const ds = new RestAPI({
                read: {url: 'https://monsterjs.org/assets/world.json'},
                write: {url: 'https://monsterjs.org/assets/world.json'}
            });
            const clone = ds.getClone();
            clone.setOption('read.url', 'https://example.com/changed.json');
            expect(ds.getOption('read.url')).to.equal('https://monsterjs.org/assets/world.json');
        });
    });

})
