<?php

namespace Wpcafe_Multivendor\Core\Hooks;

defined( "ABSPATH" ) || exit;

use WpCafe\Traits\Wpc_Singleton;

/**
 * Timed Product Hooks Handler
 *
 * Handles all timed product-related vendor permissions and filtering for wpcafe-pro controllers
 * using filter hooks to maintain clean separation between plugins.
 */
class Timed_Product_Hooks {

    use Wpc_Singleton;

    /**
     * Initialize all timed product filters
     */
    public function init() {
        add_filter( 'wpcafe_pro_timed_product_create_permission', [ $this, 'can_create_timed_product' ], 10, 2 );
        add_filter( 'wpcafe_pro_timed_product_read_permission', [ $this, 'can_read_timed_products' ], 10, 2 );
        add_filter( 'wpcafe_pro_timed_product_query_args', [ $this, 'filter_timed_product_query' ], 10, 2 );
        add_filter( 'wpcafe_pro_timed_product_item_permission', [ $this, 'can_access_timed_product_item' ], 10, 2 );
        add_filter( 'wpcafe_pro_timed_product_update_permission', [ $this, 'can_update_timed_product' ], 10, 2 );
        add_filter( 'wpcafe_pro_timed_product_delete_permission', [ $this, 'can_delete_timed_product' ], 10, 2 );
        add_filter( 'wpcafe_pro_timed_product_bulk_delete_check', [ $this, 'can_bulk_delete_timed_products' ], 10, 3 );
        add_filter( 'wpcafe_pro_timed_product_prepare_data', [ $this, 'prepare_timed_product_data' ], 10, 2 );
        add_filter( 'wpcafe_pro_applicable_timed_product_conditions', [ $this, 'filter_applicable_timed_product_conditions' ], 10, 2 );

        // Dokan store page hooks for timed product filtering
        add_action( 'dokan_store_page_query_filter', [ $this, 'filter_vendor_store_query' ], 10, 2 );
        add_filter( 'wpcafe_multivendor_vendor_store_products', [ $this, 'filter_slider_products' ], 10, 2 );
    }

    /**
     * Check if user is admin
     *
     * @return bool
     */
    private function is_admin() {
        return current_user_can('manage_options');
    }

    /**
     * Check if user is vendor but not admin
     *
     * @return bool
     */
    private function is_vendor_only() {
        return wpc_user_is_dokan_vendor() && !$this->is_admin();
    }

    /**
     * Filter timed product query args for vendors
     *
     * @param array $args Query arguments
     * @param \WP_REST_Request $request Request object
     * @return array
     */
    public function filter_timed_product_query($args, $request) {
        if ($this->is_vendor_only()) {
            $args['author'] = get_current_user_id();
        }
        return $args;
    }

    /**
     * Check if user can create timed product
     *
     * @param bool $default_permission Default permission
     * @param \WP_REST_Request $request Request object
     * @return bool
     */
    public function can_create_timed_product($default_permission, $request) {
        return $default_permission || wpc_user_is_dokan_vendor();
    }

    /**
     * Check if user can read timed products
     *
     * @param bool $default_permission Default permission
     * @param \WP_REST_Request $request Request object
     * @return bool
     */
    public function can_read_timed_products($default_permission, $request) {
        return $default_permission || wpc_user_is_dokan_vendor();
    }

    /**
     * Check if user can access specific timed product item
     *
     * @param bool $default_permission Default permission
     * @param \WP_REST_Request $request Request object
     * @return bool
     */
    public function can_access_timed_product_item($default_permission, $request) {
        if ($this->is_admin()) {
            return true;
        }

        if (!wpc_user_is_dokan_vendor()) {
            return false;
        }

        // Check if Timed_Product_Model class exists
        if (!class_exists('\WpCafePro\Models\Timed_Product_Model')) {
            return false;
        }

        $id = intval($request['id']);
        $timed_product = \WpCafePro\Models\Timed_Product_Model::find($id);

        if (!$timed_product) {
            return false;
        }

        return (int) $timed_product->post_author === get_current_user_id();
    }

    /**
     * Check if user can update timed product
     *
     * @param bool $default_permission Default permission
     * @param \WP_REST_Request $request Request object
     * @return bool
     */
    public function can_update_timed_product($default_permission, $request) {
        return $this->can_access_timed_product_item($default_permission, $request);
    }

    /**
     * Check if user can delete timed product
     *
     * @param bool $default_permission Default permission
     * @param \WP_REST_Request $request Request object
     * @return bool
     */
    public function can_delete_timed_product($default_permission, $request) {
        return $this->can_access_timed_product_item($default_permission, $request);
    }

    /**
     * Check if user can bulk delete timed products
     *
     * @param bool $default_permission Default permission
     * @param array $ids Array of timed product IDs
     * @param \WP_REST_Request $request Request object
     * @return bool
     */
    public function can_bulk_delete_timed_products($default_permission, $ids, $request) {
        if ($this->is_admin()) {
            return true;
        }

        if (!wpc_user_is_dokan_vendor()) {
            return false;
        }

        // Check if Timed_Product_Model class exists
        if (!class_exists('\WpCafePro\Models\Timed_Product_Model')) {
            return false;
        }

        $current_user_id = get_current_user_id();

        foreach ($ids as $id) {
            $timed_product = \WpCafePro\Models\Timed_Product_Model::find($id);
            if ($timed_product && (int) $timed_product->post_author !== $current_user_id) {
                return false; // Found a timed product not owned by vendor
            }
        }

        return true;
    }

    /**
     * Prepare timed product data for database storage
     *
     * @param array $data Prepared data
     * @param \WP_REST_Request $request Request object
     * @return array
     */
    public function prepare_timed_product_data($data, $request) {
        if ($this->is_vendor_only()) {
            $data['post_author'] = get_current_user_id();
        }
        return $data;
    }

    /**
     * Filter applicable timed product conditions for vendor-specific rules
     *
     * @param array $timed_product_conditions Array of timed product conditions
     * @param WP_Query|null $query The query object (may be null in some contexts)
     * @return array Modified timed product conditions
     */
    public function filter_applicable_timed_product_conditions($timed_product_conditions, $query = null) {
        if ( empty( $timed_product_conditions ) || ! is_array( $timed_product_conditions ) ) {
            return $timed_product_conditions;
        }

        $modified_conditions = [];

        foreach ( $timed_product_conditions as $timed_product ) {
            $timed_product_author = (int) $timed_product->post_author;
            $is_admin = user_can( $timed_product_author, 'manage_options' );

            $modified_condition = clone $timed_product;

            if ( ! $is_admin ) {
                $modified_condition->product_rule = $this->restrict_product_rule_to_vendor($timed_product->product_rule, $timed_product_author);
            }

            $modified_conditions[] = $modified_condition;
        }

        return $modified_conditions;
    }

    /**
     * Get timed products for vendor and admin combined
     *
     * @param int $vendor_id Vendor user ID
     * @return array Array of timed product conditions
     */
    private function get_vendor_and_admin_timed_products($vendor_id) {
        if ( ! class_exists( '\WpCafePro\Models\Timed_Product_Model' ) ) {
            return [];
        }

        $admin_users = get_users([
            'capability' => 'manage_options',
            'fields' => 'ID'
        ]);

        $author_ids = array_merge( [$vendor_id], $admin_users );

        $timed_products = get_posts([
            'post_type' => 'wpc-timed-product',
            'post_status' => 'active',
            'author__in' => $author_ids,
            'posts_per_page' => -1,
            'orderby' => 'date',
            'order' => 'DESC'
        ]);

        if ( empty( $timed_products ) ) {
            $timed_products = get_posts([
                'post_type' => 'wpc-timed-product',
                'post_status' => 'publish',
                'author__in' => $author_ids,
                'posts_per_page' => -1,
                'orderby' => 'date',
                'order' => 'DESC'
            ]);
        }

        $timed_product_models = [];
        foreach ( $timed_products as $post ) {
            $timed_product_models[] = \WpCafePro\Models\Timed_Product_Model::find( $post->ID );
        }

        return array_filter( $timed_product_models); // Remove any null values
    }

    /**
     * Filter vendor store query to hide timed products
     *
     * @param WP_Query $query The query object
     * @param array $store_info Store information array
     * @return void
     */
    public function filter_vendor_store_query($query, $store_info) {
        if ( ! class_exists( '\WpCafePro\FoodOrder\TimedProduct\Timed_Products_Conditions' ) ) {
            return;
        }

        $author_name = $query->get('author_name');
        if ( empty( $author_name ) ) {
            $author_name = get_query_var('store');
            if ( empty( $author_name ) ) {
                $author_name = get_query_var( dokan_get_option( 'custom_store_url', 'dokan_general', 'store' ) );
            }
        }

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

        // Get vendor user by slug
        $vendor_user = get_user_by( 'slug', $author_name );
        if ( ! $vendor_user ) {
            return;
        }

        $vendor_id = $vendor_user->ID;

        $timed_product_conditions = $this->get_vendor_and_admin_timed_products( $vendor_id );

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

        $vendor_timed_products = [];
        $admin_timed_products = [];

        foreach ( $timed_product_conditions as $timed_product ) {
            $timed_product_author = (int) $timed_product->post_author;
            $is_admin = user_can( $timed_product_author, 'manage_options' );

            if ( $is_admin ) {
                $admin_timed_products[] = $timed_product;
            } elseif ( $timed_product_author === $vendor_id ) {
                $vendor_timed_products[] = $timed_product;
            }
        }

        $rules_to_apply = ! empty( $vendor_timed_products ) ? $vendor_timed_products : $admin_timed_products;

        foreach ( $rules_to_apply as $timed_product ) {
            $time_rules = $timed_product->time_rules;
            $product_rule = $timed_product->product_rule;
            $action = $timed_product->action;
            $timed_product_author = (int) $timed_product->post_author;
            if ( ! user_can( $timed_product_author, 'manage_options' ) && $timed_product_author === $vendor_id ) {
                $product_rule = $this->restrict_product_rule_to_vendor( $product_rule, $vendor_id );
            }

            $time_rule_apply_now = \WpCafePro\FoodOrder\TimedProduct\Timed_Products_Conditions::is_time_rule_applicable_now( $time_rules );

            if ( 'set_hidden' === $action && $time_rule_apply_now ) {
                \WpCafePro\FoodOrder\TimedProduct\Timed_Products_Conditions::modify_query_hide_products_by_rule( $query, $product_rule );
            }

            if ( 'set_visible' === $action && ! $time_rule_apply_now ) {
                \WpCafePro\FoodOrder\TimedProduct\Timed_Products_Conditions::modify_query_hide_products_by_rule( $query, $product_rule );
            }
        }
    }

    /**
     * Filter slider products array to remove timed products
     *
     * @param array $products Array of WC_Product objects
     * @param int $vendor_id Vendor user ID
     * @return array Filtered products array
     */
    public function filter_slider_products($products, $vendor_id) {
        if ( ! class_exists( '\WpCafePro\FoodOrder\TimedProduct\Timed_Products_Conditions' ) ) {
            return $products;
        }

        $timed_product_conditions = $this->get_vendor_and_admin_timed_products( $vendor_id );

        if ( empty( $timed_product_conditions ) ) {
            return $products;
        }

        $vendor_timed_products = [];
        $admin_timed_products = [];

        foreach ( $timed_product_conditions as $timed_product ) {
            $timed_product_author = (int) $timed_product->post_author;
            $is_admin = user_can( $timed_product_author, 'manage_options' );

            if ( $is_admin ) {
                $admin_timed_products[] = $timed_product;
            } elseif ( $timed_product_author === $vendor_id ) {
                $vendor_timed_products[] = $timed_product;
            }
        }

        $rules_to_apply = ! empty( $vendor_timed_products ) ? $vendor_timed_products : $admin_timed_products;

        $product_ids_to_hide = [];
        foreach ( $rules_to_apply as $timed_product ) {
            $time_rules = $timed_product->time_rules;
            $product_rule = $timed_product->product_rule;
            $action = $timed_product->action;
            $timed_product_author = (int) $timed_product->post_author;
            if ( ! user_can( $timed_product_author, 'manage_options' ) && $timed_product_author === $vendor_id ) {
                $product_rule = $this->restrict_product_rule_to_vendor( $product_rule, $vendor_id );
            }

            $time_rule_apply_now = \WpCafePro\FoodOrder\TimedProduct\Timed_Products_Conditions::is_time_rule_applicable_now($time_rules);

            $should_hide = false;
            if ( 'set_hidden' === $action && $time_rule_apply_now ) {
                $should_hide = true;
            }
            if ( 'set_visible' === $action && ! $time_rule_apply_now ) {
                $should_hide = true;
            }

            if ( $should_hide ) {
                if ( empty( $product_rule ) || ! is_array( $product_rule ) ) {
                    $product_rule = ['type' => 'all_products'];
                }

                $rule_type = ! empty( $product_rule['type'] ) ? $product_rule['type'] : 'all_products';

                switch ( $rule_type ) {
                    case 'all_products':
                        $excluded_products = ! empty( $product_rule['excluded_products'] ) && is_array( $product_rule['excluded_products'] ) ? array_map( 'intval', $product_rule['excluded_products'] ) : [];

                        foreach ($products as $product) {
                            $product_id = is_object($product) ? $product->get_id() : $product;
                            if (!in_array($product_id, $excluded_products)) {
                                $product_ids_to_hide[] = $product_id;
                            }
                        }
                        break;

                    case 'specific_products':
                        // Hide specific products
                        if (!empty($product_rule['products']) && is_array($product_rule['products'])) {
                            $product_ids_to_hide = array_merge(
                                $product_ids_to_hide,
                                array_map('intval', $product_rule['products'])
                            );
                        }
                        break;

                    case 'specific_categories':
                        // Hide products in specific categories
                        if (!empty($product_rule['categories']) && is_array($product_rule['categories'])) {
                            $category_ids = array_map('intval', $product_rule['categories']);

                            foreach ( $products as $product ) {
                                if ( ! is_object( $product ) ) {
                                    continue;
                                }

                                $product_categories = wp_get_post_terms( $product->get_id(), 'product_cat', ['fields' => 'ids'] );

                                if ( is_array( $product_categories ) && array_intersect( $category_ids, $product_categories ) ) {
                                    $product_ids_to_hide[] = $product->get_id();
                                }
                            }
                        }
                        break;
                }
            }
        }

        if ( ! empty( $product_ids_to_hide ) ) {
            $product_ids_to_hide = array_unique($product_ids_to_hide);
            $products = array_filter($products, function($product) use ($product_ids_to_hide) {
                $product_id = is_object($product) ? $product->get_id() : $product;
                return !in_array($product_id, $product_ids_to_hide);
            });
        }

        return $products;
    }

    /**
     * Restrict product rule to only include vendor's own products
     *
     * @param array $product_rule The original product rule
     * @param int $vendor_id Vendor user ID
     * @return array Modified product rule
     */
    private function restrict_product_rule_to_vendor($product_rule, $vendor_id) {
        if ( empty( $product_rule ) || ! is_array( $product_rule ) ) {
            $product_rule = ['type' => 'all_products'];
        }

        $rule_type = ! empty( $product_rule['type'] ) ? $product_rule['type'] : 'all_products';

        // Get all vendor's product IDs
        $vendor_product_ids = get_posts([
            'post_type' => 'product',
            'author' => $vendor_id,
            'posts_per_page' => -1,
            'fields' => 'ids',
            'post_status' => 'any'
        ]);

        if ( empty( $vendor_product_ids ) ) {
            return ['type' => 'specific_products', 'specific_products' => []];
        }

        switch ( $rule_type ) {
            case 'all_products':
                $excluded_products = ! empty( $product_rule['excluded_products'] ) && is_array( $product_rule['excluded_products'] ) ? array_map( 'intval', $product_rule['excluded_products'] ) : [];
                $allowed_vendor_products = array_diff( $vendor_product_ids, $excluded_products );

                return [
                    'type' => 'specific_products',
                    'specific_products' => array_values( $allowed_vendor_products )
                ];

            case 'specific_products':
                $specified_products = ! empty( $product_rule['specific_products'] ) && is_array( $product_rule['specific_products'] ) ? array_map( 'intval', $product_rule['specific_products'] ) : ( ! empty( $product_rule['products'] ) && is_array( $product_rule['products'] ) ? array_map( 'intval', $product_rule['products'] ) : [] );
                $allowed_products = array_intersect( $specified_products, $vendor_product_ids );

                return [
                    'type' => 'specific_products',
                    'specific_products' => array_values( $allowed_products )
                ];

            case 'specific_categories':
                $category_ids = ! empty( $product_rule['specific_categories'] ) && is_array( $product_rule['specific_categories'] ) ? array_map( 'intval', $product_rule['specific_categories'] ) : ( ! empty( $product_rule['categories'] ) && is_array( $product_rule['categories'] ) ? array_map( 'intval', $product_rule['categories'] ) : [] );

                if ( empty( $category_ids ) ) {
                    return ['type' => 'specific_products', 'specific_products' => []];
                }

                $vendor_products_in_categories = [];
                foreach ( $vendor_product_ids as $product_id ) {
                    $product_categories = wp_get_post_terms( $product_id, 'product_cat', ['fields' => 'ids'] );
                    if ( is_array( $product_categories ) && array_intersect( $category_ids, $product_categories ) ) {
                        $vendor_products_in_categories[] = $product_id;
                    }
                }

                return [
                    'type' => 'specific_products',
                    'specific_products' => $vendor_products_in_categories
                ];

            default:
                return [
                    'type' => 'specific_products',
                    'specific_products' => $vendor_product_ids
                ];
        }
    }
}
