import axios, { type AxiosRequestConfig } from 'axios';
import MockAdapter from 'axios-mock-adapter';
import { HeaptraderAPI } from './api';
import { expect, jest, test } from '@jest/globals';
import type { User } from './models';

class HeaptraderAPITest extends HeaptraderAPI
{
    public _mock: MockAdapter;
    public _fakeXsrf: string;
    public _mockUser: User;

    constructor()
    {
        super("");
        this._mock = new MockAdapter(axios);
        this._fakeXsrf = "asdfghjkl";
        this._mockUser = {
            "id": 1,
            "name": "Admin",
            "email": "board@ucla.edu",
            "email_verified_at": "2025-11-05T20:05:42.000000Z",
            "created_at": "2025-11-04T18:57:35.000000Z",
            "updated_at": "2025-11-05T20:05:44.000000Z",
            "two_factor_confirmed_at": null
        };
        this.setupMockResponses();
    }

    setupMockResponses(): void
    {
        this._mock.onGet("/up").reply(200, {});

        // TODO: see if there's a way to actually return an xsrf cookie, get mock Axios to use it
        this._mock.onGet("/sanctum/csrf-cookie").reply(204);
        
        this._mock.onPost("/login").reply((config: AxiosRequestConfig) => {
            if (config.data.password === 'opensesame')
            {
                return {
                    status: 200,
                    data: {"two_factor": false}
                };
            }
            else
            {
                return {
                    status: 422,
                    data: {
                        "message": "These credentials do not match our records.",
                        "errors": {
                            "email": [
                                "These credentials do not match our records."
                            ]
                        }
                    }
                };
            }
            // TODO: simulate 419 error from no CSRF cookie
        });

        this._mock.onGet("/api/user").reply(200, this._mockUser);
    }
}

test('check uptime', async () => {
    const api = new HeaptraderAPITest();
    const success = await api.heartbeat();
    expect(success).toBe(true);
});

test('requests CSRF cookie before login attempts', async () => {
    const api = new HeaptraderAPITest();
    await api.login({
        email: "board@linux.ucla.edu",
        password: "password123"
    });
    expect(api._mock.history[0].method).toMatch(/GET/i);
    expect(api._mock.history[0].url).toBe("/sanctum/csrf-cookie");
});

test('login attempt with correct credentials', async () => {
    const api = new HeaptraderAPITest();
    const success = await api.login({
        email: "board@linux.ucla.edu",
        password: "opensesame"
    });
    expect(success).toBe(true);
});

test('login attempt with wrong credentials', async () => {
    const api = new HeaptraderAPITest();
    const success = await api.login({
        email: "board@linux.ucla.edu",
        password: "sneed"
    });
    expect(success).toBe(false);
});

test('gets user info', async () => {
    const api = new HeaptraderAPITest();
    expect(await api.user()).toEqual(api._mockUser);
});
