<?php

namespace SheetWise;

use WP_Comment;
use WP_Post;
use WP_User;

class Hooks {

    /**
     * Initialize the hooks
     *
     * @since 1.0.0
     *
     * @return void
     */
    public function __construct() {
        // Register hooks directly with their arg counts to avoid calling
        // swise_get_data_sources() too early, which triggers translation
        // loading before the init action.
        $core_hooks = [
            'user_register'          => 2,
            'wp_update_user'         => 3,
            'delete_user'            => 3,
            'wp_login'               => 2,
            'wp_logout'              => 1,
            'save_post'              => 3,
            'edit_post'              => 2,
            'wp_trash_post'          => 2,
            'untrash_post'           => 2,
            'transition_post_status' => 3,
            'wp_insert_comment'      => 2,
            'edit_comment'           => 2,
            'delete_comment'         => 2,
            'wp_set_comment_status'  => 2,
        ];

        foreach ( $core_hooks as $hook => $num_of_args ) {
            add_action( $hook, [ $this, $hook ], 10, $num_of_args );
        }
    }

    /**
     * Handle the user_register hook
     *
     * @since 1.0.0
     *
     * @param int $user_id
     * @parem array $userdata
     *
     * @return void
     */
    public function user_register( $user_id, $userdata ) {
        $user = get_user_by( 'ID', $user_id );
        $hook = 'user_register';

        if ( ! $user ) {
            return;
        }

        $user_meta_keys = array_keys( get_user_meta( $user->data->ID ) );

        $all_event_codes = swise_get_data_source_events();
        if ( ! array_key_exists( $hook, $all_event_codes ) ) {
            return;
        }

        $all_event_codes = swise_get_data_source_events();

        $user_values = $this->get_user_values( $all_event_codes, $hook, $user, $user_meta_keys );

        if ( empty( $user_values ) ) {
            return;
        }

        // define hook name beforehand
        $creation_hook = 'sheetwise_scheduled_' . $hook;

        as_enqueue_async_action(
            $creation_hook,
            [
                'args' => [
                    'type'   => 'user',
                    'hook'   => $hook,
                    'values' => $user_values,
                    'id'     => $user_id,
                ],
            ],
            'swise_user',
            true
        );
    }

    /**
     * Handle the wp_update_user hook
     *
     * @since 1.0.0
     *
     * @param int $user_id
     *
     * @return void
     */
    public function wp_update_user( $user_id, $userdata, $userdata_raw ) {
        $user = get_user_by( 'ID', $user_id );
        $hook = 'wp_update_user';

        if ( ! $user ) {
            return;
        }

        $user_meta_keys = array_keys( get_user_meta( $user->data->ID ) );

        $all_event_codes = swise_get_data_source_events();

        if ( ! array_key_exists( $hook, $all_event_codes ) ) {
            return;
        }

        $user_values = $this->get_user_values( $all_event_codes, $hook, $user, $user_meta_keys );

        if ( empty( $user_values ) ) {
            return;
        }

        // define hook name beforehand
        $creation_hook = 'sheetwise_scheduled_' . $hook;

        as_enqueue_async_action(
            $creation_hook,
            [
                'args' => [
                    'type'   => 'user',
                    'hook'   => $hook,
                    'values' => $user_values,
                    'id'     => $user_id,
                ],
            ],
            'swise_user',
            true
        );
    }

    /**
     * Handle the delete_user hook
     *
     * @since 1.0.0
     *
     * @param int     $id
     * @param bool    $reassign
     * @param WP_User $user
     *
     * @return void
     */
    public function delete_user( $user_id, $reassign, $user ) {
        $hook = 'delete_user';

        $user_meta_keys = array_keys( get_user_meta( $user->data->ID ) );

        $all_event_codes = swise_get_data_source_events();

        if ( ! array_key_exists( $hook, $all_event_codes ) ) {
            return;
        }

        $user_values = $this->get_user_values( $all_event_codes, $hook, $user, $user_meta_keys );

        if ( empty( $user_values ) ) {
            return;
        }

        // define hook name beforehand
        $creation_hook = 'sheetwise_scheduled_' . $hook;

        as_enqueue_async_action(
            $creation_hook,
            [
                'args' => [
                    'type'   => 'user',
                    'hook'   => $hook,
                    'values' => $user_values,
                    'id'     => $user_id,
                ],
            ],
            'swise_user',
            true
        );
    }

    /**
     * Handle the wp_login hook
     *
     * @since 1.0.0
     *
     * @param string $user_login
     * @param WP_User $user
     *
     * @return void
     */
    public function wp_login( $user_login, $user ) {
        $hook = 'wp_login';

        $user_meta_keys = array_keys( get_user_meta( $user->data->ID ) );

        $all_event_codes = swise_get_data_source_events();

        if ( ! array_key_exists( $hook, $all_event_codes ) ) {
            return;
        }

        $user_values = $this->get_user_values( $all_event_codes, $hook, $user, $user_meta_keys );

        if ( empty( $user_values ) ) {
            return;
        }

        // define hook name beforehand
        $creation_hook = 'sheetwise_scheduled_' . $hook;

        as_enqueue_async_action(
            $creation_hook,
            [
                'args' => [
                    'type'   => 'user',
                    'hook'   => $hook,
                    'values' => $user_values,
                    'id'     => $user->ID,
                ],
            ],
            'swise_user',
            true
        );
    }

    /**
     * Handle the wp_logout hook
     *
     * @since 1.0.0
     *
     * @param int $user_id
     *
     * @return void
     */
    public function wp_logout( $user_id ) {
        $user = get_user_by( 'ID', $user_id );

        $hook = 'wp_logout';

        $user_meta_keys = array_keys( get_user_meta( $user->data->ID ) );

        $all_event_codes = swise_get_data_source_events();

        if ( ! array_key_exists( $hook, $all_event_codes ) ) {
            return;
        }

        $user_values = $this->get_user_values( $all_event_codes, $hook, $user, $user_meta_keys );

        if ( empty( $user_values ) ) {
            return;
        }

        // define hook name beforehand
        $creation_hook = 'sheetwise_scheduled_' . $hook;

        as_enqueue_async_action(
            $creation_hook,
            [
                'args' => [
                    'type'   => 'user',
                    'hook'   => $hook,
                    'values' => $user_values,
                    'id'     => $user->ID,
                ],
            ],
            'swise_user',
            true
        );
    }

    /**
     * Handle the save_post hook
     *
     * @since 1.0.0
     *
     * @param int $post_id
     * @param WP_Post $post
     * @param bool $update
     *
     * @return void
     */
    public function save_post( $post_id, $post, $update ) {
        // Only want to set if this is a new post!
        if ( 'auto-draft' === $post->post_status ) {
            return;
        }

        // Avoid autosaves
        if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
            return;
        }

        // Check if this is the first published version of the post
        if ( 'publish' !== $post->post_status && $post->post_date_gmt !== $post->post_modified_gmt ) {
            return;
        }

        // Only set for our allowed post_type
        if ( ! in_array( get_post_type( $post_id ), swise_get_supported_post_types(), true ) ) {
            return;
        }

        $hook = 'save_post';

        // define hook name beforehand
        $creation_hook = 'sheetwise_scheduled_' . $hook;

        as_enqueue_async_action(
            $creation_hook,
            [
                'args' => [
                    'type'   => 'post',
                    'hook'   => $hook,
                    'values' => $post,
                    'id'     => $post_id,
                ],
            ],
            'swise_post',
            true
        );
    }

    /**
     * Handle the edit_post hook
     *
     * @since 1.0.0
     *
     * @param int $post_id
     * @param WP_Post $post
     *
     * @return void
     */
    public function edit_post( $post_id, $post ) {
        $hook = 'edit_post';

        // define hook name beforehand
        $creation_hook = 'sheetwise_scheduled_' . $hook;

        as_enqueue_async_action(
            $creation_hook,
            [
                'args' => [
                    'type'   => 'post',
                    'hook'   => $hook,
                    'values' => $post,
                    'id'     => $post_id,
                ],
            ],
            'swise_post',
            true
        );
    }

    /**
     * Handle the wp_trash_post hook
     *
     * @since 1.0.0
     *
     * @param int $post_id
     *
     * @return void
     */
    public function wp_trash_post( $post_id, $previous_status ) {
        if ( ! in_array( get_post_type( $post_id ), swise_get_supported_post_types(), true ) ) {
            return;
        }
        $post = get_post( $post_id );

        if ( ! ( $post instanceof WP_Post ) ) {
            return;
        }

        $hook = 'wp_trash_post';

        // define hook name beforehand
        $creation_hook = 'sheetwise_scheduled_' . $hook;

        as_enqueue_async_action(
            $creation_hook,
            [
                'args' => [
                    'type'   => 'post',
                    'hook'   => $hook,
                    'values' => $post,
                    'id'     => $post_id,
                ],
            ],
            'swise_post',
            true
        );
    }

    /**
     * Handle the wp_insert_comment hook
     *
     * @since 1.0.0
     *
     * @param int $comment_id
     * @param WP_Comment $comment
     *
     * @return void
     */
    public function wp_insert_comment( $comment_id, $comment ) {
        $hook = 'wp_insert_comment';

        // define hook name beforehand
        $creation_hook = 'sheetwise_scheduled_' . $hook;

        as_enqueue_async_action(
            $creation_hook,
            [
                'args' => [
                    'type'   => 'comment',
                    'hook'   => $hook,
                    'values' => $comment,
                    'id'     => $comment_id,
                ],
            ],
            'swise_comment',
            true
        );
    }

    /**
     * Handle the edit_comment hook
     *
     * @since 1.0.0
     *
     * @param int $comment_id
     * @param array $data
     *
     * @return void
     */
    public function edit_comment( $comment_id, $data ) {
        $hook = 'edit_comment';

        // define hook name beforehand
        $creation_hook = 'sheetwise_scheduled_' . $hook;

        as_enqueue_async_action(
            $creation_hook,
            [
                'args' => [
                    'type'   => 'comment',
                    'hook'   => $hook,
                    'values' => get_comment( $comment_id ),
                    'id'     => $comment_id,
                ],
            ],
            'swise_comment',
            true
        );
    }

    /**
     * Handle the untrash_post hook
     *
     * @since 2.0.0
     *
     * @param int    $post_id
     * @param string $previous_status
     *
     * @return void
     */
    public function untrash_post( $post_id, $previous_status ) {
        if ( ! in_array( get_post_type( $post_id ), swise_get_supported_post_types(), true ) ) {
            return;
        }

        $post = get_post( $post_id );

        if ( ! ( $post instanceof WP_Post ) ) {
            return;
        }

        $hook = 'untrash_post';

        // define hook name beforehand
        $creation_hook = 'sheetwise_scheduled_' . $hook;

        as_enqueue_async_action(
            $creation_hook,
            [
                'args' => [
                    'type'   => 'post',
                    'hook'   => $hook,
                    'values' => $post,
                    'id'     => $post_id,
                ],
            ],
            'swise_post',
            true
        );
    }

    /**
     * Handle the transition_post_status hook
     *
     * @since 2.0.0
     *
     * @param string  $new_status
     * @param string  $old_status
     * @param WP_Post $post
     *
     * @return void
     */
    public function transition_post_status( $new_status, $old_status, $post ) {
        // Skip auto-drafts and revisions.
        if ( 'auto-draft' === $new_status || 'inherit' === $new_status ) {
            return;
        }

        // Skip if status hasn't actually changed.
        if ( $new_status === $old_status ) {
            return;
        }

        if ( ! in_array( get_post_type( $post->ID ), swise_get_supported_post_types(), true ) ) {
            return;
        }

        $hook = 'transition_post_status';

        $values = [
            'ID'            => $post->ID,
            'post_title'    => $post->post_title,
            'old_status'    => $old_status,
            'new_status'    => $new_status,
            'post_author'   => $post->post_author,
            'post_date'     => $post->post_date,
            'post_modified' => $post->post_modified,
            'post_type'     => $post->post_type,
        ];

        // define hook name beforehand
        $creation_hook = 'sheetwise_scheduled_' . $hook;

        as_enqueue_async_action(
            $creation_hook,
            [
                'args' => [
                    'type'   => 'post',
                    'hook'   => $hook,
                    'values' => $values,
                    'id'     => $post->ID,
                ],
            ],
            'swise_post',
            true
        );
    }

    /**
     * Handle the delete_comment hook
     *
     * @since 2.0.0
     *
     * @param int        $comment_id
     * @param WP_Comment $comment
     *
     * @return void
     */
    public function delete_comment( $comment_id, $comment ) {
        $hook = 'delete_comment';

        // define hook name beforehand
        $creation_hook = 'sheetwise_scheduled_' . $hook;

        as_enqueue_async_action(
            $creation_hook,
            [
                'args' => [
                    'type'   => 'comment',
                    'hook'   => $hook,
                    'values' => $comment,
                    'id'     => $comment_id,
                ],
            ],
            'swise_comment',
            true
        );
    }

    /**
     * Handle the wp_set_comment_status hook
     *
     * @since 2.0.0
     *
     * @param int    $comment_id
     * @param string $comment_status The new status (approve, hold, spam, trash).
     *
     * @return void
     */
    public function wp_set_comment_status( $comment_id, $comment_status ) {
        $comment = get_comment( $comment_id );

        if ( ! ( $comment instanceof WP_Comment ) ) {
            return;
        }

        $hook = 'wp_set_comment_status';

        $values = [
            'comment_ID'           => $comment->comment_ID,
            'comment_post_ID'      => $comment->comment_post_ID,
            'comment_author'       => $comment->comment_author,
            'comment_author_email' => $comment->comment_author_email,
            'comment_content'      => $comment->comment_content,
            'new_status'           => $comment_status,
            'old_status'           => $comment->comment_approved,
        ];

        // define hook name beforehand
        $creation_hook = 'sheetwise_scheduled_' . $hook;

        as_enqueue_async_action(
            $creation_hook,
            [
                'args' => [
                    'type'   => 'comment',
                    'hook'   => $hook,
                    'values' => $values,
                    'id'     => $comment_id,
                ],
            ],
            'swise_comment',
            true
        );
    }

    /**
     * Get the user values
     *
     * @since 1.0.0
     *
     * @param array $all_event_codes
     * @param string $hook
     * @param WP_User $user
     * @param array $user_meta_keys
     *
     * @return array
     */
    private function get_user_values( $all_event_codes, $hook, $user, $user_meta_keys ) {
        $user_values = [];
        $default_events = array_keys( $all_event_codes[ $hook ] );

        foreach ( $default_events as $event ) {
            if ( $event === 'user_id' ) {
                $user_values[ $event ] = $user->data->ID;
            } elseif ( in_array( $event, $user_meta_keys, true ) ) {
                $user_values[ $event ] = get_user_meta( $user->data->ID, $event, true );
            } else {
                $user_values[ $event ] = $user->data->$event;
            }
        }

        return $user_values;
    }
}
