<?php
namespace Booktics\Service;

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

use Booktics\Category\Controllers\Category_Controller;
use Booktics\Contracts\Hookable_Service_Contract;

class Service_Hooks implements Hookable_Service_Contract {

    /**
     * Register the service hooks.
     *
     * @return void
     */
    public function register() {
        add_filter(
            'booktics_service_args', array(
				$this,
				'booktics_service_args',
            ), 10, 2
        );
        add_action(
            'booktics_service_created', array(
				$this,
				'service_category_sync',
            ), 10, 2
        );

        add_action(
            'booktics_service_updated', array(
				$this,
				'service_category_sync',
            ), 10, 2
        );
    }

    /**
     * Filter service arguments based on the current user's role.
     *
     * @param array $args The service arguments.
     * @param $request
     *
     * @return array The filtered service arguments.
     */
    public function booktics_service_args( $args, $request ) {
        $current_user = wp_get_current_user();
        $roles        = $current_user->roles;
        if ( in_array( 'administrator', $roles, true ) ) {
            return $args;
        }

        if ( in_array( 'booktics_team_member', $roles, true ) ) {
            $args['meta_query'][] = array(
                'key'     => 'team_member',
                'value'   => sprintf( 'i:%d;', intval( $current_user->ID ) ),
                'compare' => 'LIKE',
            );
        }

        return $args;
    }

    /**
     * Add service to specified categories
     *
     * @param int $service_id
     * @param array $category_ids
     *
     * @return void
     */
    private function add_service_to_categories( $service_id, array $category_ids ) {
        if ( empty( $category_ids ) ) {
            return;
        }

        $category_taxonomy = ( new Category_Controller() )->taxonomy;

        foreach ( $category_ids as $category_id ) {
            $category = get_term_by( 'id', $category_id, $category_taxonomy );
            if ( $category && ! is_wp_error( $category ) ) {
                $services = get_term_meta( $category->term_id, 'booktics_category_services', true );
                if ( ! is_array( $services ) ) {
                    $services = array();
                }
                if ( ! in_array( $service_id, $services ) ) {
                    $services[] = $service_id;
                    update_term_meta( $category->term_id, 'booktics_category_services', $services );
                }
            }
        }
    }

    /**
     * Remove service from categories except specified ones
     *
     * @param int $service_id
     * @param array $exclude_category_ids Categories to keep the service in
     *
     * @return void
     */
    private function remove_service_from_categories( $service_id, array $exclude_category_ids = array() ) {
        $category_taxonomy = ( new Category_Controller() )->taxonomy;

        $existing_categories = get_terms(
            array(
				'taxonomy'   => $category_taxonomy,
                // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Meta query is necessary for filtering services by service categories.
				'meta_query' => array(
					array(
						'key'     => 'booktics_category_services',
						'value'   => $service_id,
						'compare' => 'LIKE',
					),
				),
				'hide_empty' => false,
            )
        );

        if ( ! empty( $existing_categories ) && ! is_wp_error( $existing_categories ) ) {
            foreach ( $existing_categories as $existing_category ) {
                if ( in_array( $existing_category->term_id, $exclude_category_ids ) ) {
                    continue;
                }

                $services = get_term_meta( $existing_category->term_id, 'booktics_category_services', true );
                if ( is_array( $services ) ) {
                    $services = array_diff( $services, array( $service_id ) );
                    update_term_meta( $existing_category->term_id, 'booktics_category_services', $services );
                }
            }
        }
    }


    /**
     * @param $service
     * @param $request
     *
     * @return void
     */
    public function service_category_sync( $service, $request ) {
        // Remove service from categories except the new ones
        $this->remove_service_from_categories( $service->id, $service->categories );

        // Add service to new categories
        $this->add_service_to_categories( $service->id, $service->categories );
    }
}
