const {
    handleTextFeedback,
    handleFullName,
    handleMobileNumber,
    handleEmail,
    getAudioHandlers,
    getVideoHandlers,
    // makePhoto, // TODO: не уверен, что есть смысл тестить эту функцию, т.к. каждое каждое действие в функции должно быть покрыто моками
    // getMediaContent,
    submitData,
    initFeedbackModule,
    handleGrade,
    // clearRequestObject,
    // getRequestObject,
    feedbackEmitter
} = require("../dist/index");

afterEach(() => {
    jest.clearAllMocks();
})

describe("тест handleTextFeedback", () => {
    let spy;

    beforeEach(() => {
        jest.clearAllMocks();

        spy = jest.fn();

        feedbackEmitter.once("error", spy);
    })

    test("пустая строка", () => {
        handleTextFeedback("");

        expect(spy).toBeCalled();
    });

    test("непустая строка", () => {
        handleTextFeedback("text");

        expect(spy).not.toBeCalled();
    })
})

describe("тест handleFullName", () => {
    let spy;

    beforeEach(() => {
        jest.clearAllMocks();

        spy = jest.fn();

        feedbackEmitter.once("error", spy);
    })

    test("пустая строка", () => {
        handleFullName("");

        expect(spy).toBeCalled();
    })

    test("непустая строка", () => {
        handleFullName(" ");

        expect(spy).not.toBeCalled();
    })
})

describe("тест handleMobileNumber", () => {
    let message = undefined;
    let spy;

    beforeEach(() => {
        jest.clearAllMocks();

        message = undefined;

        spy = jest.fn((m) => message = m);

        feedbackEmitter.once("error", spy);
    })

    test("пустая строка", () => {
        handleMobileNumber("");

        expect(message).toStrictEqual("Mobile number value is empty");
    })

    test("0 (000) 000 00-00", () => {
        handleMobileNumber("0 (000) 000 00-00");

        expect(message).toStrictEqual("Mobile number is not valid");
    })

    test("8 (960) 265 86-25", () => {
        handleMobileNumber("8 (960) 265 86-25");

        expect(message).toBeUndefined();
    })

    test("Number(89602658625)", () => {
        handleMobileNumber(89602658625);

        expect(message).toBeUndefined();
    })

    test("String(89602658625)", () => {
        handleMobileNumber("89602658625");

        expect(message).toBeUndefined();
    })

    test("String(84952658625)", () => {
        handleMobileNumber("84952658625");

        expect(message).toBeUndefined();
    })
})

describe("тест handleEmail", () => {
    let message = undefined;
    let spy;

    beforeEach(() => {
        jest.clearAllMocks();

        message = undefined;

        spy = jest.fn((m) => message = m);

        feedbackEmitter.once("error", spy);
    })

    test("", () => {
        handleEmail("");

        expect(message).toStrictEqual("Email value is empty");
    })

    test("g@f", () => {
        handleEmail("g@f");

        expect(message).toStrictEqual("Email is not valid");
    })

    test("g@f.ru", () => {
        handleEmail("g@f.ru");

        expect(message).toBeUndefined();
    })

    test("g@.ru", () => {
        handleEmail("g@.ru");

        expect(message).toStrictEqual("Email is not valid");
    })

    test("g@.ru", () => {
        handleEmail("@c.ru");

        expect(message).toStrictEqual("Email is not valid");
    })

    test("g@.ru", () => {
        handleEmail("@.ru");

        expect(message).toStrictEqual("Email is not valid");
    })

    test("g@.ru", () => {
        handleEmail("g@fru");

        expect(message).toStrictEqual("Email is not valid");
    })
})

describe("тест getAudioHandlers", () => {
    const mediaRecorderSpies = {
        start: jest.fn(),
        stop: jest.fn(),
    }

    const mediaStreamSpy = {
        getAudioTracks: jest.fn(() => []),
        getTracks: jest.fn(() => [])
    }

    beforeEach(() => {
        Object.defineProperty(global, 'MediaRecorder', {
            writable: true,
            value: jest.fn().mockImplementation(() => ({
                ondataavailable: jest.fn(),
                audioBitrateMode: "variable",
                audioBitsPerSecond: 0,
                onerror: jest.fn(),
                onpause: jest.fn(),
                onresume: jest.fn(),
                mimeType: 'audio/webm',
                stream: global.MediaStream,
                state: "inactive",
                start: mediaRecorderSpies.start,
                stop: mediaRecorderSpies.stop,
                pause: jest.fn(),
                resume: jest.fn(),
                requestData: jest.fn(),
                addEventListener: jest.fn(),
                removeEventListener: jest.fn(),
                dispatchEvent: jest.fn(),
            })).mockName('MediaRecorder')
        })

        Object.defineProperty(MediaRecorder, 'isTypeSupported', {
            writable: true,
            value: () => true
        })
    })

    test("функция работает", () => {
        const controller = getAudioHandlers(mediaStreamSpy);

        expect(controller).toBeInstanceOf(Array);
    })

    test("первый обработчик", () => {
        const [start] = getAudioHandlers(mediaStreamSpy);

        start();

        expect(mediaRecorderSpies.start).toBeCalled();
    })

    test("второй обработчик", () => {
        const [, stop] = getAudioHandlers(mediaStreamSpy);

        stop();

        expect(mediaRecorderSpies.stop).toBeCalled();
    })

    test("третий обработчик", () => {
        const [, , stopTracks] = getAudioHandlers(mediaStreamSpy);

        stopTracks();

        expect(mediaStreamSpy.getTracks).toBeCalled();
    })
})

/** @todo */
describe("тест getVideoHandlers", () => {
    const mediaRecorderSpies = {
        start: jest.fn(),
        stop: jest.fn(),
    }

    const mediaStreamSpy = {
        getAudioTracks: jest.fn(() => []),
        getTracks: jest.fn(() => [])
    }

    beforeEach(() => {
        Object.defineProperty(global, 'MediaRecorder', {
            writable: true,
            value: jest.fn().mockImplementation(() => ({
                ondataavailable: jest.fn(),
                audioBitrateMode: "variable",
                audioBitsPerSecond: 0,
                onerror: jest.fn(),
                onpause: jest.fn(),
                onresume: jest.fn(),
                mimeType: 'audio/webm',
                stream: global.MediaStream,
                state: "inactive",
                start: mediaRecorderSpies.start,
                stop: mediaRecorderSpies.stop,
                pause: jest.fn(),
                resume: jest.fn(),
                requestData: jest.fn(),
                addEventListener: jest.fn(),
                removeEventListener: jest.fn(),
                dispatchEvent: jest.fn(),
            })).mockName('MediaRecorder')
        })

        Object.defineProperty(MediaRecorder, 'isTypeSupported', {
            writable: true,
            value: () => true
        })
    })

    test("функция работает", () => {
        const controller = getVideoHandlers(mediaStreamSpy);

        expect(controller).toBeInstanceOf(Array);
    })

    test("первый обработчик", () => {
        const [start] = getVideoHandlers(mediaStreamSpy);

        start();

        expect(mediaRecorderSpies.start).toBeCalled();
    })

    test("второй обработчик", () => {
        const [, stop] = getVideoHandlers(mediaStreamSpy);

        stop();

        expect(mediaRecorderSpies.stop).toBeCalled();
    })

    test("третий обработчик", () => {
        const [, , stopTracks] = getAudioHandlers(mediaStreamSpy);

        stopTracks();

        expect(mediaStreamSpy.getTracks).toBeCalled();
    })
})

describe("тест submitData", () => {
    const fetchSpy = jest.fn();

    Object.defineProperty(global, "fetch", {
        writable: true,
        value: fetchSpy
    });

    test("функция работает", () => {
        submitData()

        expect(fetchSpy).toBeCalled();
    })
})

describe("тест initFeedbackModule", () => {
    let spy;

    beforeEach(() => {
        jest.clearAllMocks();

        spy = jest.fn();

        feedbackEmitter.once("error", spy);
    })

    test("без аргумента host", () => {
        initFeedbackModule();

        expect(spy).toBeCalled();
    })

    test("некорректный аргумент rotation", () => {
        initFeedbackModule("localhost", 473, "", NaN);

        expect(spy).toBeCalled();
    })

    test("Все аргументы нормальные", () => {
        initFeedbackModule("localhost");

        expect(spy).not.toBeCalled();
    })
})

describe("тест handleGrade", () => {
    let spy;

    beforeEach(() => {
        jest.clearAllMocks();

        spy = jest.fn();

        feedbackEmitter.once("error", spy);
    })

    test("grade = 6, maxGrade = undefined(5 по умолчанию)", () => {
        handleGrade(6);

        expect(spy).toBeCalled();
    })

    test("grade = 6, maxGrade = -1", () => {
        handleGrade(6, -1);

        expect(spy).toBeCalled();
    })

    test("grade = 4, maxGrade = 5", () => {
        handleGrade(4, 5);

        expect(spy).not.toBeCalled();
    })
})
