#!/usr/local/cpanel/3rdparty/bin/perl -w

#                                      Copyright 2025 WebPros International, LLC
#                                                           All rights reserved.
# copyright@cpanel.net                                         http://cpanel.net
# This code is subject to the cPanel license. Unauthorized copying is prohibited

package t::medium::retry_domain_migration_sitejet_plugin;

use cPstrict;

use Test2::V0 -no_utf8 => 1;
use Test2::Tools::Explain;
use Test2::Plugin::NoWarnings;
use Test2::Tools::Exception qw/dies/;

use Test::MockFile;
use Test::MockObject;

use Test::Cpanel::Policy;

# must go below T:C:Policy
use Mock::Cpanel::Logger;

use parent qw(
  Cpanel::TestObj
);

use Cpanel();

our @stack;

BEGIN {
    *CORE::GLOBAL::chdir = sub { push @stack, "chdir $_[0]" };
}

require "/usr/local/cpanel/plugins/cpanel/sitejet/plugin/scripts/retry_domain_migration.pl";
$INC{'/usr/local/cpanel/plugins/cpanel/sitejet/plugin/scripts/retry_domain_migration.pl'} = __PACKAGE__;

my $valid_yaml = <<~'EOF';
    username: testuser
    old_domain: example.com
    new_domain: newexample.com
    exception: File Locked
    timestamp: 20250722_143001
    created_by: Cpanel::Sitejet::Hooks::ChangeDomains
    EOF

__PACKAGE__->new()->runtests() if !caller;

#----------------------------------------------------------------------

#e.g., num_method_tests()
sub new ( $class, @args ) {
    my $self = $class->SUPER::new(@args);
    return $self;
}

#e.g., set environs before running tests
sub runtests ( $self, @args ) {
    return $self->SUPER::runtests(@args);
}

sub test__load_config : Tests(4) ($self) {

    # Create mock path for our config files
    my $valid_config_path = '/home/user/tmp/sitejet_migration_domain.tld.failed.yaml';
    my $empty_config_path = '/home/user/tmp/sitejet_migration_empty.failed.yaml';

    # Create mock file with valid YAML content
    my $mock_valid_file = Test::MockFile->file( $valid_config_path, $valid_yaml );
    my $mock_empty_file = Test::MockFile->file( $empty_config_path, 'this is a text file' );

    # Test loading a valid config file
    my $valid_config;
    ok(
        lives {
            $valid_config = plugin::retry_domain_migration::_load_config($valid_config_path);
        },
        'Loading valid config file does not die'
    );

    # Check that we got back the expected data
    is(
        $valid_config,
        {
            username   => 'testuser',
            old_domain => 'example.com',
            new_domain => 'newexample.com',
            exception  => 'File Locked',
            timestamp  => '20250722_143001',
            created_by => 'Cpanel::Sitejet::Hooks::ChangeDomains',
        },
        'Config contains expected data'
    );

    Common::YAML::clear_cache();

    # Test loading an empty config file
    like(
        dies {
            plugin::retry_domain_migration::_load_config($empty_config_path);
        },
        qr/Invalid config file format/,
        'Loading empty config file dies with expected error'
    );

    # Test loading a non-existent file
    like(
        dies {
            plugin::retry_domain_migration::_load_config(undef);
        },
        qr/Please provide a config file path/,
        'Loading non-existent config file dies with expected error'
    );

    Common::YAML::clear_cache();

}

sub test_run_with_valid_config : Tests(2) ($self) {
    my $valid_config_path = '/home/user/tmp/sitejet_migration_domain.tld.failed.yaml';
    my $mock_valid_file   = Test::MockFile->file( $valid_config_path, $valid_yaml );
    my $homedir           = '/home/testuser';

    my @mocks = $self->mock_subs(
        'Cpanel::AccessIds::do_as_user_with_exception' => sub ( $user, $code ) {
            return $code->();
        },
        'Cpanel::Sitejet::MoveWebsite::new' => sub ( $self, $old_domain, $new_domain ) {
            return bless {
                old_domain => $old_domain,
                new_domain => $new_domain,
                connector  => undef,
              },
              'Cpanel::Sitejet::MoveWebsite';
        },
        'Cpanel::Sitejet::MoveWebsite::run' => sub {
            my $self = shift;
            return 1;    # Simulate successful run
        },
        'Cpanel::PwCache::gethomedir' => sub ($user) {
            return $homedir;
        },
        'Cpanel::HelpfulScript::getopt' => sub {
            my ( $self, $option ) = @_;
            if ( $option eq 'config' ) {
                return $valid_config_path;
            }
            return undef;
        },
        'Cpanel::HelpfulScript::full_help' => sub {
            return 'Help message';
        },
        'Cpanel::Sitejet::Hooks::ChangeDomains::_create_failure_memento' => sub {
            my @args = @_;
            return 1;
        }
    );

    my $mock_homedir = Test::MockFile->new_dir($homedir);
    push @mocks, $mock_homedir;
    my $script_obj = plugin::retry_domain_migration->new();

    # Test successful run
    ok(
        lives {
            plugin::retry_domain_migration::run($script_obj);
        },
        'Run method completes successfully'
    );

    my $got_messages = Mock::Cpanel::Logger::get_messages('info');

    like(
        $got_messages->[0]{message},
        qr/Moved website data successfully/,
        'Run method logs success message'
    ) or diag explain $got_messages;

    Mock::Cpanel::Logger::clear_all();
    Common::YAML::clear_cache();

}

sub test_run_with_migration_with_runtime_failure : Tests(2) ($self) {
    my $invalid_config_path = '/home/user/tmp/sitejet_migration_domain.tld.failed.yaml';
    my $mock_invalid_file   = Test::MockFile->file( $invalid_config_path, $valid_yaml );
    my $homedir             = '/home/testuser';

    my @mocks = $self->mock_subs(
        'Cpanel::AccessIds::do_as_user_with_exception' => sub ( $user, $code ) {
            return $code->();
        },
        'Cpanel::Sitejet::MoveWebsite::new' => sub ( $self, $old_domain, $new_domain ) {
            return bless {
                old_domain => $old_domain,
                new_domain => $new_domain,
                connector  => undef,
              },
              'Cpanel::Sitejet::MoveWebsite';
        },
        'Cpanel::Sitejet::MoveWebsite::run' => sub {
            my $self = shift;
            return 0;    # Simulate failed run
        },
        'Cpanel::PwCache::gethomedir' => sub ($user) {
            return $homedir;
        },
        'Cpanel::HelpfulScript::getopt' => sub {
            my ( $self, $option ) = @_;
            if ( $option eq 'config' ) {
                return $invalid_config_path;
            }
            return undef;
        },
        'Cpanel::HelpfulScript::full_help' => sub {
            return 'Help message';
        },
        'Cpanel::Sitejet::Hooks::ChangeDomains::_create_failure_memento' => sub {
            my @args = @_;
            return 1;
        }
    );
    my $mock_homedir = Test::MockFile->new_dir($homedir);
    push @mocks, $mock_homedir;

    my $script_obj = plugin::retry_domain_migration->new();

    # Test failed run
    ok(
        lives {
            # This should report an error because the migration failed
            plugin::retry_domain_migration::run($script_obj);
        },
        'Run method lives with internal failure.'
    );

    my $got_errors = Mock::Cpanel::Logger::get_messages('error');

    like(
        $got_errors->[0]{message},
        qr/Failed to migrate/,
        'Run method logs errors'
    ) or diag explain $got_errors;

    Mock::Cpanel::Logger::clear_all();

    Common::YAML::clear_cache();

}

sub test_run_with_args : Tests(3) ($self) {
    my $username;
    my $old_domain;
    my $new_domain;
    my $homedir = '/home/testuser';

    my @mocks = $self->mock_subs(
        'Cpanel::AccessIds::do_as_user_with_exception' => sub ( $user, $code ) {
            return $code->();
        },
        'Cpanel::Sitejet::MoveWebsite::new' => sub ( $self, $old_domain, $new_domain ) {
            return bless {
                old_domain => $old_domain,
                new_domain => $new_domain,
                connector  => undef,
              },
              'Cpanel::Sitejet::MoveWebsite';
        },
        'Cpanel::Sitejet::MoveWebsite::run' => sub {
            my $self = shift;
            return 1;    # Simulate successful run
        },
        'Cpanel::PwCache::gethomedir' => sub ($user) {
            return $homedir;
        },
        'Cpanel::HelpfulScript::getopt' => sub {
            my ( $self, $option ) = @_;
            if ( $option eq 'username' ) {
                return $username;
            }
            elsif ( $option eq 'old_domain' ) {
                return $old_domain;
            }
            elsif ( $option eq 'new_domain' ) {
                return $new_domain;
            }

            return undef;
        },
        'Cpanel::HelpfulScript::full_help' => sub {
            return 'Help message';
        },
        'Cpanel::Sitejet::Hooks::ChangeDomains::_create_failure_memento' => sub {
            my @args = @_;
            return 1;
        }
    );
    my $mock_homedir = Test::MockFile->new_dir($homedir);
    push @mocks, $mock_homedir;

    my $script_obj = plugin::retry_domain_migration->new();

    # Test failing run
    like(
        dies {
            plugin::retry_domain_migration::run($script_obj);
        },
        qr/Help message/,
        'Run method dies with expected error when parameters are undefined'
    );

    $username   = 'testuser';
    $old_domain = 'example.com';
    $new_domain = 'newexample.com';

    # Test successful run
    ok(
        lives {
            plugin::retry_domain_migration::run($script_obj);
        },
        'Run method completes successfully'
    );

    my $got_messages = Mock::Cpanel::Logger::get_messages('info');

    like(
        $got_messages->[0]{message},
        qr/Moved website data successfully/,
        'Run method logs success message'
    ) or diag explain $got_messages;

    Mock::Cpanel::Logger::clear_all();
    Common::YAML::clear_cache();

}

1;
