<?php
/**
 * Tags REST Controller.
 *
 * Routes:
 *   GET    /titancart/v1/tags              List tags (paginated, searchable)
 *   POST   /titancart/v1/tags              Create tag
 *   PUT    /titancart/v1/tags/{id}         Rename tag
 *   DELETE /titancart/v1/tags/{id}         Delete tag
 *   POST   /titancart/v1/tags/merge        Merge tags
 *   GET    /titancart/v1/tags/{id}/products  Products with this tag
 *   POST   /titancart/v1/products/{id}/tags  Sync tags for a product
 *   GET    /titancart/v1/products/{id}/tags  Get tags for a product
 *
 * @package TitanCart\REST\Products
 */

namespace TitanCart\REST\Products;

use TitanCart\Modules\Products\TagManager;
use WP_REST_Server;
use WP_REST_Request;
use WP_REST_Response;
use WP_Error;

defined( 'ABSPATH' ) || exit;

class TagsController {

    private string $namespace = 'titancart/v1';
    private TagManager $manager;

    public function __construct() {
        $this->manager = new TagManager();
    }

    public function register_routes(): void {

        register_rest_route( $this->namespace, '/tags', [
            [
                'methods'             => WP_REST_Server::READABLE,
                'callback'            => [ $this, 'list_tags' ],
                'permission_callback' => [ $this, 'admin_permission' ],
                'args'                => [
                    'page'     => [ 'type' => 'integer', 'default' => 1 ],
                    'per_page' => [ 'type' => 'integer', 'default' => 50 ],
                    'search'   => [ 'type' => 'string' ],
                    'sort'     => [ 'type' => 'string', 'default' => 'name' ],
                    'order'    => [ 'type' => 'string', 'default' => 'ASC' ],
                ],
            ],
            [
                'methods'             => WP_REST_Server::CREATABLE,
                'callback'            => [ $this, 'create_tag' ],
                'permission_callback' => [ $this, 'admin_permission' ],
            ],
        ] );

        register_rest_route( $this->namespace, '/tags/(?P<id>\d+)', [
            [
                'methods'             => WP_REST_Server::EDITABLE,
                'callback'            => [ $this, 'update_tag' ],
                'permission_callback' => [ $this, 'admin_permission' ],
            ],
            [
                'methods'             => WP_REST_Server::DELETABLE,
                'callback'            => [ $this, 'delete_tag' ],
                'permission_callback' => [ $this, 'admin_permission' ],
            ],
        ] );

        register_rest_route( $this->namespace, '/tags/merge', [
            [
                'methods'             => WP_REST_Server::CREATABLE,
                'callback'            => [ $this, 'merge_tags' ],
                'permission_callback' => [ $this, 'admin_permission' ],
            ],
        ] );

        register_rest_route( $this->namespace, '/tags/(?P<id>\d+)/products', [
            [
                'methods'             => WP_REST_Server::READABLE,
                'callback'            => [ $this, 'get_tag_products' ],
                'permission_callback' => [ $this, 'admin_permission' ],
            ],
        ] );

        // Product-level tag routes.
        register_rest_route( $this->namespace, '/products/(?P<id>\d+)/tags', [
            [
                'methods'             => WP_REST_Server::READABLE,
                'callback'            => [ $this, 'get_product_tags' ],
                'permission_callback' => [ $this, 'admin_permission' ],
            ],
            [
                'methods'             => WP_REST_Server::CREATABLE,
                'callback'            => [ $this, 'sync_product_tags' ],
                'permission_callback' => [ $this, 'admin_permission' ],
            ],
        ] );
    }

    // ══════════════════════════════════════════════════════════════════════════

    public function list_tags( WP_REST_Request $request ): WP_REST_Response {
        $result = $this->manager->list_tags( [
            'page'     => (int) $request->get_param( 'page' ),
            'per_page' => (int) $request->get_param( 'per_page' ),
            'search'   => $request->get_param( 'search' ),
            'sort'     => $request->get_param( 'sort' ),
            'order'    => $request->get_param( 'order' ),
        ] );
        return new WP_REST_Response( $result );
    }

    public function create_tag( WP_REST_Request $request ): WP_REST_Response|WP_Error {
        $name = trim( $request->get_param( 'name' ) ?? '' );
        if ( $name === '' ) {
            return new WP_Error( 'tc_invalid', 'Tag name is required.', [ 'status' => 422 ] );
        }

        $id = $this->manager->create( $name );
        if ( ! $id ) {
            return new WP_Error( 'tc_failed', 'Failed to create tag.', [ 'status' => 500 ] );
        }

        return new WP_REST_Response( $this->manager->get_tag( $id ), 201 );
    }

    public function update_tag( WP_REST_Request $request ): WP_REST_Response|WP_Error {
        $id = (int) $request['id'];
        if ( ! $this->manager->get_tag( $id ) ) {
            return new WP_Error( 'tc_not_found', 'Tag not found.', [ 'status' => 404 ] );
        }

        $name = trim( $request->get_param( 'name' ) ?? '' );
        if ( $name === '' ) {
            return new WP_Error( 'tc_invalid', 'Tag name is required.', [ 'status' => 422 ] );
        }

        $this->manager->update( $id, [ 'name' => $name ] );
        return new WP_REST_Response( $this->manager->get_tag( $id ) );
    }

    public function delete_tag( WP_REST_Request $request ): WP_REST_Response|WP_Error {
        $id = (int) $request['id'];
        if ( ! $this->manager->get_tag( $id ) ) {
            return new WP_Error( 'tc_not_found', 'Tag not found.', [ 'status' => 404 ] );
        }
        $this->manager->delete( $id );
        return new WP_REST_Response( [ 'deleted' => true, 'id' => $id ] );
    }

    public function merge_tags( WP_REST_Request $request ): WP_REST_Response|WP_Error {
        $source_ids = $request->get_param( 'source_ids' );
        $target_id  = (int) $request->get_param( 'target_id' );

        if ( ! is_array( $source_ids ) || empty( $source_ids ) || ! $target_id ) {
            return new WP_Error( 'tc_invalid', 'source_ids (array) and target_id (int) are required.', [ 'status' => 422 ] );
        }

        $this->manager->merge( array_map( 'intval', $source_ids ), $target_id );
        return new WP_REST_Response( $this->manager->get_tag( $target_id ) );
    }

    public function get_tag_products( WP_REST_Request $request ): WP_REST_Response {
        $id = (int) $request['id'];
        $db = titancart_db();
        $products = $db->getArray(
            "SELECT p.id, pt.name, p.price, p.sku AS product_code, p.status
             FROM {$db->table('product_tags')} ptg
             INNER JOIN {$db->table('products')} p ON p.id = ptg.product_id
             LEFT JOIN {$db->table('product_translations')} pt
                 ON pt.product_id = p.id AND pt.language_code = 'en'
             WHERE ptg.tag_id = ?i
             ORDER BY pt.name ASC",
            $id
        );
        return new WP_REST_Response( $products );
    }

    public function get_product_tags( WP_REST_Request $request ): WP_REST_Response {
        return new WP_REST_Response( $this->manager->get_product_tags( (int) $request['id'] ) );
    }

    public function sync_product_tags( WP_REST_Request $request ): WP_REST_Response|WP_Error {
        $product_id = (int) $request['id'];
        $tags       = $request->get_param( 'tags' );

        if ( ! is_array( $tags ) ) {
            return new WP_Error( 'tc_invalid', 'tags must be an array of tag names.', [ 'status' => 422 ] );
        }

        $this->manager->sync_product_tags( $product_id, $tags );
        return new WP_REST_Response( $this->manager->get_product_tags( $product_id ) );
    }

    public function admin_permission(): bool {
        return current_user_can( 'manage_options' );
    }
}
