import { BaseCommand } from '@adonisjs/core/build/standalone';
import crypto from 'crypto';
import fs from 'fs';
// import Config from '@ioc:Adonis/Core/Config';
import Logger from '@ioc:Adonis/Core/Logger';

export default class ValidateChecksum extends BaseCommand {
    /**
     * Command name is used to run the command
     */
    public static commandName = 'validate:checksum';

    /**
     * Command description is displayed in the "help" output
     */
    public static description = '';

    public static settings = {
        /**
         * Set the following value to true, if you want to load the application
         * before running the command. Don't forget to call `node ace generate:manifest`
         * afterwards.
         */
        loadApp: true,

        /**
         * Set the following value to true, if you want this command to keep running until
         * you manually decide to exit the process. Don't forget to call
         * `node ace generate:manifest` afterwards.
         */
        stayAlive: false,
    };

    public async run() {
        // this.logger.info('Hello world!')
        const { default: File } = await import('App/Models/File');
        // const { default: HashValue } = await  (await (import ('App/Models/HashValue')));

        // query all files from database:
        const files = await File.query().preload('hashvalues');

        // const logLevel = Config.get('app.logger.level', 'info');
        // console.log(this.logger.)

        for (var file of files) {
            let hashValue = await file.related('hashvalues').query().pluck('value', 'type');

            const filePath = '/storage/app/public/' + file.pathName;
            let calculatedMd5FileHash;
            try {
                calculatedMd5FileHash = await this.checksumFile(filePath, 'md5');
            } catch (exception) {
                // this.logger.error(exception.message);
                Logger.error(exception.message);
                continue;
            }

            if (hashValue['md5'] === calculatedMd5FileHash) {
                Logger.info(`File id ${file.id}: stored md5 checksum: ${calculatedMd5FileHash}, control md5 checksum: ${hashValue['md5']}`);
            } else {
                Logger.error(
                    `File id ${file.id}: stored md5 checksum: ${calculatedMd5FileHash}, control md5 checksum: ${hashValue['md5']}`,
                );
            }
        }
    }

    private async checksumFile(path, hashName = 'md5'): Promise<string> {
        return new Promise((resolve, reject) => {
            const hash = crypto.createHash(hashName);
            const stream = fs.createReadStream(path);
            stream.on('error', (err) => reject(err));
            stream.on('data', (chunk) => hash.update(chunk));
            stream.on('end', () => resolve(hash.digest('hex')));
        });
    }
}
