<?php
defined( 'ABSPATH' ) || exit;

/**
 * REST API for the Theme Builder.
 *
 * Routes registered under the existing jalpi-page-builder/v1 namespace:
 *   GET    /theme-templates             list templates (optional ?location=)
 *   POST   /theme-templates             create template
 *   GET    /theme-templates/{id}        get single template
 *   POST   /theme-templates/{id}        update title / status / priority / conditions
 *   DELETE /theme-templates/{id}        delete template
 *   GET    /theme-conditions/options    post types, categories, tags for condition UI
 */
class Jalpi_Theme_API {

    private static ?self $instance = null;

    private const NS = 'jalpi-page-builder/v1';

    public static function instance(): self {
        if ( null === self::$instance ) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    private function __construct() {
        add_action( 'rest_api_init', [ $this, 'register_routes' ] );
    }

    public function register_routes(): void {
        register_rest_route( self::NS, '/theme-templates', [
            [
                'methods'             => WP_REST_Server::READABLE,
                'callback'            => [ $this, 'list_templates' ],
                'permission_callback' => [ $this, 'permission' ],
                'args'                => [
                    'location' => [
                        'type'              => 'string',
                        'sanitize_callback' => 'sanitize_key',
                        'required'          => false,
                    ],
                ],
            ],
            [
                'methods'             => WP_REST_Server::CREATABLE,
                'callback'            => [ $this, 'create_template' ],
                'permission_callback' => [ $this, 'permission' ],
            ],
        ] );

        register_rest_route( self::NS, '/theme-templates/(?P<id>\d+)', [
            [
                'methods'             => WP_REST_Server::READABLE,
                'callback'            => [ $this, 'get_template' ],
                'permission_callback' => [ $this, 'permission' ],
            ],
            [
                'methods'             => WP_REST_Server::EDITABLE,
                'callback'            => [ $this, 'update_template' ],
                'permission_callback' => [ $this, 'permission' ],
            ],
            [
                'methods'             => WP_REST_Server::DELETABLE,
                'callback'            => [ $this, 'delete_template' ],
                'permission_callback' => [ $this, 'permission' ],
            ],
        ] );

        register_rest_route( self::NS, '/theme-conditions/options', [
            'methods'             => WP_REST_Server::READABLE,
            'callback'            => [ $this, 'get_condition_options' ],
            'permission_callback' => [ $this, 'permission' ],
        ] );
    }

    public function permission(): bool {
        return current_user_can( 'edit_theme_options' );
    }

    // ── Handlers ──────────────────────────────────────────────────────────────

    public function list_templates( WP_REST_Request $request ): WP_REST_Response {
        $args = [
            'post_type'      => Jalpi_Theme_Builder::CPT,
            'post_status'    => 'publish',
            'posts_per_page' => -1,
            'meta_key'       => '_jalpi_tpl_priority', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
            'orderby'        => 'meta_value_num',
            'order'          => 'ASC',
            'no_found_rows'  => true,
        ];

        $location = $request->get_param( 'location' );
        if ( $location ) {
            $args['meta_query'] = [ // phpcs:ignore WordPress.DB.SlowDBQuery
                [ 'key' => '_jalpi_tpl_location', 'value' => sanitize_key( $location ) ],
            ];
        }

        $posts = get_posts( $args );

        return rest_ensure_response( array_map( [ $this, 'format' ], $posts ) );
    }

    public function create_template( WP_REST_Request $request ): WP_REST_Response {
        $location    = sanitize_key( $request->get_param( 'location' ) ?: 'header' );
        $loc_labels  = Jalpi_Theme_Builder::get_locations();
        $title       = sanitize_text_field(
            $request->get_param( 'title' ) ?:
            /* translators: %s: location label (e.g. Header, Footer) */
            sprintf( __( '%s Template', 'jalpi-page-builder' ), $loc_labels[ $location ]['label'] ?? ucfirst( $location ) )
        );

        if ( ! array_key_exists( $location, Jalpi_Theme_Builder::LOCATIONS ) ) {
            return new WP_REST_Response( [ 'message' => __( 'Invalid location.', 'jalpi-page-builder' ) ], 400 );
        }

        $post_id = wp_insert_post(
            [
                'post_type'   => Jalpi_Theme_Builder::CPT,
                'post_title'  => $title,
                'post_status' => 'publish',
            ],
            true
        );

        if ( is_wp_error( $post_id ) ) {
            return new WP_REST_Response( [ 'message' => $post_id->get_error_message() ], 500 );
        }

        // Priority = (max existing priority for this location) + 10.
        $priority = $this->next_priority( $location );

        update_post_meta( $post_id, '_jalpi_tpl_location',   $location );
        update_post_meta( $post_id, '_jalpi_tpl_priority',   $priority );
        update_post_meta( $post_id, '_jalpi_tpl_status',     'inactive' );
        update_post_meta( $post_id, '_jalpi_tpl_conditions', '[]' );

        // Store a blank page scaffold so the editor doesn't start empty.
        global $wpdb;
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $wpdb->replace(
            $wpdb->prefix . 'jalpi_pages',
            [
                'post_id'   => $post_id,
                'page_data' => wp_json_encode( [ 'version' => '1.0', 'sections' => [] ] ),
                'version'   => 1,
            ],
            [ '%d', '%s', '%d' ]
        );

        return rest_ensure_response( $this->format( get_post( $post_id ) ) );
    }

    public function get_template( WP_REST_Request $request ): WP_REST_Response {
        $post = $this->load_post( (int) $request['id'] );
        if ( ! $post ) return new WP_REST_Response( [ 'message' => __( 'Not found.', 'jalpi-page-builder' ) ], 404 );

        return rest_ensure_response( $this->format( $post ) );
    }

    public function update_template( WP_REST_Request $request ): WP_REST_Response {
        $post = $this->load_post( (int) $request['id'] );
        if ( ! $post ) return new WP_REST_Response( [ 'message' => __( 'Not found.', 'jalpi-page-builder' ) ], 404 );

        $id = $post->ID;

        if ( null !== $request->get_param( 'title' ) ) {
            wp_update_post( [
                'ID'         => $id,
                'post_title' => sanitize_text_field( $request->get_param( 'title' ) ),
            ] );
        }

        if ( null !== $request->get_param( 'status' ) ) {
            $status = in_array( $request->get_param( 'status' ), [ 'active', 'inactive' ], true )
                ? $request->get_param( 'status' )
                : 'inactive';
            update_post_meta( $id, '_jalpi_tpl_status', $status );
        }

        if ( null !== $request->get_param( 'priority' ) ) {
            update_post_meta( $id, '_jalpi_tpl_priority', absint( $request->get_param( 'priority' ) ) );
        }

        if ( null !== $request->get_param( 'conditions' ) ) {
            $raw = $request->get_param( 'conditions' );
            if ( is_array( $raw ) ) {
                update_post_meta( $id, '_jalpi_tpl_conditions', wp_json_encode( $this->sanitize_conditions( $raw ) ) );
            }
        }

        delete_transient( 'jalpi_render_' . $id );

        return rest_ensure_response( $this->format( get_post( $id ) ) );
    }

    public function delete_template( WP_REST_Request $request ): WP_REST_Response {
        $post = $this->load_post( (int) $request['id'] );
        if ( ! $post ) return new WP_REST_Response( [ 'message' => __( 'Not found.', 'jalpi-page-builder' ) ], 404 );

        global $wpdb;
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $wpdb->delete( $wpdb->prefix . 'jalpi_pages', [ 'post_id' => $post->ID ], [ '%d' ] );
        wp_delete_post( $post->ID, true );

        return rest_ensure_response( [ 'deleted' => true, 'id' => $post->ID ] );
    }

    public function get_condition_options(): WP_REST_Response {
        $post_types = [];
        foreach ( get_post_types( [ 'public' => true ], 'objects' ) as $type ) {
            $post_types[] = [
                'value' => $type->name,
                'label' => $type->labels->singular_name . ' (' . $type->name . ')',
            ];
        }

        $categories = [];
        $cat_terms  = get_terms( [ 'taxonomy' => 'category', 'hide_empty' => false, 'number' => 200 ] );
        if ( ! is_wp_error( $cat_terms ) ) {
            foreach ( $cat_terms as $t ) {
                $categories[] = [ 'value' => (string) $t->term_id, 'label' => $t->name ];
            }
        }

        $tags      = [];
        $tag_terms = get_terms( [ 'taxonomy' => 'post_tag', 'hide_empty' => false, 'number' => 200 ] );
        if ( ! is_wp_error( $tag_terms ) ) {
            foreach ( $tag_terms as $t ) {
                $tags[] = [ 'value' => (string) $t->term_id, 'label' => $t->name ];
            }
        }

        return rest_ensure_response( compact( 'post_types', 'categories', 'tags' ) );
    }

    // ── Helpers ───────────────────────────────────────────────────────────────

    private function load_post( int $id ): ?WP_Post {
        $post = get_post( $id );
        return ( $post && $post->post_type === Jalpi_Theme_Builder::CPT ) ? $post : null;
    }

    private function format( WP_Post $post ): array {
        $id         = $post->ID;
        $raw_conds  = get_post_meta( $id, '_jalpi_tpl_conditions', true ) ?: '[]';
        $conditions = json_decode( $raw_conds, true ) ?: [];

        return [
            'id'         => $id,
            'title'      => $post->post_title,
            'location'   => get_post_meta( $id, '_jalpi_tpl_location', true ) ?: '',
            'status'     => get_post_meta( $id, '_jalpi_tpl_status',   true ) ?: 'inactive',
            'priority'   => (int) ( get_post_meta( $id, '_jalpi_tpl_priority', true ) ?: 10 ),
            'conditions' => $conditions,
            'editUrl'    => esc_url_raw( admin_url( 'admin.php?page=jalpi-page-builder-editor&post_id=' . $id ) ),
            'previewUrl' => esc_url_raw( Jalpi_Theme_Builder::get_preview_url( $id ) ),
            'modified'   => get_the_modified_date( 'Y-m-d H:i', $post ),
        ];
    }

    private function sanitize_conditions( array $conditions ): array {
        $valid_types = [
            'entire_site', 'singular', 'post_type', 'all_archives',
            'category', 'tag', 'post_id', 'author', 'search', '404',
        ];

        $clean = [];
        foreach ( $conditions as $c ) {
            if ( ! is_array( $c ) ) continue;
            $type = sanitize_key( $c['type'] ?? '' );
            if ( ! in_array( $type, $valid_types, true ) ) continue;

            $operator = in_array( $c['operator'] ?? 'is', [ 'is', 'is_not' ], true )
                ? $c['operator']
                : 'is';

            $clean[] = [
                'type'     => $type,
                'operator' => $operator,
                'value'    => sanitize_text_field( $c['value'] ?? '' ),
                'label'    => sanitize_text_field( $c['label'] ?? '' ),
            ];
        }

        return $clean;
    }

    private function next_priority( string $location ): int {
        // phpcs:ignore WordPress.DB.SlowDBQuery
        $ids = get_posts( [
            'post_type'      => Jalpi_Theme_Builder::CPT,
            'post_status'    => 'publish',
            'meta_query'     => [ [ 'key' => '_jalpi_tpl_location', 'value' => $location ] ], // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
            'fields'         => 'ids',
            'posts_per_page' => -1,
            'no_found_rows'  => true,
        ] );

        $max = 0;
        foreach ( $ids as $eid ) {
            $p = (int) get_post_meta( $eid, '_jalpi_tpl_priority', true );
            if ( $p > $max ) $max = $p;
        }

        return $max + 10;
    }
}
