<?php

namespace Booktics\Category;

if ( ! defined( 'ABSPATH' ) ) exit;

use Booktics\Contracts\Hookable_Service_Contract;
use Booktics\Models\Service_Model;

class Category_Hooks implements Hookable_Service_Contract {

    /**
     * Register the hooks for the category service sync
     *
     * @return void
     */
    public function register() {
        add_action(
            'booktics_category_created', array(
				$this,
				'category_service_sync',
            ), 10, 1
        );
        add_action(
            'booktics_category_updated', array(
				$this,
				'category_service_sync',
            ), 10, 1
        );
    }

    /**
     * Sync the services categories
     *
     * @param $category
     * @return void
     */
    public function category_service_sync( $category ) {
        $this->remove_category_from_unlinked_services( $category->id, $category->services );
        $this->add_category_to_linked_services( $category->id, $category->services );
    }

    /**
     * Remove the category from services that are no longer linked to it
     *
     * @param int $category_id
     * @param array $new_service_ids
     * @return void
     */
    private function remove_category_from_unlinked_services( $category_id, array $new_service_ids ) {
        $args = array(
            // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Meta query is necessary for filtering booktics categories by meta fields
            'meta_query' => array(
                array(
                    'key'     => 'categories',
                    'value'   => sprintf( 'i:%d;', intval( $category_id ) ),
                    'compare' => 'LIKE',
                ),
            ),
        );

        $services = Service_Model::all( $args );
        foreach ( $services as $service ) {
            if ( $service && ! in_array( $service->id, $new_service_ids ) ) {
                $categories = $service->categories;
                $categories = array_diff( $categories, array( $category_id ) );
                Service_Model::find( $service->id )->update(
                    array(
						'categories' => array_values( $categories ),
                    )
                );
            }
        }
    }

    /**
     * Add the category to all linked services
     *
     * @param int $category_id
     * @param array $service_ids
     * @return void
     */
    private function add_category_to_linked_services( $category_id, array $service_ids ) {
        foreach ( $service_ids as $service_id ) {
            $service = Service_Model::find( $service_id );
            if ( $service ) {
                $service_categories = $service->categories;
                if ( ! in_array( $category_id, $service_categories ) ) {
                    $service_categories[] = $category_id;
                    $service->update( array( 'categories' => $service_categories ) );
                }
            }
        }
    }
}
