<?php

namespace Booktics\Category\Controllers;

use Booktics\Abstracts\Base_Rest_Controller;
use Booktics\Models\Service_Model;
use WP_HTTP_Response;
use WP_REST_Server;

/**
 * Category controller
 *
 * @package Booktics/Category
 */
class Category_Controller extends Base_Rest_Controller {

    /**
     * Endpoint namespace
     *
     * @var string
     */
    protected $namespace = 'booktics/v1';

    /**
     * Route name
     *
     * @var string
     */
    protected $base = 'categories';

    /**
     * Taxonomy type
     *
     * @var string
     */
    public $taxonomy = 'booktics_service_category';

    /**
     * Register routes
     *
     * @return  void
     */
    public function register_routes(): void {
        register_rest_route(
            $this->namespace, $this->base, array(
                array(
                    'methods'             => WP_REST_Server::READABLE,
                    'callback'            => array( $this, 'get_items' ),
                    'permission_callback' => array(
                        $this,
                        'get_items_permission',
                    ),
                ),
                array(
                    'methods'             => WP_REST_Server::CREATABLE,
                    'callback'            => array( $this, 'create_item' ),
                    'permission_callback' => array(
                        $this,
                        'create_category_permission',
                    ),
                ),
                array(
                    'methods'             => WP_REST_Server::DELETABLE,
                    'callback'            => array(
                        $this,
                        'bulk_delete_items',
                    ),
                    'permission_callback' => array(
                        $this,
                        'bulk_delete_items_permission',
                    ),
                ),
            )
        );

        register_rest_route(
            $this->namespace, $this->base . '/(?P<id>[\d]+)/clone', array(
                array(
                    'methods'             => WP_REST_Server::CREATABLE,
                    'callback'            => array( $this, 'clone_item' ),
                    'permission_callback' => array(
                        $this,
                        'clone_item_permission',
                    ),
                ),
            )
        );

        register_rest_route(
            $this->namespace, $this->base . '/(?P<id>[\d]+)', array(
                array(
                    'methods'             => WP_REST_Server::READABLE,
                    'callback'            => array( $this, 'get_item' ),
                    'permission_callback' => array(
                        $this,
                        'get_item_permission',
                    ),
                ),
                array(
                    'methods'             => WP_REST_Server::DELETABLE,
                    'callback'            => array( $this, 'delete_item' ),
                    'permission_callback' => array(
                        $this,
                        'delete_item_permission',
                    ),
                ),
                array(
                    'methods'             => WP_REST_Server::EDITABLE,
                    'callback'            => array( $this, 'update_item' ),
                    'permission_callback' => array(
                        $this,
                        'update_item_permission',
                    ),
                ),
            )
        );
    }

    /**
     * Get all categories
     */
    public function get_items( $request ) {
        $per_page = $request->get_param( 'per_page' ) ? (int) $request->get_param( 'per_page' ) : 10;
        $page     = $request->get_param( 'paged' ) ? (int) $request->get_param( 'paged' ) : 1;
        $search   = $request->get_param( 'search' ) ? sanitize_text_field( $request->get_param( 'search' ) ) : '';

        $args = array(
            'taxonomy'   => $this->taxonomy,
            'hide_empty' => false,
            'orderby'    => 'term_id',
            'order'      => 'DESC',
            'number'     => $per_page,
            'offset'     => ( $page - 1 ) * $per_page,
        );

        if ( ! empty( $search ) ) {
            $args['search'] = $search;
        }

        $categories = get_terms( $args );
        $total      = wp_count_terms( $this->taxonomy );

        if ( ! empty( $categories ) && ! is_wp_error( $categories ) ) {
            foreach ( $categories as $category ) {
                $category->id       = $category->term_id;
                $services           = get_term_meta( $category->term_id, 'booktics_category_services', true );
                $services           = is_array( $services ) ? $services : array();
                $category->services = $this->get_service_details( $services );
                $category->image    = get_term_meta( $category->term_id, 'booktics_category_image', true );
                unset( $category->term_id );
            }
        }

        $response = array(
            'items'        => is_array( $categories ) ? array_values( $categories ) : [],
            'total'        => (int) $total,
            'per_page'     => $per_page,
            'last_page'    => ceil( $total / $per_page ),
            'current_page' => $page,
        );

        return $this->response( $response, __( 'Categories fetched successfully', 'booktics' ) );
    }

    /**
     * Get a single category
     *
     * @param $request Request object
     *
     * @return array|WP_HTTP_Response
     */
    public function get_item( $request ) {
        $category = get_term( absint( $request['id'] ), $this->taxonomy );

        if ( is_wp_error( $category ) ) {
            return $this->error( __( 'Category not found', 'booktics' ), 404 );
        }
        $category->id       = $category->term_id;
        $services           = get_term_meta( $category->term_id, 'booktics_category_services', true );
        $services           = is_array( $services ) ? $services : array();
        $category->services = $this->get_service_details( $services );
        $category->image    = get_term_meta( $category->term_id, 'booktics_category_image', true );

        return $this->response( $category, __( 'Category fetched successfully', 'booktics' ) );
    }

    /**
     * Create a category
     *
     * @param $request Request object
     *
     * @return array|WP_HTTP_Response
     */
    public function create_item( $request ) {
        $data     = json_decode( $request->get_body(), true );
        $name     = isset( $data['name'] ) ? sanitize_text_field( $data['name'] ) : '';
        $args     = array(
            'description' => isset( $data['description'] ) ? sanitize_textarea_field( $data['description'] ) : '',
            'parent'      => isset( $data['parent'] ) ? absint( $data['parent'] ) : 0,
        );
        if ( empty( $name ) ) {
            return $this->error( __( 'Category name is required', 'booktics' ), 400 );
        }
        $category = wp_insert_term( $name, $this->taxonomy, $args );
        if ( is_wp_error( $category ) ) {
            return $this->error( __( 'Category creation error', 'booktics' ) );
        }

        if ( isset( $data['services'] ) ) {
            update_term_meta( $category['term_id'], 'booktics_category_services', $data['services'] );
        }

        if ( ! empty( $data['image'] ) ) {
            update_term_meta( $category['term_id'], 'booktics_category_image', esc_url_raw( $data['image'] ) );
        }

        $category           = get_term( $category['term_id'], $this->taxonomy );
        $services           = get_term_meta( $category->term_id, 'booktics_category_services', true );
        $category->services = $services ?? array();
        $category->image    = get_term_meta( $category->term_id, 'booktics_category_image', true );
        $category->id       = $category->term_id;
        unset( $category->term_id );

        do_action( 'booktics_category_created', $category );

        return $this->response( $category, __( 'Category created successfully', 'booktics' ), 201 );
    }

    /**
     * Update a category
     *
     * @param $request Request object
     *
     * @return array|WP_HTTP_Response
     */
    public function update_item( $request ) {
        $data = json_decode( $request->get_body(), true );
        $args = array();
        if ( isset( $data['name'] ) ) {
            $args['name'] = sanitize_text_field( $data['name'] );
        }
        if ( isset( $data['description'] ) ) {
            $args['description'] = sanitize_textarea_field( $data['description'] );
        }
        if ( isset( $data['parent'] ) ) {
            $args['parent'] = absint( $data['parent'] );
        }

        $category = wp_update_term( absint( $request['id'] ), $this->taxonomy, $args );

        if ( is_wp_error( $category ) ) {
            return $this->error( __( 'Category update error', 'booktics' ) );
        }

        if ( isset( $data['services'] ) ) {
            update_term_meta( $category['term_id'], 'booktics_category_services', $data['services'] );
        }

        // Handle image update
        if ( isset( $data['image'] ) ) {
            if ( ! empty( $data['image'] ) ) {
                update_term_meta( $category['term_id'], 'booktics_category_image', esc_url_raw( $data['image'] ) );
            } else {
                delete_term_meta( $category['term_id'], 'booktics_category_image' );
            }
        }

        $category           = get_term( $category['term_id'], $this->taxonomy );
        $services           = get_term_meta( $category->term_id, 'booktics_category_services', true );
        $category->services = $this->get_service_details( is_array( $services ) ? $services : array() );
        $category->image    = get_term_meta( $category->term_id, 'booktics_category_image', true );
        $category->id       = $category->term_id;
        unset( $category->term_id );

        do_action( 'booktics_category_updated', $category );

        return $this->response( $category, __( 'Category updated successfully', 'booktics' ), 201 );
    }

    /**
     * Delete a category
     *
     * @param $request Request object
     *
     * @return array|WP_HTTP_Response
     */
    public function delete_item( $request ) {
        $result = wp_delete_term( absint( $request['id'] ), $this->taxonomy );

        if ( is_wp_error( $result ) ) {
            return $this->error( __( 'Category delete error', 'booktics' ) );
        }

        return $this->response( array(), __( 'Category deleted successfully', 'booktics' ) );
    }

    /**
     * Check permissions
     *
     * @return bool
     */
    public function get_items_permission( $request ) {
        return true;
    }

    /**
     * Check permission for getting a single category
     *
     * @return bool
     */
    public function get_item_permission( $request ) {
        return true;
    }

    /**
     * Check permission for creating a category
     *
     * @return bool
     */
    public function create_category_permission( $request ) {
        return current_user_can( 'manage_options' );
    }

    /**
     * Check permission for updating a category
     *
     * @return bool
     */
    public function update_item_permission( $request ) {
        return current_user_can( 'manage_options' );
    }

    /**
     * Check permission for deleting a category
     *
     * @return bool
     */
    public function delete_item_permission( $request ) {
        return current_user_can( 'manage_options' );
    }

    /**
     * Bulk delete categories
     *
     * @param $request Request object
     *
     * @return array|WP_HTTP_Response
     */
    public function bulk_delete_items( $request ) {
        $data = json_decode( $request->get_body(), true );

        if ( empty( $data['ids'] ) || ! is_array( $data['ids'] ) ) {
            return $this->error( __( 'No categories specified for deletion', 'booktics' ) );
        }

        $errors = array();
        foreach ( $data['ids'] as $id ) {
            $result = wp_delete_term( $id, $this->taxonomy );
            if ( is_wp_error( $result ) ) {
                $errors[] = $id;
            }
        }

        if ( ! empty( $errors ) ) {
            /* translators: %s: Category IDs that failed to delete */
            return $this->error( sprintf( __( 'Failed to delete some categories: %s', 'booktics' ), implode( ', ', $errors ) ) );
        }

        return $this->response( array(), __( 'Categories deleted successfully', 'booktics' ) );
    }

    /**
     * Check permission for bulk deleting categories
     *
     * @return bool
     */
    public function bulk_delete_items_permission( $request ) {
        return current_user_can( 'manage_options' );
    }

    /**
     * Get next available copy number for category name
     *
     * @param string $name Original category name
     *
     * @return int Next available number
     */
    private function get_next_copy_number( string $name ): int {
        $terms = get_terms(
            array(
                'taxonomy'   => $this->taxonomy,
                'hide_empty' => false,
                'name__like' => $name . ' (Copy',
            )
        );

        if ( empty( $terms ) ) {
            return 1;
        }

        $numbers = array();
        foreach ( $terms as $term ) {
            if ( preg_match( '/\(Copy(\s(\d+))?\)$/', $term->name, $matches ) ) {
                $numbers[] = isset( $matches[2] ) ? (int) $matches[2] : 1;
            }
        }

        return empty( $numbers ) ? 1 : max( $numbers ) + 1;
    }

    /**
     * Clone a category
     *
     * @param $request Request object
     *
     * @return array|WP_HTTP_Response
     */
    public function clone_item( $request ) {
        $category = get_term( absint( $request['id'] ), $this->taxonomy );

        if ( is_wp_error( $category ) ) {
            return $this->error( __( 'Category not found', 'booktics' ), 404 );
        }

        $args = array(
            'description' => $category->description,
            'parent'      => $category->parent,
        );

        $copy_number  = $this->get_next_copy_number( $category->name );
        $new_name     = $category->name . ' (Copy' . ( $copy_number > 1 ? ' ' . $copy_number : '' ) . ')';
        $new_category = wp_insert_term( $new_name, $this->taxonomy, $args );

        if ( is_wp_error( $new_category ) ) {
            return $this->error( __( 'Category clone error', 'booktics' ) );
        }

        $services = get_term_meta( $category->term_id, 'booktics_category_services', true );
        if ( $services ) {
            update_term_meta( $new_category['term_id'], 'booktics_category_services', $services );
        }

        $new_category           = get_term( $new_category['term_id'], $this->taxonomy );
        $new_category->services = $services ?? array();
        $new_category->id       = $new_category->term_id;
        unset( $new_category->term_id );

        return $this->response( $new_category, __( 'Category cloned successfully', 'booktics' ), 201 );
    }

    /**
     * Check permission for cloning a category
     *
     * @return bool
     */
    public function clone_item_permission( $request ) {
        return current_user_can( 'manage_options' );
    }

    /**
     * Get service details for given service IDs
     *
     * @param array $service_ids Array of service IDs
     *
     * @return array Array of service details
     */
    private function get_service_details( array $service_ids ): array {
        if ( empty( $service_ids ) ) {
            return array();
        }

        $services = array();
        foreach ( $service_ids as $service_id ) {
            $service = ( new Service_Model() )->find( $service_id );
            if ( $service ) {
                $services[] = array(
                    'id'          => $service->id,
                    'title'       => $service->title,
                    'description' => $service->content,
                    'status'      => $service->status,
                );
            }
        }

        return $services;
    }
}
