import CommanderCommand       from '../../CommanderCommand.js';
import inquirer               from 'inquirer';
import SessionManager         from '../../../managers/SessionManager.js';
import ora                    from 'ora';
import DojoBackendManager     from '../../../managers/DojoBackendManager.js';
import Assignment             from '../../../sharedByClients/models/Assignment.js';
import SharedAssignmentHelper from '../../../shared/helpers/Dojo/SharedAssignmentHelper.js';
import TextStyle              from '../../../types/TextStyle.js';


abstract class AssignmentPublishUnpublishCommandBase extends CommanderCommand {
    protected abstract publish: boolean;

    protected defineCommand() {
        this.command
            .description(`${ this.publish ? 'publish' : 'unpublish' } an assignment`)
            .argument('<name or url>', 'name or url (http/s or ssh) of the assignment')
            .option('-f, --force', 'don\'t ask for confirmation')
            .action(this.commandAction.bind(this));
    }

    protected async commandAction(assignmentNameOrUrl: string, options: { force: boolean }): Promise<void> {
        if ( !options.force ) {
            options.force = (await inquirer.prompt({
                                                       type   : 'confirm',
                                                       name   : 'force',
                                                       message: this.publish ? 'Are you sure you want to publish this assignment?' : 'Are you sure you want to unpublish this assignment?'
                                                   })).force;
        }

        if ( !options.force ) {
            return;
        }

        let assignment!: Assignment | undefined;

        {
            console.log(TextStyle.BLOCK('Please wait while we verify and retrieve data...'));

            if ( !await SessionManager.testSession(true, null) ) {
                return;
            }

            ora('Checking assignment:').start().info();
            ora({
                    text  : assignmentNameOrUrl,
                    indent: 4
                }).start().info();
            const assignmentGetSpinner: ora.Ora = ora({
                                                          text  : 'Checking if assignment exists',
                                                          indent: 8
                                                      }).start();
            assignment = await DojoBackendManager.getAssignment(assignmentNameOrUrl);
            if ( !assignment ) {
                assignmentGetSpinner.fail(`The assignment doesn't exists`);
                return;
            }
            assignmentGetSpinner.succeed(`The assignment exists`);


            const assignmentCheckAccessSpinner: ora.Ora = ora({
                                                                  text  : 'Checking accesses',
                                                                  indent: 8
                                                              }).start();
            if ( !assignment.staff.some(staff => staff.id === SessionManager.profile?.id) ) {
                assignmentCheckAccessSpinner.fail(`You are not in the staff of this assignment`);
                return;
            }
            assignmentCheckAccessSpinner.succeed(`You are in the staff of this assignment`);


            const assignmentIsPublishable: ora.Ora = ora({
                                                             text  : 'Checking if the assignment is publishable',
                                                             indent: 8
                                                         }).start();
            const isPublishable = await SharedAssignmentHelper.isPublishable(assignment.gitlabId);
            if ( !isPublishable.isPublishable ) {
                assignmentIsPublishable.fail(`The assignment is not publishable: ${ isPublishable.status?.message }`);
                return;
            }
            assignmentIsPublishable.succeed(`The assignment is publishable`);
        }

        {
            console.log(TextStyle.BLOCK(`Please wait while we ${ this.publish ? 'publish' : 'unpublish' } the assignment...`));

            try {
                await DojoBackendManager.changeAssignmentPublishedStatus(assignment, this.publish);
            } catch ( error ) {
                return;
            }
        }
    }
}


export default AssignmentPublishUnpublishCommandBase;