<?php

namespace WeDevs\AppBridge\Integrations\WooCommerce\REST;

use Exception;
use stdClass;
use WC_Customer;
use WC_REST_Customers_Controller;
use WP_Error;
use WP_REST_Request;
use WP_REST_Server;
use WP_User;

/**
 * Mobile-facing customer "me" endpoint.
 *
 * Routes:
 *   - GET    app-bridge/v1/wc/customers/me
 *   - PUT    app-bridge/v1/wc/customers/me
 *   - DELETE app-bridge/v1/wc/customers/me
 */
class CustomerController extends WC_REST_Customers_Controller {

    /** @var string */
    protected $namespace = 'app-bridge/v1/wc';

    /** @var string */
    protected $rest_base = 'customers';

    public function register_routes() {
        register_rest_route(
            $this->namespace, '/' . $this->rest_base . '/me', [
                [
                    'methods'             => WP_REST_Server::READABLE,
                    'callback'            => [ $this, 'get_item' ],
                    'permission_callback' => 'is_user_logged_in',
                ],
                [
                    'methods'             => WP_REST_Server::EDITABLE,
                    'callback'            => [ $this, 'update_item' ],
                    'permission_callback' => 'is_user_logged_in',
                ],
                [
                    'methods'             => WP_REST_Server::DELETABLE,
                    'callback'            => [ $this, 'delete_item' ],
                    'permission_callback' => [ $this, 'is_user_a_customer' ],
                ],
                'schema' => [ $this, 'get_public_item_schema' ],
            ]
        );
    }

    public function get_item_schema() {
        $schema = parent::get_item_schema();

        $schema['properties']['profile_picture'] = [
            'description' => __( 'Profile picture uploaded by customer', 'app-bridge' ),
            'type'        => 'object',
            'context'     => [ 'view', 'edit' ],
            'properties'  => [
                'id'            => [
                    'description' => __( 'Attachment ID', 'app-bridge' ),
                    'type'        => 'integer',
                    'context'     => [ 'view', 'edit' ],
                    'readonly'    => true,
                ],
                'media_details' => [
                    'description' => __( 'Details about the media file, specific to its type.', 'app-bridge' ),
                    'type'        => 'object',
                    'context'     => [ 'view', 'edit', 'embed' ],
                    'readonly'    => true,
                ],
            ],
        ];

        return $schema;
    }

    public function is_user_a_customer( $request ) {
        if ( ! current_user_can( 'customer' ) ) {
            return new WP_Error(
                'app_bridge_rest_not_customer',
                __( 'You are not a customer.', 'app-bridge' ),
                [ 'status' => rest_authorization_required_code() ]
            );
        }

        return true;
    }

    public function get_item( $request ) {
        $request->set_param( 'id', get_current_user_id() );

        return parent::get_item( $request );
    }

    public function update_item( $request ) {
        $request->set_param( 'id', get_current_user_id() );

        $password         = $request->get_param( 'password' );
        $current_password = $request->get_param( 'current_password' ) ?? '';

        if ( ! empty( $password ) ) {
            if ( empty( $current_password ) ) {
                return new WP_Error(
                    'app_bridge_rest_missing_current_password',
                    esc_html__( 'The current password can not be empty.', 'app-bridge' ),
                    [ 'status' => 400 ]
                );
            }

            $user = get_user_by( 'id', get_current_user_id() );
            if ( ! $user || ! wp_check_password( $current_password, $user->user_pass, $user->ID ) ) {
                return new WP_Error(
                    'app_bridge_rest_invalid_current_password',
                    esc_html__( 'The current password you entered is incorrect.', 'app-bridge' ),
                    [ 'status' => 400 ]
                );
            }
        }

        add_action( 'woocommerce_rest_insert_customer', [ $this, 'upload_profile_picture' ], 10, 3 );

        $response = parent::update_item( $request );

        remove_action( 'woocommerce_rest_insert_customer', [ $this, 'upload_profile_picture' ] );

        return $response;
    }

    public function delete_item( $request ) {
        $request->set_param( 'id', get_current_user_id() );
        $request->set_param( 'reassign', null );
        $request->set_param( 'force', true );

        return parent::delete_item( $request );
    }

    /**
     * @param WP_User         $wp_user
     * @param WP_REST_Request $request
     * @param bool            $creating
     *
     * @throws Exception
     */
    public function upload_profile_picture( $wp_user, $request, $creating ) {
        global $wp_rest_server;

        $endpoints             = $wp_rest_server->get_routes();
        $attachment_controller = $endpoints['/wp/v2/media'][0]['callback'][0];
        $attachment_response   = $attachment_controller->create_item( $request );

        if ( ! empty( $attachment_response->data['id'] ) ) {
            $customer = new WC_Customer( $wp_user->id );
            $customer->add_meta_data( 'app_bridge_customer_profile_picture_id', $attachment_response->data['id'], true );
            $customer->save_meta_data();
        }
    }

    /**
     * @param \WC_Customer $item
     */
    protected function get_formatted_item_data( $item ) {
        $data                    = parent::get_formatted_item_data( $item );
        $data['profile_picture'] = new stdClass();
        $profile_picture_id      = $item->get_meta( 'app_bridge_customer_profile_picture_id', true );
        $post                    = get_post( $profile_picture_id );

        if ( ! empty( $post->ID ) ) {
            $media_details = wp_get_attachment_metadata( $post->ID );

            if ( empty( $media_details ) ) {
                $media_details = new stdClass();
            } elseif ( ! empty( $media_details['sizes'] ) ) {
                foreach ( $media_details['sizes'] as $size => &$size_data ) {
                    if ( isset( $size_data['mime-type'] ) ) {
                        $size_data['mime_type'] = $size_data['mime-type'];
                        unset( $size_data['mime-type'] );
                    }

                    $image_src = wp_get_attachment_image_src( $post->ID, $size );
                    if ( ! $image_src ) {
                        continue;
                    }

                    $size_data['source_url'] = $image_src[0];
                }

                $full_src = wp_get_attachment_image_src( $post->ID, 'full' );

                if ( ! empty( $full_src ) ) {
                    $media_details['sizes']['full'] = [
                        'file'       => wp_basename( $full_src[0] ),
                        'width'      => $full_src[1],
                        'height'     => $full_src[2],
                        'mime_type'  => $post->post_mime_type,
                        'source_url' => $full_src[0],
                    ];
                }
            } else {
                $media_details['sizes'] = new stdClass();
            }

            $data['profile_picture'] = [
                'id'            => $post->ID,
                'media_details' => $media_details,
            ];
        }

        return $data;
    }
}
