import { Option } from 'commander';
import { PrettyPrint } from '../output/pretty_print.js';

export class Workflows {
    constructor(program, logger, services) {
        this.logger = logger;
        this.services = services;
        services["workflows"] = this;

        this.logger.debug('Workflows.constructor');

        // Récupérer les commandes existantes enregistrées par Admin
        const userCommand = program.commands.find(cmd => cmd.name() === 'user');
        const companyCommand = program.commands.find(cmd => cmd.name() === 'company');

        // --- user find <query> ---
        userCommand
            .command('find')
            .argument('<query>', 'search by displayName or loginEmail (auto-detected by @)')
            .description('Find a user by name or email and display details')
            .addOption(new Option('-j, --json', 'display raw JSON').conflicts('interactive'))
            .addOption(new Option('--interactive', 'show result in interactive display').conflicts('json'))
            .addOption(new Option('--format <format>', 'output format: small, medium or full (default: full)'))
            .action(async (query, options) => {
                this.services['telemetry'].sendTelemetry('user', 'find', '');
                try {
                    const user = await this.resolveUser(query);
                    if (options.interactive) {
                        this.services['interactive_display'].displayObjectNavigator(user);
                    } else {
                        PrettyPrint.display(user, undefined, options.json);
                    }
                } catch (error) {
                    PrettyPrint.error(error.message || error);
                }
            });

        // --- company find <query> ---
        companyCommand
            .command('find')
            .argument('<query>', 'search companies by name')
            .description('Find a company by name and display details')
            .addOption(new Option('-j, --json', 'display raw JSON').conflicts('interactive'))
            .addOption(new Option('--interactive', 'show result in interactive display').conflicts('json'))
            .addOption(new Option('--format <format>', 'output format: small, medium or full (default: full)'))
            .action(async (query, options) => {
                this.services['telemetry'].sendTelemetry('company', 'find', '');
                try {
                    const company = await this.resolveCompany(query);
                    if (options.interactive) {
                        this.services['interactive_display'].displayObjectNavigator(company);
                    } else {
                        PrettyPrint.display(company, undefined, options.json);
                    }
                } catch (error) {
                    PrettyPrint.error(error.message || error);
                }
            });

        // --- user company <query> ---
        userCommand
            .command('company')
            .argument('<query>', 'find user, then display their company')
            .description('Find a user and display their company details')
            .addOption(new Option('-j, --json', 'display raw JSON').conflicts('interactive'))
            .addOption(new Option('--interactive', 'show result in interactive display').conflicts('json'))
            .action(async (query, options) => {
                this.services['telemetry'].sendTelemetry('user', 'company', '');
                try {
                    const user = await this.resolveUser(query);
                    const companyId = user.data.companyId;
                    if (!companyId) {
                        PrettyPrint.error('User has no associated company');
                        return;
                    }
                    const company = await this.services["admin"].getCompany(companyId, {});
                    if (options.interactive) {
                        this.services['interactive_display'].displayObjectNavigator(company);
                    } else {
                        PrettyPrint.display(company, undefined, options.json);
                    }
                } catch (error) {
                    PrettyPrint.error(error.message || error);
                }
            });

        // --- user apps <query> ---
        userCommand
            .command('apps')
            .argument('<query>', 'find user, then list their applications')
            .description('Find a user and list their applications')
            .addOption(new Option('-j, --json', 'display raw JSON').conflicts('interactive'))
            .addOption(new Option('--interactive', 'show result in interactive display').conflicts('json'))
            .addOption(new Option('--columns <columns...>', 'filter columns to be displayed'))
            .action(async (query, options) => {
                this.services['telemetry'].sendTelemetry('user', 'apps', '');
                try {
                    const user = await this.resolveUser(query);
                    const userId = user.data.id;
                    const apps = await this.services["applications"].getApplications({ owner: userId });
                    if (options.interactive) {
                        this.services['interactive_display'].displayObjectNavigator(apps, 'applications', options);
                    } else {
                        PrettyPrint.display(apps, options.columns, options.json);
                    }
                } catch (error) {
                    PrettyPrint.error(error.message || error);
                }
            });
    }

    // --- Méthodes de résolution réutilisables ---

    async resolveUser(query) {
        this.logger.debug('Workflows.resolveUser');

        const isEmail = query.includes('@');
        const searchOptions = isEmail ? { email: query } : { name: query };

        const result = await this.services["admin"].getUsers(searchOptions);
        const users = result.data;

        if (!users || users.length === 0) {
            throw new Error(`No user found matching "${query}"`);
        }

        let selectedUserId;

        if (users.length === 1) {
            selectedUserId = users[0].id;
        } else {
            selectedUserId = await this._selectUser(users, query);
        }

        const userDetails = await this.services["admin"].getUser(selectedUserId, {});
        return userDetails;
    }

    async resolveCompany(query) {
        this.logger.debug('Workflows.resolveCompany');

        const result = await this.services["admin"].getCompanies({ name: query });
        const companies = result.data;

        if (!companies || companies.length === 0) {
            throw new Error(`No company found matching "${query}"`);
        }

        let selectedCompanyId;

        if (companies.length === 1) {
            selectedCompanyId = companies[0].id;
        } else {
            selectedCompanyId = await this._selectCompany(companies, query);
        }

        const companyDetails = await this.services["admin"].getCompany(selectedCompanyId, {});
        return companyDetails;
    }

    // Wrappers pour select() — import dynamique pour éviter le crash
    // sur Node < 21.7 (styleText) et permet de stubber dans les tests
    async _selectUser(users, query) {
        const { default: select } = await import('@inquirer/select');
        return await select({
            message: `Multiple users found for "${query}". Select one:`,
            choices: users.map(u => ({
                name: `${u.displayName} (${u.loginEmail})`,
                value: u.id
            }))
        });
    }

    async _selectCompany(companies, query) {
        const { default: select } = await import('@inquirer/select');
        return await select({
            message: `Multiple companies found for "${query}". Select one:`,
            choices: companies.map(c => ({
                name: c.name,
                value: c.id
            }))
        });
    }
}
