<?php
/**
 * TitanCart Calendar REST Controller
 *
 * @package TitanCart\REST\Calendar
 */

namespace TitanCart\REST\Calendar;

use TitanCart\Modules\Calendar\CalendarManager;
use WP_REST_Request;
use WP_REST_Response;

defined( 'ABSPATH' ) || exit;

class CalendarController {

    private string $ns = 'titancart/v1';
    private ?CalendarManager $mgr = null;

    private function mgr(): CalendarManager {
        if ( ! $this->mgr ) $this->mgr = new CalendarManager();
        return $this->mgr;
    }

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

    public function register_routes(): void {
        register_rest_route( $this->ns, '/calendar/events', [
            [ 'methods' => 'GET',  'callback' => [ $this, 'list_events' ],  'permission_callback' => [ $this, 'admin_check' ] ],
            [ 'methods' => 'POST', 'callback' => [ $this, 'create_event' ], 'permission_callback' => [ $this, 'admin_check' ] ],
        ] );

        register_rest_route( $this->ns, '/calendar/events/(?P<id>\d+)', [
            [ 'methods' => 'GET',    'callback' => [ $this, 'get_event' ],    'permission_callback' => [ $this, 'admin_check' ] ],
            [ 'methods' => 'PUT',    'callback' => [ $this, 'update_event' ], 'permission_callback' => [ $this, 'admin_check' ] ],
            [ 'methods' => 'DELETE', 'callback' => [ $this, 'delete_event' ], 'permission_callback' => [ $this, 'admin_check' ] ],
        ] );
    }

    public function list_events( WP_REST_Request $req ): WP_REST_Response {
        // wp_date() (site timezone) is deliberate: month-window defaults should be
        // the SITE's current month, not UTC's — date() here was silently UTC because
        // WP pins PHP's timezone to UTC at bootstrap.
        $from = $req->get_param( 'from' ) ?: wp_date( 'Y-m-01' );
        $to   = $req->get_param( 'to' )   ?: wp_date( 'Y-m-t' );
        return new WP_REST_Response( $this->mgr()->get_events( $from, $to ) );
    }

    public function get_event( WP_REST_Request $req ): WP_REST_Response {
        $item = $this->mgr()->get( (int) $req['id'] );
        return $item ? new WP_REST_Response( $item ) : new WP_REST_Response( [ 'error' => 'Not found' ], 404 );
    }

    public function create_event( WP_REST_Request $req ): WP_REST_Response {
        $data = $req->get_json_params();
        if ( empty( $data['title'] ) || empty( $data['event_date'] ) ) {
            return new WP_REST_Response( [ 'error' => 'Title and date are required' ], 422 );
        }
        $id = $this->mgr()->create( $data );
        // KI-86 (failure-reporting half) — create() hands back insert_id ⇒ 0 on a failed
        // insert ⇒ get(0) is null ⇒ WP core emits 201 with a ZERO-BYTE body
        // (class-wp-rest-server.php L536-538: `null === $result` ⇒ return, echoing
        // nothing). The required-field half is already covered above (L56).
        if ( ! $id ) {
            return new WP_REST_Response( [ 'error' => 'Failed to create event' ], 500 );
        }
        return new WP_REST_Response( $this->mgr()->get( $id ), 201 );
    }

    public function update_event( WP_REST_Request $req ): WP_REST_Response {
        $this->mgr()->update( (int) $req['id'], $req->get_json_params() ?: [] ); // KI-85
        // KI-87 (S407) — a missing id used to return 200 + a ZERO-BYTE body. Mirrors
        // get_event() L51. The preceding update() matched 0 rows, so there is no write.
        $item = $this->mgr()->get( (int) $req['id'] );
        return $item ? new WP_REST_Response( $item ) : new WP_REST_Response( [ 'error' => 'Not found' ], 404 );
    }

    public function delete_event( WP_REST_Request $req ): WP_REST_Response {
        $this->mgr()->delete( (int) $req['id'] );
        return new WP_REST_Response( [ 'deleted' => true ] );
    }
}
