package Cpanel::Easy::Apache::Utils::ArchiveRestore;

# cpanel - Cpanel/Easy/Apache/Utils/ArchiveRestore.pm
#                                                 Copyright(c) 2010 cPanel, Inc.
#                                                           All rights Reserved.
# copyright@cpanel.net                                         http://cpanel.net
# This code is subject to the cPanel license. Unauthorized copying is prohibited

sub run {
    my ( $easy, $coderef ) = @_;

    my @backups;

    if ( -d $easy->_get_backupdir() ) {
        push @backups, [ $easy->_get_backupdir(), 'Previous backup' ];
    }

    if ( -d $easy->_get_buildok_archivedir() ) {
        push @backups, [ $easy->_get_buildok_archivedir(), 'Archive of successful build with failed httpd.conf generation' ];

    }

    my $archive_dir = $easy->_get_backup_archivedir();
    if ( -d $archive_dir ) {
        for my $arch_bu ( map { File::Spec->catdir( $archive_dir, $_ ) } sort $easy->_list_backup_archivedir() ) {
            next if !-d $arch_bu;
            next if $arch_bu !~ m{ [/] \d{8} [.] \d+ \z}xms;
            push @backups, $arch_bu;
        }
    }

    my @backups_data;
    if (@backups) {
        my %days_seen;
        for my $bu (@backups) {

            my $path = '';
            my $name = '';

            if ( ref $bu eq 'ARRAY' ) {
                $path = $bu->[0];
                $name = $easy->maketext( $bu->[1] );
            }
            else {
                $path = $bu;
                my $bu_label = "Unkown: $path";
                if ( $path =~ m{ [/] (\d{4}) (\d{2}) (\d{2}) [.] (\d+) \z }xms ) {
                    require Cpanel::Time;
                    my ( undef, $time ) = split( /\s+/, Cpanel::Time::time2datetime($4) );
                    $bu_label = "$1-$2-$3 ${time}Z";    # ISO 8601 format

                    # $bu_label .= " [$days_seen{ $bu_label }]" if exists $days_seen{ $bu_label };

                    $days_seen{$bu_label}++;
                }
                $name = $easy->maketext( q{Build archived '[_1]'}, $bu_label );
            }

            push @backups_data, [ $path, $name ] if -d $path && $name;
        }

        my $path = '';
        if ( $easy->get_param('restore-archive') eq 'listonly' ) {
            print "Current archives:\n";
            for my $archive_ar (@backups_data) {
                print "[$archive_ar->[1]]\n\t$archive_ar->[0]\n\n";
            }
            $easy->_footer();
            exit;
        }
        elsif ( $easy->get_param('restore-archive') && $easy->get_param('restore-archive') ne '--restore-archive' ) {
            $path = $easy->get_param('restore-archive');
        }
        else {
            $path = $coderef->( $easy, \@backups_data );
        }

        if ( -d $path ) {
            $easy->print_alert( q{Attempting to restore '[_1]'}, $path );

            # add other checks ? allow some to be --force aware ?
            if ( !-x "$path/bin/httpd" || $path eq $easy->{'base_dir'} ) {
                $easy->print_alert(q{Sorry that does not appear to be a valid easyapache archive});
                $easy->_footer();
                exit;
            }

            # TEMPORARY FOR TESTING
            if ( !$easy->get_param('force') ) {
                $easy->print_alert(q{While this functionality is in BETA you must use --force to have it actually run the restore.});
                $easy->_footer();
                exit;
            }

            my $bu = 0;
            if ( $easy->_no_apache() ) {
                $easy->print_alert('Skipping backup, no working apache found');
            }
            else {
                $easy->_do_bu_file_move( { 'copy' => 1 } );
                $easy->print_alert('Backup of working apache complete.');
                $bu++;
            }

            local $easy->{'_'}{'restore_backup'} = 1;

            # is a copy not a move; does not do $path/conf
            my ( $rc, @err ) = $easy->_restore_backup_if_needed( 1, $path );
            @err = ( q{Could not restore '[_1]'}, $path ) if !@err;

            if ($rc) {
                my $archived_conf = "$path/conf/httpd.conf";
                $archived_conf = $easy->_get_main_httpd_conf() if !-e $archived_conf;

                if ( $easy->_httpd_conf_syntax_check_cmd($archived_conf) ) {
                    if ( $archived_conf ne $easy->_get_main_httpd_conf() ) {
                        my ( $ar, $mn ) = ( $archived_conf, $easy->_get_main_httpd_conf() );
                        if ( Cpanel::FileUtils::safecopy( $ar, $mn ) ) {
                            my @cmd = qw(/usr/local/cpanel/bin/apache_conf_distiller --update --reset --main);

                            my ( $rc, @err ) = $easy->run_system_cmd_returnable( \@cmd );
                            if ( !$rc ) {
                                $easy->print_alert(@err);
                                return;
                            }

                            if ( !$easy->_httpd_conf_syntax_check_cmd($mn) ) {
                                if ($bu) {
                                    local $easy->{'_'}{'restore_backup'} = 1;
                                    $easy->_restore_backup_if_needed(1);
                                }
                                else {
                                    $easy->print_alert('No backup to restore');
                                }
                                return;
                            }
                        }
                        else {
                            $easy->print_alert( q{Could not copy '[_1]' to '[_2]': [_3] - this will need done manually!}, $ar, $mn );
                            $easy->print_alert( q{Be sure to then run '[_1]'}, '/usr/local/cpanel/bin/apache_conf_distiller --update --reset --main' );
                        }
                    }

                    Cpanel::SafeDir::safermdir( $easy->_get_buildok_archivedir() );    # already restored so we don't need it

                    $easy->print_alert( q{'[_1]' has been restored}, $path );
                }
                else {
                    $easy->print_alert( q{'[_1]' is still invalid for '[_2]'}, $archived_conf, $path );
                    if ($bu) {
                        local $easy->{'_'}{'restore_backup'} = 1;
                        $easy->_restore_backup_if_needed(1);
                    }
                    else {
                        $easy->print_alert('No backup to restore');
                    }
                }
            }
            else {
                $easy->print_alert(@err);
            }
        }
        else {
            local $! = 20;
            $easy->print_alert( q{'[_1]': [_2]}, '--restore-archive', $! );
        }
    }
    else {
        $easy->print_alert(q{Currently there are no backups that can be restored.});
    }
}

1;
