<?php

declare( strict_types=1 );

namespace Soft_Tehnica\Freya_Sync_Service\Services;

use WP_Error;
use WP_REST_Request;
use WP_REST_Response;
use WP_Term;

defined( 'ABSPATH' ) || exit;

/**
 * Undocumented class
 */
class CategoryMetaService
{

    /** @var mixed|null */
    private $input = null;

    public function __construct()
    {
        if ( !$this->is_product_categories_api_call() ) {
            return;
        }

        $this->input = json_decode( file_get_contents( 'php://input' ) );
        add_action( 'create_product_cat', [$this, 'on_create_category'], 10, 2 );
        add_action( 'edit_product_cat', [$this, 'on_edit_category'], 10, 2 );
        add_filter( 'woocommerce_rest_prepare_product_cat', [$this, 'add_meta_data_to_category_response'], 10, 3 );
    }

    public function on_create_category( int $term_id, int $tt_id ): void
    {
        $meta_data = $this->get_category_meta_from_body( $term_id, false );

        foreach ( $meta_data as $meta ) {
            if ( !isset( $meta->key ) || !isset( $meta->value ) ) {
                continue;
            }

            update_term_meta( $term_id, $meta->key, $meta->value );
        }
    }

    public function on_edit_category( int $term_id, int $tt_id ): void
    {
        $meta_data = $this->get_category_meta_from_body( $term_id, true );

        foreach ( $meta_data as $meta ) {
            if ( !isset( $meta->key ) ) {
                continue;
            }

            if ( !isset( $meta->value ) ) {
                delete_term_meta( $term_id, $meta->key );
            } else {
                update_term_meta( $term_id, $meta->key, $meta->value );
            }
        }
    }

    /**
     * @param WP_REST_Response|WP_Error $response
     */
    public function add_meta_data_to_category_response(
        $response,
        WP_Term $category,
        WP_REST_Request $request
    ): WP_REST_Response {
        $meta_data = get_term_meta( $category->term_id );

        $payload = [];

        foreach ( $meta_data as $key => $value ) {
            if ( is_array( $value ) && count( $value ) === 1 ) {
                $value = $value[0];
            }

            $payload[] = (object) [
                'key'   => $key,
                'value' => $value,
            ];
        }

        $response->data['meta_data'] = $payload;

        return $response;
    }

    /**
     * @return object{key: string, value: mixed}[]
     */
    private function get_category_meta_from_body( int $category_id, bool $update ): array
    {
        if ( is_null( $this->input ) ) {
            return [];
        }

        if ( isset( $this->input->meta_data ) && is_array( $this->input->meta_data ) ) {
            return $this->parse_meta_list( $this->input->meta_data );
        }

        $is_batch = $this->is_batch_update();

        if ( !$is_batch ) {
            return [];
        }

        if ( !$update ) {
            $category = get_term( $category_id, 'product_cat' );

            if ( !$category || !( $category instanceof WP_Term ) ) {
                return [];
            }

            if ( !isset( $this->input->create ) || !is_array( $this->input->create ) ) {
                return [];
            }

            foreach ( $this->input->create as $i ) {
                if ( !isset( $i->name ) ) {
                    continue;
                }

                if ( $i->name === $category->name ) {
                    return isset( $i->meta_data ) && is_array( $i->meta_data )
                        ? $this->parse_meta_list( $i->meta_data )
                        : [];
                }
            }
        } else {
            if ( !isset( $this->input->update ) || !is_array( $this->input->update ) ) {
                return [];
            }

            foreach ( $this->input->update as $i ) {
                if ( !isset( $i->id ) ) {
                    continue;
                }

                if ( intval( $i->id ) === $category_id ) {
                    return isset( $i->meta_data ) && is_array( $i->meta_data )
                        ? $this->parse_meta_list( $i->meta_data )
                        : [];
                }
            }
        }

        return [];
    }

    /**
     * @param array<array-key, mixed> $list
     *
     * @return object{key: string, value: mixed}[]
     */
    private function parse_meta_list( array $list ): array
    {
        if ( !is_array( $list ) ) {
            return [];
        }

        $ret = [];

        foreach ( $list as $i ) {
            if ( !isset( $i->key ) ) {
                continue;
            }

            $payload = ['key' => $i->key];

            if ( isset( $i->value ) ) {
                $payload['value'] = $i->value;
            }

            $ret[] = (object) $payload;
        }

        return $ret;
    }

    private function is_product_categories_api_call(): bool
    {
        return strpos( $_SERVER['REQUEST_URI'], '/wc/v3/products/categories' ) !== false;
    }

    private function is_batch_update(): bool
    {
        return strpos( $_SERVER['REQUEST_URI'], '/wc/v3/products/categories/batch' ) !== false;
    }
}
