<?php

namespace WeDevs\AppBridge\Integrations\WooCommerce\REST;

use WC_REST_Products_Controller;
use WP_REST_Server;

/**
 * Class AuctionController
 *
 * @package WeDevs\AppBridge\Integrations\WooCommerce\REST
 *
 * @author weDevs
 */
class AuctionController extends WC_REST_Products_Controller {
    /**
     * Endpoint namespace
     *
     * @var string
     */
    protected $namespace = 'app-bridge/v1';

    /**
     * Route name
     *
     * @var string
     */
    protected $rest_base = 'pocket-store';

    public function __construct() {
        $this->register_routes();
    }

    /**
     * Register routes
     *
     * @return void
     * @since 1.0.0
     */
    public function register_routes() {
        register_rest_route(
            $this->namespace, '/' . $this->rest_base . '/auctions/products/(?P<id>[\d]+)', [
				[
					'methods'             => WP_REST_Server::READABLE,
					'callback'            => [ $this, 'get_item' ],
					'permission_callback' => '__return_true',
					'args'                => [
						'id' => [
							'description' => __( 'Unique identifier for the resource.', 'app-bridge' ),
							'type'        => 'integer',
							'required'    => true,
						],
					],
				],
			]
        );

        register_rest_route(
            $this->namespace, '/' . $this->rest_base . '/auctions/place-bid', [
				[
					'methods'             => WP_REST_Server::CREATABLE,
					'callback'            => [ $this, 'place_bid' ],
					'permission_callback' => '__return_true',
					'args'                => [
						'id'        => [
							'description' => __( 'Auction product ID. Unique identifier for the resource.', 'app-bridge' ),
							'type'        => 'integer',
							'required'    => true,
						],
						'bid_value' => [
							'description' => __( 'Auction product bid value.', 'app-bridge' ),
							'type'        => 'float',
							'required'    => true,
						],
					],
				],
			]
        );

        register_rest_route(
            $this->namespace, '/' . $this->rest_base . '/auctions/get-current-bid', [
				[
					'methods'             => WP_REST_Server::CREATABLE,
					'callback'            => [ $this, 'get_current_auction_status' ],
					'permission_callback' => '__return_true',
					'args'                => [
						'id'        => [
							'description' => __( 'Auction product ID. Unique identifier for the resource.', 'app-bridge' ),
							'type'        => 'integer',
							'required'    => true,
						],
						'last_activity'        => [
							'description' => __( 'Auction product last activity timestamp.', 'app-bridge' ),
							'type'        => 'integer',
							'required'    => true,
						],
					],
				],
			]
        );
    }

    /**
     * Get auction product data
     *
     * @param \WP_REST_Request $request
     *
     * @return \WP_Error|\WP_HTTP_Response|\WP_REST_Response
     */
    public function get_item( $request ) {
        $response = parent::get_item( $request )->get_data();

        // Getting auction product object
        $object = new \WC_Product_Auction( absint( $response['id'] ) );

        $closed_details = [];
        $is_closed      = false;

        if ( $object->is_closed() && $object->is_started() ) {
            $is_closed      = true;
            $closed_details = $this->get_closed_details( $object );
        }

        $auction_history = apply_filters( 'woocommerce__auction_history_data', $object->auction_history() );

        if ( $object->is_started() ) {
            $auction_history[] = [
                'id'         => '',
                'date'       => $object->get_auction_start_time(),
                'bid'        => apply_filters( 'auction_history_started_text', __( 'Auction started', 'app-bridge' ), $object ),
                'userid'     => '',
                'auction_id' => '',
                'proxy'      => '',
            ];
        }

        $data['auction_details'] = [
            'is_closed'       => $is_closed,
            'closed_details'  => $closed_details,
            'auction_history' => $auction_history,
            'last_activity'   => get_option( 'simple_auction_last_activity', '0' ),
        ];

        $response = apply_filters( 'dokan_auction_rest_product_get_items', array_merge( $response, $data ) );

        return rest_ensure_response( $response );
    }

    /**
     * Places a bid for auction product
     *
     * @param \WP_REST_Request $request
     *
     * @return \WP_Error|\WP_HTTP_Response|\WP_REST_Response
     */
    public function place_bid( $request ) {
        $placed_bid = [];

        $product_id = apply_filters( 'woocommerce_place_bid_product_id', absint( $request->get_param( 'id' ) ) );
        $bid        = apply_filters( 'woocommerce_place_bid_bid', abs( round( str_replace( ',', '.', $request->get_param( 'bid_value' ) ), wc_get_price_decimals() ) ) );

        $auction      = new \WC_Product_Auction( $product_id );
        $product_type = method_exists( $auction, 'get_type' ) ? $auction->get_type() : $auction->product_type;

        $place_bid_handler = apply_filters( 'woocommerce_place_bid_handler', $product_type, $auction );

        $bid_obj = new \WC_Bid();

        if ( 'auction' === $place_bid_handler && $bid_obj->placebid( $product_id, $bid ) ) {
            // Place bid
            $placed_bid['product_id'] = $product_id;
            $placed_bid['placed']     = true;
        }

        return rest_ensure_response( $placed_bid );
    }

    /**
     * Gets current auction price
     *
     * @param \WP_REST_Request $request
     *
     * @return void|\WP_Error|\WP_HTTP_Response|\WP_REST_Response
     */
    public function get_current_auction_status( $request ) {
        $response = null;

        $last_activity = get_option( 'simple_auction_last_activity', '0' );

        if ( $last_activity === intval( $request->get_param( 'last_activity' ) ) ) {
            return rest_ensure_response( apply_filters( 'simple_auction_get_price_for_auctions', $response ) );
        }

        $response['last_activity'] = $last_activity;

        $product_id = $request->get_param( 'id' );

        $product_data = new \WC_Product_Auction( $product_id );

        if ( 'yes' === $product_data->get_auction_sealed() ) {
            return rest_ensure_response( apply_filters( 'simple_auction_get_price_for_auctions', $response ) );
        }

        $response[ $product_id ]['add_to_cart_text'] = $product_data->add_to_cart_text();
        $response[ $product_id ]['current_bidder']   = $product_data->get_auction_current_bider();

        if ( ! $product_data->is_closed() ) {
            $response[ $product_id ]['bid_value'] = $product_data->bid_value();
            $response[ $product_id ]['timer']     = $product_data->get_seconds_remaining();
            $response[ $product_id ]['activity']  = $product_data->auction_history_last( $product_id );
        }

        if ( $product_data->is_reserved() ) {
            if ( $product_data->is_reserve_met() ) {
                $response[ $product_id ]['reserve'] = apply_filters( 'reserve_bid_text', esc_html__( 'Reserve price has not been met', 'app-bridge' ) );
            } elseif ( $product_data->is_reserve_met() ) {
                $response[ $product_id ]['reserve'] = apply_filters( 'reserve_met_bid_text', esc_html__( 'Reserve price has been met', 'app-bridge' ) );
            }
        }

        return rest_ensure_response( apply_filters( 'simple_auction_get_price_for_auctions', $response ) );
    }

    /**
     * Build the closed-auction details payload (failure reason, buy-now copy,
     * highest bidder name).
     *
     * @param \WC_Product_Auction $product
     *
     * @return array<string, mixed>
     */
    protected function get_closed_details( $product ): array {
        $failed_message = '';

        if ( $product->get_auction_fail_reason() === '1' ) {
            $failed_message = __( 'Auction failed because there were no bids', 'app-bridge' );
        } elseif ( $product->get_auction_fail_reason() === '2' ) {
            $failed_message = __( 'Auction failed because item did not make it to reserve price', 'app-bridge' );
        }

        $closed_details = [
            'finished_title' => __( 'Auction has finished', 'app-bridge' ),
            'failed_message' => $failed_message,
        ];

        if ( $product->get_auction_closed() === '3' ) {
            $closed_details['closed_message'] = __( 'Product sold for buy now price', 'app-bridge' );
            $closed_details['closed_bidder']  = wc_format_decimal( $product->get_regular_price() );
        } elseif ( $product->get_auction_current_bider() ) {
            $closed_details['closed_message'] = __( 'Highest bidder was', 'app-bridge' );
            $closed_details['closed_bidder']  = get_userdata( $product->get_auction_current_bider() )->display_name;
        }

        return $closed_details;
    }
}
