<?php

namespace HelpGent\App\Providers;

defined( 'ABSPATH' ) || exit;

use stdClass;
use WP_REST_Request;
use HelpGent\App\DTO\MessageDTO;
use HelpGent\App\DTO\ChatMessageDTO;
use HelpGent\App\Models\HelpGentUser as HelpGentUserModel;
use HelpGent\App\Repositories\SettingsRepository;
use HelpGent\WpMVC\Contracts\Provider;
use HelpGent\App\Mail\NewResponseMailer;
use HelpGent\App\Mail\Admin\NewResponseMailer as AdminNewResponseMailer;
use HelpGent\App\Mail\NewMessageMailer;
use HelpGent\App\Mail\NewChatMessageMailer;
use HelpGent\App\Mail\Admin\NewMessageMailer as AdminNewMessageMailer;
use HelpGent\App\BackgroundProcessors\BackgroundProcessor;

class EmailNotificationProvider implements Provider {
    public ?BackgroundProcessor $background_processor = null;

    public function boot() {
        add_action( 'init', [ $this, 'init_background_processor' ] );
        add_action( 'helpgent_after_submit_form', [ $this, 'send_new_response_notification_in_background' ], 10, 3 );
        add_action( 'helpgent_after_store_message', [ $this, 'send_new_message_notification_in_background' ], 10, 4 );
        add_action( 'helpgent_after_store_chat_message', [ $this, 'send_new_chat_message_notification_in_background' ], 10, 4 );
    }

    public function init_background_processor() {
        $this->background_processor = new BackgroundProcessor( 'send_email' );
    }

    public function send_new_response_notification_in_background( stdClass $response, stdClass $form, WP_REST_Request $request ) {
        $args = [
            'response' => $response,
            'form'     => $form,
            'params'   => $request->get_params(),
        ];

        $this->run_in_background( [ $this, 'send_new_response_notification' ], $args );
    }

    public function send_new_response_notification( array $args = [] ): bool {
        /**
         * @var array $params
         */
        $params = $args[ 'params' ];

        /**
         * @var stdClass $form
         */
        $form = $args[ 'form' ];

        /**
         * @var stdClass $response
         */
        $response = $args[ 'response' ];

        if ( empty( $form->content ) ) {
            return false;
        }

        if ( empty( $form->content['global'] ) ) {
            return false;
        }
        
        $admin = apply_filters( 'helpgent_email_notification_admin_data', null, $form );

        if ( empty( $admin ) ) {
            $admin = $this->get_admin();
        }

        if ( empty( $admin ) ) {
            return false;
        }

        $global_settings = $form->content['global'];
        $created_by_user = ! empty( $response->created_by ) ? $this->get_user_by_id( $response->created_by ) : null;
        $response_token  = isset( $params['response_token'] ) ? $params['response_token'] : '';

        /**
         * @var SettingsRepository $settings_repository
         */
        $settings_repository     = helpgent_singleton( SettingsRepository::class );
        $email_template_settings = $settings_repository->get_email_template_settings();

        $notify_admin = ( bool ) helpgent_get_nested_value( 'admin_notification_notify_on_new_response', $global_settings, true );
        $notify_admin = apply_filters( 'helpgent_send_admin_email_notification', $notify_admin, $form );

        $site_name = get_site_option( 'blogname', 'HelpGent' );
        $site_url  = get_site_url();

        // Notify Admin
        if ( $notify_admin ) {
            $mailer          = new AdminNewResponseMailer( $response, $email_template_settings, $created_by_user, $admin, $form );
            $mailer->subject = helpgent_get_nested_value( 'admin_notification_new_response_subject', $global_settings, '' );
            $mailer->body    = helpgent_get_nested_value( 'admin_notification_new_response_body', $global_settings, '' );

            $mailer->placeholders['{{SITE_NAME}}'] = $site_name;
            $mailer->placeholders['{{SITE_URL}}']  = $site_url;

            if ( $created_by_user ) {
                $mailer->headers['Reply-To'] = $created_by_user['email'];
            }

            /**
             * @var AdminNewResponseMailer $mailer
             */
            $mailer = apply_filters( 'helpgent_new_response_mailer_for_admin', $mailer, $response, $form, $response_token, $admin, $created_by_user );

            $mailer->send( $form );
        }

        if ( ! $created_by_user ) {
            return false;
        }

        $notify_user = ( bool ) helpgent_get_nested_value( 'user_notification_notify_on_new_response', $global_settings, true );
        $notify_user = apply_filters( 'helpgent_send_user_email_notification', $notify_user, $form );

        if ( ! $notify_user || empty( $created_by_user['email'] ) ) {
            return false;
        }

        // Notify User
        $mailer = new NewResponseMailer( $response, $email_template_settings, $created_by_user, $created_by_user, $response_token );

        $mailer->subject = helpgent_get_nested_value( 'user_notification_new_response_subject', $global_settings, '' );
        $mailer->body    = helpgent_get_nested_value( 'user_notification_new_response_body', $global_settings, '' );

        $mailer->placeholders['{{FROM_NAME}}']  = $admin['name'];
        $mailer->placeholders['{{FROM_EMAIL}}'] = $admin['email'];
        $mailer->placeholders['{{SITE_NAME}}']  = $site_name;
        $mailer->placeholders['{{SITE_URL}}']   = $site_url;

        if ( ! empty( $admin['email'] ) ) {
            $mailer->headers['Reply-To'] = $admin['email'];
        }

        /**
         * @var NewResponseMailer $mailer
         */
        $mailer = apply_filters( 'helpgent_new_response_mailer_for_user', $mailer, $response, $form, $response_token, $admin, $created_by_user );
        $mailer->send( $form );

        return false;
    }

    public function send_new_message_notification_in_background( MessageDTO $message_dto, WP_REST_Request $request, stdClass $form, stdClass $response ) {
        $args = [
            'message'  => $message_dto,
            'params'   => $request->get_params(),
            'response' => $response,
            'form'     => $form,
        ];

        $this->run_in_background( [ $this, 'send_new_message_notification' ], $args );
    }

    public function send_new_message_notification( $args = [] ): bool {
        /**
         * @var MessageDTO $message_dto
         */
        $message_dto = $args[ 'message' ];

        /**
         * @var stdClass $form
         */
        $form = $args[ 'form' ];

        /**
         * @var stdClass $form
         */
        $response = $args[ 'response' ];

        if ( empty( $form->content ) ) {
            return false;
        }

        if ( empty( $form->content['global'] ) ) {
            return false;
        }

        $global_settings = $form->content['global'];
        $response_user   = ! empty( $response->created_by ) ? $this->get_user_by_id( $response->created_by ) : null;

        $admin = apply_filters( 'helpgent_email_notification_admin_data', null, $form );

        if ( empty( $admin ) ) {
            $admin = $this->get_admin();
        }

        if ( empty( $admin ) ) {
            return false;
        }

        /**
         * @var SettingsRepository $settings_repository
         */
        $settings_repository     = helpgent_singleton( SettingsRepository::class );
        $email_template_settings = $settings_repository->get_email_template_settings();

        $notify_admin = ( bool ) helpgent_get_nested_value( 'admin_notification_notify_on_user_message', $global_settings, false );
        $notify_admin = apply_filters( 'helpgent_send_admin_email_notification', $notify_admin, $form );

        $is_message_from_response_author = $message_dto->get_created_by() === absint( $response->created_by );
        $messaged_by                     = $this->get_user_by_id( $message_dto->get_created_by() );

        $site_name = get_site_option( 'blogname', 'HelpGent' );
        $site_url  = get_site_url();

        if ( $is_message_from_response_author && $notify_admin ) {
            $mailer          = new AdminNewMessageMailer( $message_dto, $email_template_settings, $messaged_by, $admin, $form );
            $mailer->subject = helpgent_get_nested_value( 'admin_notification_user_message_subject', $global_settings, '' );
            $mailer->body    = helpgent_get_nested_value( 'admin_notification_user_message_body', $global_settings, '' );

            $mailer->placeholders['{{SITE_NAME}}'] = $site_name;
            $mailer->placeholders['{{SITE_URL}}']  = $site_url;

            if ( ! empty( $response_user['email'] ) ) {
                $mailer->headers['Reply-To'] = $response_user['email'];
            }

            /**
             * @var AdminNewMessageMailer $mailer
             */
            $mailer = apply_filters( 'helpgent_new_message_mailer_for_user', $mailer, $response, $form, $admin, $response_user, $messaged_by );

            $mailer->send( $form );
        }

        $notify_user = ( bool ) helpgent_get_nested_value( 'user_notification_notify_on_admin_message', $global_settings, false );
        $notify_user = apply_filters( 'helpgent_send_user_email_notification', $notify_user, $form );

        if (
            ! $is_message_from_response_author &&
            $notify_user &&
            ! empty( $response_user['email'] )
        ) {
            $mailer          = new NewMessageMailer( $message_dto, $email_template_settings, $messaged_by, $response_user );
            $mailer->subject = helpgent_get_nested_value( 'user_notification_admin_message_subject', $global_settings, '' );
            $mailer->body    = helpgent_get_nested_value( 'user_notification_admin_message_body', $global_settings, '' );

            $mailer->placeholders['{{FROM_NAME}}']  = $admin['name'];
            $mailer->placeholders['{{FROM_EMAIL}}'] = $admin['email'];
            $mailer->placeholders['{{SITE_NAME}}']  = $site_name;
            $mailer->placeholders['{{SITE_URL}}']   = $site_url;

            if ( ! empty( $admin['email'] ) ) {
                $mailer->headers['Reply-To'] = $admin['email'];
            }

            /**
             * @var NewMessageMailer $mailer 
             */
            $mailer = apply_filters( 'helpgent_new_message_mailer_for_user', $mailer, $response, $form, $admin, $response_user, $messaged_by );

            $mailer->send( $form );
        }

        return false;
    }

    public function send_new_chat_message_notification_in_background( ChatMessageDTO $message_dto, WP_REST_Request $request, stdClass $form, stdClass $response ) {
        if ( '1' !==  ( string ) $request->get_param( 'notify_via_email' ) ) {
            return;
        }

        if ( empty( $response->created_by ) ) {
            return;
        }

        $is_user_message = $message_dto->get_created_by() === absint( $response->created_by );

        if ( $is_user_message ) {
            return;
        }

        if ( empty( $form->content ) ) {
            return;
        }
        
        $args = [
            'message'  => $message_dto,
            'params'   => $request->get_params(),
            'response' => $response,
            'form'     => $form,
        ];

        $this->run_in_background( [ $this, 'send_new_chat_message_notification' ], $args );
    }

    public function send_new_chat_message_notification( $args = [] ): bool {
        /**
         * @var ChatMessageDTO $message_dto
         */
        $message_dto = $args[ 'message' ];

        /**
         * @var stdClass $form
         */
        $form = $args[ 'form' ];

        /**
         * @var stdClass $form
         */
        $response = $args[ 'response' ];

        $admin = apply_filters( 'helpgent_email_notification_admin_data', null, $form );

        if ( empty( $admin ) ) {
            $admin = $this->get_admin();
        }

        if ( empty( $admin ) ) {
            return false;
        }

        /**
         * @var SettingsRepository $settings_repository
         */
        $settings_repository     = helpgent_singleton( SettingsRepository::class );
        $email_template_settings = ( array ) $settings_repository->get_email_template_settings();

        $to_user     = $this->get_user_by_id( $response->created_by );
        $messaged_by = $this->get_user_by_id( $message_dto->get_created_by() );

        if ( empty( $messaged_by ) || empty( $to_user['email'] ) ) {
            return false;
        }

        $site_name = get_site_option( 'blogname', 'HelpGent' );
        $site_url  = get_site_url();

        $mailer          = new NewChatMessageMailer( $message_dto, $email_template_settings, $messaged_by, $to_user );
        $global_settings = $form->content['global'];

        $mailer->subject = helpgent_get_nested_value( 'user_notification_admin_chat_message_subject', $global_settings, $this->get_helpgent_user_email_subject_for_new_chat_message() );
        $mailer->body    = helpgent_get_nested_value( 'user_notification_admin_chat_message_body', $global_settings, $this->get_helpgent_user_email_body_for_new_chat_message() );

        $mailer->placeholders['{{FROM_NAME}}']  = $admin['name'];
        $mailer->placeholders['{{FROM_EMAIL}}'] = $admin['email'];
        $mailer->placeholders['{{SITE_NAME}}']  = $site_name;
        $mailer->placeholders['{{SITE_URL}}']   = $site_url;

        if ( ! empty( $admin['email'] ) ) {
            $mailer->headers['Reply-To'] = $admin['email'];
        }

        /**
         * @var NewChatMessageMailer $mailer 
         */
        $mailer = apply_filters( 'helpgent_new_chat_message_mailer_for_user', $mailer, $response, $form, $admin, $messaged_by, $messaged_by );

        $mailer->send( $form );

        return false;
    }

    public function run_in_background( callable $callback, array $args ) {
        if ( ! $this->background_processor ) {
            return;
        }

        $this->background_processor->run(
            [
                [ 'callback' => $callback, 'args' => $args ]
            ]
        );
    }

    public function get_admin(): ?array {
        global $wpdb;

        $user = get_user_by( 'email', get_bloginfo( 'admin_email' ) );

        if ( ! $user ) {
            return null;
        }

        return [
            'id'    => $user->data->ID, 
            'name'  => $user->data->display_name, 
            'email' => $user->data->user_email,
        ];
    }

    public function get_user_by_id( int $id ): ?array {
        $user = HelpGentUserModel::query()->where( 'id', $id )->first();

        if ( ! $user ) {
            return null;
        }

        return [
            'name'          => $user->name,
            'email'         => $user->email,
            'registered_id' => $user->registered_id,
            'token'         => $user->token,
        ];
    }

    public function get_helpgent_user_email_subject_for_new_response():string {
        return apply_filters( 'helpgent_guest_email_subject_for_new_response', 'Action Required: Verify Your Form Submission' );
    }

    public function get_helpgent_user_email_body_for_new_response(): string {
        $hours                     = intval( helpgent_get_setting( 'remove_unverified_response_after_hours', 48 ) );
        $response_auto_remove_note = 0 < $hours ? "Please be informed that unverified conversations will be automatically deleted within {$hours} hours to maintain security and prevent misuse." : "";

        $template = "
            Greetings {{TO_NAME}},

            We hope this email finds you well. Recently, a new form has been submitted using your email address. To ensure the security and privacy of your data, we are sending you this verification email. 

            Date and Time: {{NOW}}
            IP Address: {{IP_ADDRESS}}

            To verify and access the conversation, please click the button below: {{VERIFICATION_LINK}}

            If you did not make this submission, please click the following link: {{CANCEL_LINK}}

            $response_auto_remove_note
        ";

        return apply_filters( 'helpgent_guest_email_body_for_new_response', trim( $template ) );
    }

    public function get_helpgent_user_email_subject_for_new_chat_message():string {
        return apply_filters( 'helpgent_user_email_subject_for_chat_message', 'A new reply from our support team' );
    }

    public function get_helpgent_user_email_body_for_new_chat_message(): string {
        $hours                     = intval( helpgent_get_setting( 'remove_unverified_response_after_hours', 48 ) );
        $response_auto_remove_note = 0 < $hours ? "Please be informed that unverified conversations will be automatically deleted within {$hours} hours to maintain security and prevent misuse." : "";

        $template = "
            Hi {{TO_NAME}},

            You have a new reply from our support team regarding your recent chat.

            📩 Message from {{FROM_NAME}},

            {{MESSAGE}}

            Click the button below to view and continue the conversation:

            {{DASHBOARD_LINK}}

            If you have any further questions, feel free to reply to this email. We're here to help!

            Best regards

            $response_auto_remove_note
        ";

        return apply_filters( 'helpgent_user_email_body_for_chat_message', trim( $template ) );
    }
}
