import MysqlConnectionManager from "../src/db/MysqlConnectionManager";
import Model from "../src/db/Model";
import Validator from "../src/db/Validator";
import {MIGRATIONS} from "./_migrations";

class FakeDummyModel extends Model {
    public name?: string;
    public date?: Date;
    public date_default?: Date;

    protected init(): void {
        this.addProperty<string>('name', new Validator().acceptUndefined().between(3, 256));
        this.addProperty<Date>('date', new Validator());
        this.addProperty<Date>('date_default', new Validator());
    }
}

beforeAll(async (done) => {
    MysqlConnectionManager.registerMigrations(MIGRATIONS);
    await MysqlConnectionManager.prepare();
    done();
});

afterAll(async (done) => {
    await MysqlConnectionManager.endPool();
    done();
});

describe('Model', () => {
    it('should have a proper table name', async () => {
        expect(FakeDummyModel.table).toBe('fake_dummy_models');
        expect(new FakeDummyModel({}).table).toBe('fake_dummy_models');
    });

    it('should insert and retrieve properly', async () => {
        await MysqlConnectionManager.query(`DROP TABLE IF EXISTS ${FakeDummyModel.table}`);
        await MysqlConnectionManager.query(`CREATE TABLE ${FakeDummyModel.table}(
            id INT NOT NULL AUTO_INCREMENT,
            name VARCHAR(256),
            date DATETIME,
            date_default DATETIME DEFAULT NOW(),
            PRIMARY KEY(id)
        )`);

        const date = new Date(569985);
        let instance: FakeDummyModel | null = new FakeDummyModel({
            name: 'name1',
            date: date,
        });

        await instance.save();
        expect(instance.id).toBe(1);
        expect(instance.name).toBe('name1');
        expect(instance.date?.getTime()).toBeCloseTo(date.getTime(), -4);
        expect(instance.date_default).toBeDefined();

        instance = await FakeDummyModel.getById(1);
        expect(instance).toBeDefined();
        expect(instance!.id).toBe(1);
        expect(instance!.name).toBe('name1');
        expect(instance!.date?.getTime()).toBeCloseTo(date.getTime(), -4);
        expect(instance!.date_default).toBeDefined();
    }, 15000);
});