<?php
/**
 * Customer Fields REST API Controller.
 *
 * Endpoints:
 *   GET  /titancart/v1/customer-fields           List all fields grouped by section
 *   PUT  /titancart/v1/customer-fields            Bulk update (position, is_visible, is_required)
 *   POST /titancart/v1/customer-fields            Add a custom field
 *   DELETE /titancart/v1/customer-fields/{id}      Delete a non-system field
 *
 * @package TitanCart\REST\Settings
 */

namespace TitanCart\REST\Settings;

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

defined( 'ABSPATH' ) || exit;

class CustomerFieldsController {

    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, '/customer-fields', [
            [
                'methods'             => WP_REST_Server::READABLE,
                'callback'            => [ $this, 'get_fields' ],
                'permission_callback' => [ $this, 'admin_permission' ],
            ],
            [
                // Explicit PUT/PATCH only — WP_REST_Server::EDITABLE includes
                // POST, which would shadow the CREATABLE handler below since
                // the first matching endpoint wins. (S127.C-1 fix)
                'methods'             => [ 'PUT', 'PATCH' ],
                'callback'            => [ $this, 'bulk_update' ],
                'permission_callback' => [ $this, 'admin_permission' ],
            ],
            [
                'methods'             => WP_REST_Server::CREATABLE,
                'callback'            => [ $this, 'create_field' ],
                'permission_callback' => [ $this, 'admin_permission' ],
            ],
        ] );

        register_rest_route( $this->namespace, '/customer-fields/(?P<id>\d+)', [
            [
                'methods'             => WP_REST_Server::DELETABLE,
                'callback'            => [ $this, 'delete_field' ],
                'permission_callback' => [ $this, 'admin_permission' ],
            ],
        ] );
    }

    // ══════════════════════════════════════════════════════════════════════════
    // HANDLERS
    // ══════════════════════════════════════════════════════════════════════════

    /** GET /customer-fields — returns fields grouped by section */
    public function get_fields( WP_REST_Request $request ): WP_REST_Response {
        $rows = $this->db->getArray(
            "SELECT * FROM {$this->db->table('customer_fields')} ORDER BY section ASC, position ASC, id ASC"
        );

        $sections = [
            'shipping' => [ 'title' => 'Shipping address',       'fields' => [] ],
            'contact'  => [ 'title' => 'Contact information',    'fields' => [] ],
            'billing'  => [ 'title' => 'Billing address',        'fields' => [] ],
        ];

        foreach ( $rows as $row ) {
            $sec = $row['section'];
            if ( isset( $sections[ $sec ] ) ) {
                $sections[ $sec ]['fields'][] = $row;
            }
        }

        return new WP_REST_Response( $sections );
    }

    /** PUT /customer-fields — bulk update positions, visibility, required */
    public function bulk_update( WP_REST_Request $request ): WP_REST_Response|WP_Error {
        $body   = $request->get_json_params() ?: [];
        $fields = $body['fields'] ?? [];

        if ( ! is_array( $fields ) || empty( $fields ) ) {
            return new WP_Error( 'tc_invalid', __( 'No fields data provided.', 'titancart-lite' ), [ 'status' => 422 ] );
        }

        foreach ( $fields as $f ) {
            $id = (int) ( $f['id'] ?? 0 );
            if ( ! $id ) continue;

            $set = [];
            if ( isset( $f['position'] ) )    $set['position']    = (int) $f['position'];
            if ( isset( $f['is_visible'] ) )  $set['is_visible']  = ! empty( $f['is_visible'] ) ? 1 : 0;
            if ( isset( $f['is_required'] ) ) $set['is_required'] = ! empty( $f['is_required'] ) ? 1 : 0;
            if ( isset( $f['description'] ) ) $set['description'] = sanitize_text_field( $f['description'] );

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

        return new WP_REST_Response( [ 'success' => true, 'updated' => count( $fields ) ] );
    }

    /** POST /customer-fields — add a custom field */
    public function create_field( WP_REST_Request $request ): WP_REST_Response|WP_Error {
        $body = $request->get_json_params() ?: [];

        $section    = sanitize_key( $body['section'] ?? '' );
        $field_name = sanitize_key( $body['field_name'] ?? '' );
        $description = sanitize_text_field( $body['description'] ?? '' );

        if ( ! in_array( $section, [ 'shipping', 'contact', 'billing' ], true ) ) {
            return new WP_Error( 'tc_invalid', __( 'Invalid section.', 'titancart-lite' ), [ 'status' => 422 ] );
        }
        if ( ! $field_name || ! $description ) {
            return new WP_Error( 'tc_invalid', __( 'Field name and description are required.', 'titancart-lite' ), [ 'status' => 422 ] );
        }

        // Check duplicate.
        $existing = $this->db->getField(
            "SELECT id FROM {$this->db->table('customer_fields')} WHERE section = ?s AND field_name = ?s LIMIT 1",
            $section, $field_name
        );
        if ( $existing ) {
            return new WP_Error( 'tc_duplicate', __( 'This field already exists in this section.', 'titancart-lite' ), [ 'status' => 422 ] );
        }

        // Get max position.
        $max_pos = (int) $this->db->getField(
            "SELECT MAX(position) FROM {$this->db->table('customer_fields')} WHERE section = ?s",
            $section
        );

        $this->db->insert( 'customer_fields', [
            'section'     => $section,
            'field_name'  => $field_name,
            'field_type'  => sanitize_key( $body['field_type'] ?? 'input' ),
            'description' => $description,
            'position'    => $max_pos + 10,
            'is_visible'  => ! empty( $body['is_visible'] ) ? 1 : 0,
            'is_required' => ! empty( $body['is_required'] ) ? 1 : 0,
            'is_system'   => 0,
            'status'      => 'active',
        ] );

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

        return new WP_REST_Response(
            $this->db->getRow( "SELECT * FROM {$this->db->table('customer_fields')} WHERE id = ?i LIMIT 1", $id ),
            201
        );
    }

    /** DELETE /customer-fields/{id} — delete a non-system field */
    public function delete_field( WP_REST_Request $request ): WP_REST_Response|WP_Error {
        $id  = (int) $request->get_param( 'id' );
        $row = $this->db->getRow(
            "SELECT * FROM {$this->db->table('customer_fields')} WHERE id = ?i LIMIT 1", $id
        );
        if ( ! $row ) {
            return new WP_Error( 'tc_not_found', __( 'Field not found.', 'titancart-lite' ), [ 'status' => 404 ] );
        }
        if ( (int) $row['is_system'] === 1 ) {
            return new WP_Error( 'tc_forbidden', __( 'System fields cannot be deleted. You can hide them by unchecking "Show".', 'titancart-lite' ), [ 'status' => 422 ] );
        }

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

        // Cascade — drop any per-customer values keyed to this field_id so we
        // don't leave orphans in tc_customer_field_values. Schema lacks a real
        // FK so we cascade in application code (S127.C-1).
        $this->db->query(
            "DELETE FROM {$this->db->table('customer_field_values')} WHERE field_id = ?i", $id
        );

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

    // ══════════════════════════════════════════════════════════════════════════
    // PERMISSIONS
    // ══════════════════════════════════════════════════════════════════════════

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