/* eslint-disable unicorn/prefer-module */
/*
 * Copyright (C) 2019 StApps
 * This program is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <https://www.gnu.org/licenses/>.
 */
import {Logger} from '@openstapps/logger';
import {expect} from 'chai';
import {existsSync} from 'fs';
import {JSONSchema7 as Schema} from 'json-schema';
import {Foo} from '../src/resources/foo.js';
import {Validator} from '../src/validate.js';
import path from 'path';
import {fileURLToPath} from 'url';
import {rm, mkdir, writeFile} from 'fs/promises';
import {Converter} from '../src/index.js';

process.on('unhandledRejection', (error: unknown) => {
  if (error instanceof Error) {
    void Logger.error('UNHANDLED REJECTION', error.stack);
  }
  process.exit(1);
});

const tmpdir = path.join(path.dirname(fileURLToPath(import.meta.url)), 'tmp');
const fooInstance: Foo = {
  lorem: 'ipsum',
  type: 'Foo',
};

describe('Validator', function () {
  this.timeout(40_000);
  this.slow(5000);

  let schema: Schema;
  let converter: Converter;

  beforeEach(async function () {
    converter = new Converter(
      path.join(path.dirname(fileURLToPath(import.meta.url)), '..', 'src', 'resources'),
    );
    schema = converter.getSchema('Foo', '0.0.1');
    if (!existsSync(tmpdir)) {
      await mkdir(tmpdir);
    }
    await writeFile(path.join(tmpdir, 'SCFoo.json'), JSON.stringify(schema, undefined, 2));
  });

  afterEach(async function () {
    try {
      await rm(tmpdir, {recursive: true});
    } catch (error) {
      expect(error, `Unable to remove temporary directory for tests at: ${tmpdir}`).to.be.null;
    }
  });

  it('should validate by schema identifying string', async function () {
    const validator = new Validator();
    await validator.addSchemas(tmpdir);
    const validationResult = validator.validate(fooInstance, 'SCFoo');
    expect(validationResult.errors, JSON.stringify(validationResult.errors, undefined, 2)).to.be.empty;
  });

  it('should validate by schema instance', async function () {
    const validator = new Validator();
    const validationResult = validator.validate(fooInstance, schema);
    expect(validationResult.errors, JSON.stringify(validationResult.errors, undefined, 2)).to.be.empty;
  });

  it('should validate intrinsic', async function () {
    const validator = new Validator();
    await validator.addSchemas(tmpdir);
    const validationResult = validator.validate(fooInstance);
    expect(validationResult.errors, JSON.stringify(validationResult.errors, undefined, 2)).to.be.empty;
  });
});
