#                                      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 Cpanel::Koality::Hooks::ChangeDomains;

use cPstrict;

use Cpanel::Imports;

use parent 'Cpanel::Hooks::ChangeDomains';
use constant NAME => 'Koality';

=encoding utf-8

=head1 NAME

Cpanel::Koality::Hooks::ChangeDomains - Koality-specific domain change operations

=head1 DESCRIPTION

This module provides Koality-specific domain change operations including API
notifications to the Koality service when domain changes occur. It inherits from
Cpanel::Hooks::ChangeDomains and registers its own hooks independently.

The module handles lightweight API calls to notify the Koality service of domain
changes, ensuring external service synchronization during domain transitions.

=head1 SYNOPSIS

This module inherits from Cpanel::Hooks::ChangeDomains and registers its own hooks.
It implements the standard service interface:

    my ($result, $message) = Cpanel::Koality::Hooks::ChangeDomains->change_domain(
        $user, $old_domain, $new_domain, $context
    );

=head1 STATIC METHODS

=head2 get_instance()

Returns a singleton instance of the Koality domain change handler.
This ensures consistent state across multiple hook invocations and provides
service-specific cache isolation.

=over 4

=item B<Returns:>

Singleton instance of Cpanel::Koality::Hooks::ChangeDomains with 'koality' service identifier

=back

=cut

my $instance = undef;

sub get_instance {
    if ( !$instance ) {
        $instance = __PACKAGE__->new(NAME);
    }
    return $instance;
}

=head2 describe()

Returns an array reference of hook descriptors that define when and how
this module's hooks should be executed by the cPanel hook system.

=over 4

=item B<Parameters:>

None.

=item B<Returns:>

Array reference containing hook configuration hashes for Koality domain change operations.

=back

=cut

sub describe {
    return get_instance()->register(NAME);
}

=head2 capture_domain_before_change($context, $data)

Static hook handler that delegates to the singleton instance's parent method.
This is the entry point called by the cPanel hook system.

=cut

sub capture_domain_before_change {
    return get_instance()->SUPER::capture_domain_before_change(@_);
}

=head2 check_for_domain_change($context, $data)

Static hook handler that delegates to the singleton instance's parent method.
This is the entry point called by the cPanel hook system for post-domain-change processing.

=cut

sub check_for_domain_change {
    return get_instance()->SUPER::check_for_domain_change(@_);
}

=head2 uapi_domain_change($context, $data)

Static hook handler that delegates to the singleton instance's parent method.
This is the entry point called by the cPanel hook system for UAPI domain changes.

=cut

sub uapi_domain_change {
    return get_instance()->SUPER::uapi_domain_change(@_);
}

=head1 INSTANCE METHODS


=head2 change_domain($self, $user, $old_domain, $new_domain, $is_whmapi)

Performs Koality-specific domain change operations including API notifications.

=over 4

=item B<Parameters:>

=over 4

=item * C<$user> - String. The cPanel username.

=item * C<$old_domain> - String. The original domain name.

=item * C<$new_domain> - String. The new domain name.

=item * C<$is_whmapi> - Optional string. When set to 'whmapi', error messages will reference the error log instead of suggesting to contact the hosting provider. Defaults to undef.

=back

=item B<Returns:>

A two-element list: C<($result, $message)>

=over 4

=item * C<$result> - Boolean indicating success (true) or failure (false/undef).

=item * C<$message> - String containing either a success message or error message.

=back

On success, returns the result from the API operation and a success message.
On failure, returns undef/false and an error message suitable for display to users.

=item B<Side Effects:>

Makes API calls to the Koality service to notify of domain changes.

Error message format varies based on the C<$is_whmapi> parameter:
- When C<$is_whmapi> is 'whmapi': Error messages reference the error log for troubleshooting
- When C<$is_whmapi> is undef/other: Error messages suggest contacting the hosting provider

=item B<Examples:>

    # Standard usage (called by framework)
    my ($result, $message) = Cpanel::Koality::Hooks::ChangeDomains->change_domain('username', 'old.com', 'new.com');

    # WHM API usage (provides different error messages)
    my ($result, $message) = Cpanel::Koality::Hooks::ChangeDomains->change_domain('username', 'old.com', 'new.com', 'whmapi');

=back

=cut

sub change_domain( $self, $user, $old_domain, $new_domain, $is_whmapi = undef ) {

    logger->info("Site Quality Monitoring domain change requested: user='$user', old='$old_domain', new='$new_domain'");

    # Create the closure for the api call.
    my $do_change_domain = sub {

        # Update nvdata if it still matches the old domain
        # but don't let this block the rest of the process if it fails
        eval {
            require Cpanel::NVData;
            if ( Cpanel::NVData::_get("koalitySignupDomain") eq $old_domain ) {
                logger->info("Updating koalitySignupDomain nvdata for user '$user' from '$old_domain' to '$new_domain'.");
                Cpanel::NVData::_set( "koalitySignupDomain", $new_domain );
            }
        };
        if ($@) {
            logger->warn("Failed to update koalitySignupDomain nvdata for user: '$user' due to the exception: $@");
        }

        require Cpanel::Koality::User;
        my $the_user = Cpanel::Koality::User->new( cpanel_username => $user );

        # Check if user has finished setting up their account in Koality
        if ( !$the_user->user_config->{enabled} ) {
            return 0;    # User hasn't completed Koality account setup
        }

        require Cpanel::API;
        my $response = Cpanel::API::execute(
            "SiteQuality",
            "update_domain",
            {
                old_domain => $old_domain,
                new_domain => $new_domain,
            }
        );

        if ( !$response->status() ) {
            die $response->{errors}->[0] if $response->{errors}->[0];
            return -1;
        }

        return $response;
    };

    my $result;
    eval {
        if ($is_whmapi) {

            # Drop privileges and call closure as user
            require Cpanel::AccessIds;
            local $Cpanel::user = $user;
            $result = Cpanel::AccessIds::do_as_user_with_exception(
                $user,
                $do_change_domain,
            );
        }
        else {
            # Call closure as current user
            $result = $do_change_domain->();
        }
    };

    # Check for exceptions first
    if ( my $exception = $@ ) {
        my $error_message = locale()->maketext( "We could not migrate your Site Quality Monitoring project from “[_2]” to “[_3]”. Error: “[_1]”.", $exception, $old_domain, $new_domain );
        return ( 0, $error_message );
    }
    elsif ( $result == 0 ) {
        return ( 1, locale()->maketext( "No Site Quality Monitoring user found for [_1].", $user ) );
    }
    elsif ( $result == -1 ) {
        return ( 1, locale()->maketext( "No Site Quality Monitoring found for [_1].", $old_domain ) );
    }
    else {
        logger->info("Updated Site Quality Monitoring domain from $old_domain to $new_domain for user $user.");
        return ( 1, locale()->maketext( "Updated Site Quality Monitoring domain from [_1] to [_2] for user [_3].", $old_domain, $new_domain, $user ) );
    }
}

=head1 DEPENDENCIES

=over 4

=item * Future: Koality API client modules (to be added)

=back

=head1 ERROR HANDLING

The module will include comprehensive error handling:

=over 4

=item * API connection failures are handled gracefully

=item * User-friendly error messages are provided

=item * Detailed logging for server administrators

=back

=head1 LOGGING

The module uses the cPanel logging system to record:

=over 4

=item * Domain change API calls to Koality service

=item * Success and failure messages

=item * API response details for troubleshooting

=back

=head1 SEE ALSO

=over 4

=item * L<Cpanel::Hooks::ChangeDomains> - The generic domain change framework

=item * L<Cpanel::Sitejet::Hooks::ChangeDomains> - Sitejet-specific implementation

=item * L<Cpanel::Xovi::Hooks::ChangeDomains> - XOVI-specific implementation

=back

=head1 AUTHOR

WebPros International, LLC

=head1 COPYRIGHT

Copyright 2025 WebPros International, LLC. All rights reserved.

=cut

1;
