import { ApplicationService } from '@adonisjs/core/types';
// import { Database, DatabaseQueryBuilder } from '@adonisjs/lucid/database';
import { ModelQueryBuilder } from '@adonisjs/lucid/orm';
// import db from '@adonisjs/lucid/services/db';
import { LucidModel, LucidRow } from '@adonisjs/lucid/types/model';
import { ChainableContract, ExcutableQueryBuilderContract } from '@adonisjs/lucid/types/querybuilder';

import { ModelQueryBuilderContract } from '@adonisjs/lucid/types/model';
/*
|--------------------------------------------------------------------------
| Provider
|--------------------------------------------------------------------------
|
| Your application is not ready when this file is loaded by the framework.
| Hence, the top level imports relying on the IoC container will not work.
| You must import them inside the life-cycle methods defined inside
| the provider class.
|
| @example:
|
| public async ready () {
|   const Database = this.app.container.resolveBinding('Adonis/Lucid/Database')
|   const Event = this.app.container.resolveBinding('Adonis/Core/Event')
|   Event.on('db:query', Database.prettyPrint)
| }
|
*/
declare module '@adonisjs/lucid/types/model' {
    // interface ModelQueryBuilderContract<Model extends LucidModel, Result = InstanceType<Model>> {
    export interface ModelQueryBuilderContract<Model extends LucidModel, Result = InstanceType<Model>> extends ChainableContract, ExcutableQueryBuilderContract<Result[]> {
        // macro typescript definitions here
        // whereTrue(columnName: string): this;
        // whereFalse(columnName: string): this;
        // any(): Promise<boolean>;
        // selectCount(): Promise<BigInt>;
        // selectIds(primaryKey?: string): Promise<number[]>;
        // selectId(primaryKey?: string): Promise<number | undefined>;
        // selectIdOrFail(primaryKey?: string): Promise<number>;
        // pluck(valueColumn: string, id?: string): Promise<{ [key: string]: any }>;
        pluck<T extends LucidModel>(valueColumn: string, id?: string): Promise<{ [key: string]: any }>;
    }

    
}
declare module '@adonisjs/lucid/orm' {
   
    class ModelQueryBuilder extends Chainable implements ModelQueryBuilderContract<LucidModel, LucidRow> {
        public pluck(valueColumn: string, id?: string): Promise<{ [key: string]: any }>;
    }
}



export default class QueryBuilderProvider {
    constructor(protected app: ApplicationService) {}

    public register() {
        // Register your own bindings
    }

    public async boot() {
        // All bindings are ready, feel free to use them      
        // const db = await this.app.container.make('lucid.db');     

        ModelQueryBuilder.macro('pluck', async function (this: ModelQueryBuilder, valueColumn: string, id?: string) {
            // let rolesPluck = {};
            let rolesPluck: { [key: number]: any } = {};
            const result = await this.exec();
            result.forEach((user, index) => {
                let idc;
                if (!id) {
                    idc = index;
                } else {
                    idc = user[id];
                }
                const value = user[valueColumn];
                // rolesPluck[idc] = user.name;
                rolesPluck[idc] = value;
            });
            return rolesPluck;
        });

        // });

        //     validator.rule('foo', () => {})
    }

    public async ready() {
        // App is ready
    }

    public async shutdown() {
        // Cleanup, since app is going down
    }
}
