<?php
/**
 * GIS_Locations_Controller — مدیریت موقعیت جغرافیایی همه entityها
 *
 * Endpoints:
 *   GET    /acc/v1/gis/locations?entity_type=customer&entity_id=5
 *   GET    /acc/v1/gis/locations/{id}
 *   POST   /acc/v1/gis/locations
 *   PUT    /acc/v1/gis/locations/{id}
 *   DELETE /acc/v1/gis/locations/{id}
 *   GET    /acc/v1/gis/locations/map?entity_type=customer  (همه برای نمایش روی نقشه)
 */

if ( ! defined( 'ABSPATH' ) ) exit;

class GIS_Locations_Controller {

    public static function register_routes(): void {
        $ns = 'acc/v1';
        $p  = 'acc_jwt_check_permission';

        register_rest_route( $ns, '/gis/locations', [
            ['methods' => 'GET',  'callback' => [self::class,'list_locations'],  'permission_callback' => $p],
            ['methods' => 'POST', 'callback' => [self::class,'create_location'], 'permission_callback' => $p],
        ] );

        register_rest_route( $ns, '/gis/locations/map', [
            'methods' => 'GET', 'callback' => [self::class,'map_locations'], 'permission_callback' => $p,
        ] );

        register_rest_route( $ns, '/gis/locations/(?P<id>\d+)', [
            ['methods' => 'GET',    'callback' => [self::class,'get_location'],    'permission_callback' => $p],
            ['methods' => 'PUT',    'callback' => [self::class,'update_location'], 'permission_callback' => $p],
            ['methods' => 'DELETE', 'callback' => [self::class,'delete_location'], 'permission_callback' => $p],
        ] );
    }

    /** لیست موقعیت‌های یک entity */
    public static function list_locations( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $entity_type = sanitize_text_field( $req->get_param('entity_type') ?? '' );
        $entity_id   = (int) ( $req->get_param('entity_id') ?? 0 );

        $wheres = [];
        $args   = [];
        if ( $entity_type ) { $wheres[] = 'l.entity_type = %s'; $args[] = $entity_type; }
        if ( $entity_id )   { $wheres[] = 'l.entity_id = %d';   $args[] = $entity_id; }

        $where = $wheres ? 'WHERE ' . implode( ' AND ', $wheres ) : '';
        $sql   = "SELECT l.*, p.code AS parcel_code, p.block_code AS parcel_block_code
                  FROM {$wpdb->prefix}gis_locations l
                  LEFT JOIN {$wpdb->prefix}gis_parcels p ON p.id = l.parcel_id
                  {$where}
                  ORDER BY l.is_primary DESC, l.id DESC
                  LIMIT 200";

        $rows = $args ? $wpdb->get_results( $wpdb->prepare( $sql, ...$args ), ARRAY_A )
                      : $wpdb->get_results( $sql, ARRAY_A );

        return new WP_REST_Response( ['data' => $rows ?? []] );
    }

    /** یک موقعیت */
    public static function get_location( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $id  = (int) $req->get_param('id');
        $row = $wpdb->get_row( $wpdb->prepare(
            "SELECT l.*, p.code AS parcel_code
             FROM {$wpdb->prefix}gis_locations l
             LEFT JOIN {$wpdb->prefix}gis_parcels p ON p.id = l.parcel_id
             WHERE l.id = %d", $id
        ), ARRAY_A );

        if ( ! $row ) return new WP_REST_Response( ['message'=>'یافت نشد'], 404 );
        return new WP_REST_Response( ['data' => $row] );
    }

    /** افزودن موقعیت */
    public static function create_location( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $data = self::_build_data( $req );

        if ( ! $data['entity_type'] || ! $data['entity_id'] ) {
            return new WP_REST_Response( ['message'=>'entity_type و entity_id الزامی است'], 400 );
        }

        // اگر این primary است، بقیه‌ی primaryهای همان entity را غیر primary کن
        if ( $data['is_primary'] ) {
            $wpdb->update(
                "{$wpdb->prefix}gis_locations",
                ['is_primary' => 0],
                ['entity_type' => $data['entity_type'], 'entity_id' => $data['entity_id']]
            );
        }

        $wpdb->insert( "{$wpdb->prefix}gis_locations", $data );
        return new WP_REST_Response( ['id' => $wpdb->insert_id, 'success' => true], 201 );
    }

    /** ویرایش */
    public static function update_location( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $id = (int) $req->get_param('id');

        $existing = $wpdb->get_row( $wpdb->prepare(
            "SELECT entity_type, entity_id FROM {$wpdb->prefix}gis_locations WHERE id = %d", $id
        ), ARRAY_A );
        if ( ! $existing ) return new WP_REST_Response( ['message'=>'یافت نشد'], 404 );

        $data = self::_build_data( $req, true );

        // اگر primary می‌شود، بقیه را غیر primary کن
        if ( ! empty( $data['is_primary'] ) ) {
            $wpdb->update(
                "{$wpdb->prefix}gis_locations",
                ['is_primary' => 0],
                ['entity_type' => $existing['entity_type'], 'entity_id' => $existing['entity_id']]
            );
        }

        $wpdb->update( "{$wpdb->prefix}gis_locations", $data, ['id' => $id] );
        return new WP_REST_Response( ['success' => true] );
    }

    /** حذف */
    public static function delete_location( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $wpdb->delete( "{$wpdb->prefix}gis_locations", ['id' => (int) $req->get_param('id')] );
        return new WP_REST_Response( ['success' => true] );
    }

    /**
     * همه موقعیت‌ها برای نمایش روی نقشه
     * GET /gis/locations/map?entity_type=customer
     *   یا  /gis/locations/map  (همه entityها)
     */
    public static function map_locations( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $entity_types = $req->get_param('entity_type'); // می‌تواند آرایه یا CSV یا خالی باشد

        $wheres = ['l.lat IS NOT NULL AND l.lng IS NOT NULL'];
        $args   = [];

        if ( $entity_types ) {
            if ( is_string( $entity_types ) && strpos( $entity_types, ',' ) !== false ) {
                $entity_types = array_filter( array_map( 'trim', explode( ',', $entity_types ) ) );
            }
            if ( is_array( $entity_types ) ) {
                $placeholders = implode( ',', array_fill( 0, count( $entity_types ), '%s' ) );
                $wheres[]     = "l.entity_type IN ({$placeholders})";
                foreach ( $entity_types as $t ) $args[] = sanitize_text_field( $t );
            } else {
                $wheres[] = 'l.entity_type = %s';
                $args[]   = sanitize_text_field( $entity_types );
            }
        }

        $where = 'WHERE ' . implode( ' AND ', $wheres );
        $sql   = "SELECT l.id, l.entity_type, l.entity_id, l.label, l.location_type,
                         l.address, l.lat, l.lng, l.parcel_id, l.is_primary
                  FROM {$wpdb->prefix}gis_locations l
                  {$where}
                  LIMIT 5000";

        $rows = $args ? $wpdb->get_results( $wpdb->prepare( $sql, ...$args ), ARRAY_A )
                      : $wpdb->get_results( $sql, ARRAY_A );

        return new WP_REST_Response( ['data' => $rows ?? []] );
    }

    /** ساخت آرایه data از request */
    private static function _build_data( WP_REST_Request $req, bool $partial = false ): array {
        $data = [];
        $fields = [
            'entity_type'   => 'text',
            'entity_id'     => 'int',
            'label'         => 'text',
            'location_type' => 'text',
            'address'       => 'textarea',
            'lat'           => 'float',
            'lng'           => 'float',
            'parcel_id'     => 'int_nullable',
            'is_primary'    => 'bool',
            'notes'         => 'textarea',
        ];

        foreach ( $fields as $key => $type ) {
            $v = $req->get_param( $key );
            if ( $partial && $v === null ) continue;

            switch ( $type ) {
                case 'int':
                    $data[ $key ] = (int) $v;
                    break;
                case 'int_nullable':
                    $data[ $key ] = $v ? (int) $v : null;
                    break;
                case 'float':
                    $data[ $key ] = $v !== null && $v !== '' ? (float) $v : null;
                    break;
                case 'bool':
                    $data[ $key ] = $v ? 1 : 0;
                    break;
                case 'textarea':
                    $data[ $key ] = sanitize_textarea_field( (string) $v );
                    break;
                default:
                    $data[ $key ] = sanitize_text_field( (string) $v );
            }
        }
        return $data;
    }
}
