<?php
/**
 * Order Statuses REST API Controller (Settings CRUD).
 *
 * Endpoints:
 *   GET    /titancart/v1/order-statuses           List all statuses with translations
 *   POST   /titancart/v1/order-statuses           Create a new status
 *   PUT    /titancart/v1/order-statuses/{id}      Update a status
 *   DELETE /titancart/v1/order-statuses/{id}      Delete a non-default status
 *
 * @package TitanCart\REST\Settings
 */

namespace TitanCart\REST\Settings;

use TitanCart\DB\Database;
use TitanCart\Core\LogService;
use WP_REST_Server;
use WP_REST_Request;
use WP_REST_Response;
use WP_Error;

defined( 'ABSPATH' ) || exit;

class OrderStatusController {

    private string $namespace = 'titancart/v1';
    private Database $db;

    public function __construct() {
        $this->db = titancart_db();
    }

    public function register_routes(): void {

        register_rest_route( $this->namespace, '/order-statuses', [
            [
                'methods'             => WP_REST_Server::READABLE,
                'callback'            => [ $this, 'get_statuses' ],
                'permission_callback' => [ $this, 'admin_permission' ],
            ],
            [
                'methods'             => WP_REST_Server::CREATABLE,
                'callback'            => [ $this, 'create_status' ],
                'permission_callback' => [ $this, 'admin_permission' ],
            ],
        ] );

        register_rest_route( $this->namespace, '/order-statuses/(?P<id>\d+)', [
            [
                'methods'             => WP_REST_Server::EDITABLE,
                'callback'            => [ $this, 'update_status' ],
                'permission_callback' => [ $this, 'admin_permission' ],
            ],
            [
                'methods'             => WP_REST_Server::DELETABLE,
                'callback'            => [ $this, 'delete_status' ],
                'permission_callback' => [ $this, 'admin_permission' ],
            ],
        ] );
    }

    /** GET /order-statuses */
    public function get_statuses( WP_REST_Request $request ): WP_REST_Response {
        $type  = sanitize_key( $request->get_param( 'type' ) ?? '' );
        $where = '';
        $args  = [];

        if ( $type && in_array( $type, [ 'order', 'fulfillment', 'gift_card' ], true ) ) {
            $where = 'WHERE os.type = ?s';
            $args  = [ $type ];
        }

        $rows = $this->db->getArray(
            "SELECT os.*, COALESCE(ost.name, os.handle) AS name, ost.description
             FROM {$this->db->table('order_statuses')} os
             LEFT JOIN {$this->db->table('order_status_translations')} ost
                 ON ost.status_id = os.id AND ost.language_code = 'en'
             {$where}
             ORDER BY os.position ASC, os.id ASC",
            ...$args
        );
        return new WP_REST_Response( $rows );
    }

    /** POST /order-statuses */
    public function create_status( WP_REST_Request $request ): WP_REST_Response|WP_Error {
        $body   = $request->get_json_params() ?: [];
        $handle = sanitize_key( $body['handle'] ?? '' );
        $name   = sanitize_text_field( $body['name'] ?? '' );
        $type   = sanitize_key( $body['type'] ?? 'order' );

        if ( ! in_array( $type, [ 'order', 'fulfillment', 'gift_card' ], true ) ) {
            $type = 'order';
        }

        if ( ! $handle || ! $name ) {
            return new WP_Error( 'tc_invalid', __( 'Handle and name are required.', 'titancart-lite' ), [ 'status' => 422 ] );
        }

        $existing = $this->db->getField(
            "SELECT id FROM {$this->db->table('order_statuses')} WHERE handle = ?s LIMIT 1", $handle
        );
        if ( $existing ) {
            return new WP_Error( 'tc_duplicate', __( 'A status with this handle already exists.', 'titancart-lite' ), [ 'status' => 422 ] );
        }

        $max_pos = (int) $this->db->getField(
            "SELECT MAX(position) FROM {$this->db->table('order_statuses')}"
        );

        $this->db->insert( 'order_statuses', [
            'handle'          => $handle,
            'type'            => $type,
            'color'           => sanitize_hex_color( $body['color'] ?? '#71797E' ) ?: '#71797E',
            'position'        => $max_pos + 10,
            'is_default'      => 0,
            'notify_customer' => ! empty( $body['notify_customer'] ) ? 1 : 0,
            'stock_action'    => in_array( $body['stock_action'] ?? '', [ 'none', 'reduce', 'restore' ] ) ? $body['stock_action'] : 'none',
        ] );

        $id = $this->db->lastInsertId();
        if ( ! $id ) {
            return new WP_Error( 'tc_create_failed', __( 'Failed to create status.', 'titancart-lite' ), [ 'status' => 500 ] );
        }

        $this->db->insert( 'order_status_translations', [
            'status_id'     => $id,
            'language_code' => 'en',
            'name'          => $name,
            'description'   => sanitize_text_field( $body['description'] ?? '' ),
        ] );

        LogService::info( 'general', 'create', 'Order status created: ' . $name . ' (#' . $id . ')', [
            'object_type' => 'order_status',
            'object_id'   => $id,
            'handle'      => $handle,
            'type'        => $type,
        ] );

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

    /** PUT /order-statuses/{id} */
    public function update_status( WP_REST_Request $request ): WP_REST_Response|WP_Error {
        $id   = (int) $request->get_param( 'id' );
        $body = $request->get_json_params() ?: [];

        $row = $this->db->getRow(
            "SELECT * FROM {$this->db->table('order_statuses')} WHERE id = ?i LIMIT 1", $id
        );
        if ( ! $row ) {
            return new WP_Error( 'tc_not_found', __( 'Status not found.', 'titancart-lite' ), [ 'status' => 404 ] );
        }

        $set = [];
        if ( isset( $body['color'] ) )           $set['color']           = sanitize_hex_color( $body['color'] ) ?: '#71797E';
        if ( isset( $body['position'] ) )        $set['position']        = (int) $body['position'];
        if ( isset( $body['notify_customer'] ) ) $set['notify_customer'] = ! empty( $body['notify_customer'] ) ? 1 : 0;
        if ( isset( $body['stock_action'] ) && in_array( $body['stock_action'], [ 'none', 'reduce', 'restore' ] ) ) {
            $set['stock_action'] = $body['stock_action'];
        }

        if ( ! empty( $set ) ) {
            $this->db->update( 'order_statuses', $set, [ 'id' => $id ] );
        }

        // Update translation.
        if ( isset( $body['name'] ) || isset( $body['description'] ) ) {
            $trans = $this->db->getRow(
                "SELECT id FROM {$this->db->table('order_status_translations')} WHERE status_id = ?i AND language_code = 'en' LIMIT 1", $id
            );
            $t_set = [];
            if ( isset( $body['name'] ) )        $t_set['name']        = sanitize_text_field( $body['name'] );
            if ( isset( $body['description'] ) ) $t_set['description'] = sanitize_text_field( $body['description'] );

            if ( $trans ) {
                $this->db->update( 'order_status_translations', $t_set, [ 'id' => (int) $trans['id'] ] );
            } else {
                $this->db->insert( 'order_status_translations', array_merge( $t_set, [
                    'status_id' => $id, 'language_code' => 'en',
                ] ) );
            }
        }

        LogService::info( 'general', 'update', 'Order status updated: #' . $id, [
            'object_type' => 'order_status',
            'object_id'   => $id,
        ] );

        return new WP_REST_Response( $this->get_single( $id ) );
    }

    /** DELETE /order-statuses/{id} */
    public function delete_status( WP_REST_Request $request ): WP_REST_Response|WP_Error {
        $id  = (int) $request->get_param( 'id' );
        $row = $this->db->getRow(
            "SELECT * FROM {$this->db->table('order_statuses')} WHERE id = ?i LIMIT 1", $id
        );
        if ( ! $row ) {
            return new WP_Error( 'tc_not_found', __( 'Status not found.', 'titancart-lite' ), [ 'status' => 404 ] );
        }
        if ( (int) $row['is_default'] === 1 ) {
            return new WP_Error( 'tc_forbidden', __( 'Cannot delete the default order status.', 'titancart-lite' ), [ 'status' => 422 ] );
        }

        // Check if any orders use this status.
        $in_use = $this->db->getField(
            "SELECT COUNT(*) FROM {$this->db->table('orders')} WHERE status = ?s LIMIT 1",
            $row['handle']
        );
        if ( (int) $in_use > 0 ) {
            return new WP_Error( 'tc_in_use', sprintf(
                /* translators: %d: number of orders currently using this status. */
                __( 'Cannot delete — %d order(s) currently use this status. Change their status first.', 'titancart-lite' ),
                (int) $in_use
            ), [ 'status' => 422 ] );
        }

        $this->db->query( "DELETE FROM {$this->db->table('order_status_translations')} WHERE status_id = ?i", $id );
        $this->db->query( "DELETE FROM {$this->db->table('order_statuses')} WHERE id = ?i LIMIT 1", $id );

        LogService::info( 'general', 'delete', 'Order status deleted: ' . $row['handle'] . ' (#' . $id . ')', [
            'object_type' => 'order_status',
            'object_id'   => $id,
            'handle'      => $row['handle'],
        ] );

        return new WP_REST_Response( [ 'deleted' => true, 'id' => $id ] );
    }

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

    private function get_single( int $id ): array {
        return $this->db->getRow(
            "SELECT os.*, COALESCE(ost.name, os.handle) AS name, ost.description
             FROM {$this->db->table('order_statuses')} os
             LEFT JOIN {$this->db->table('order_status_translations')} ost
                 ON ost.status_id = os.id AND ost.language_code = 'en'
             WHERE os.id = ?i LIMIT 1",
            $id
        ) ?: [];
    }

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