<?php

namespace WPIS;

include_once $_SERVER['DOCUMENT_ROOT'] . '/wp-config.php';
include_once $_SERVER['DOCUMENT_ROOT'] . '/wp-load.php';
include_once $_SERVER['DOCUMENT_ROOT'] . '/wp-includes/class-wpdb.php';
include_once $_SERVER['DOCUMENT_ROOT'] . '/wp-includes/pluggable.php';

class ApiPublic {

    const NAMESPACE = 'wpis';

    private $postTypeEstateName;
    private $headers;

    static public function init() {

        $class = new self();

		$class->headers[] = 'Cache-Control: no-cache';
		$class->headers[] = 'Accept: application/json';
		$class->headers[] = 'Content-Type: application/json';

        add_action( 'wp_ajax_nopriv_wpis_' . 'createContact', [$class, 'ltsContactHook'] );
        add_action( 'wp_ajax_wpis_ '. 'createContact', [$class, 'ltsContactHook'] );

        add_action( 'rest_api_init', [ $class, 'registerRoutes' ] );

        $class->postTypeEstateName =
            SettingsManager::get('enableImportCustomPostType') ?
            SettingsManager::get('customPostType') :
            EstatePostType::$postTypeName;

        return $class;
    }

    public function registerRoutes() {
        // Get estates endpoint
        register_rest_route(
            self::NAMESPACE,
            '/' . 'estates',
            [
                [
                    'methods'  => 'GET',
                    'callback' => [ $this, 'getEstates' ],
                    'permission_callback' => '__return_true',
                    'args' => [
                        'page'     => [ 'required' => false ],
                        'limit'    => [ 'required' => false ],
                        'filters'  => [ 'required' => false ],
                    ]
                ]
            ]
        );

        // Get filters endpoint
        register_rest_route(
            self::NAMESPACE,
            '/' . 'filters',
            [
                [
                    'methods'  => 'GET',
                    'callback' => [ $this, 'getFilters' ],
                    'permission_callback' => '__return_true'
                ]
            ]
        );

        // Send form data endpoint
        register_rest_route(
            self::NAMESPACE,
            '/' . 'form-data',
            [
                [
                    'methods'  => 'POST',
                    'callback' => [ $this, 'sendFormData' ],
                    'permission_callback' => '__return_true'
                ]
            ]
        );

        // Sync contact data
        register_rest_route(
            self::NAMESPACE,
            '/' . 'form-sync',
            [
                [
                    'methods'  => 'POST',
                    'callback' => [ $this, 'contactSync' ],
                    'permission_callback' => '__return_true'
                ]
            ]
        );
    }

    public function getEstates( $request ) {

        $page = $request->get_param('page');
        $limit = $request->get_param('limit');
        $sort = $request->get_param('sort');
        $excludeProject = true;

        $filters = $request->get_param('filters') ?? false;
        $filters = json_decode($filters);

        $metaQuery = [];

        if( $excludeProject ){
            $metaQuery[] = [
                'relation' => 'OR',
                [
                    'key' => 'wpis_properties_hasChildren',
                    'value' => '1',
                    'compare' => '!=',
                ],
                [
                    'key' => 'wpis_properties_hasChildren',
                    'compare' => 'EXISTS'
                ]
            ];
        };

        if( isset($filters->purpose) && 'null' !== $filters->purpose ){
            $metaQuery[] = [
                'key'     => 'wpis_purpose_label',
                'value'   => $filters->purpose,
                'compare' => '=',
            ];
        }

        if( isset($filters->categories) && 'null' !== $filters->categories ){
            if( is_array($filters->categories) ){
                $meta = [];
                $meta['relation'] = 'OR';
                foreach( $filters->categories as $category ){
                    $meta[] = [
                        'key'     => 'wpis_category_label',
                        'value'   => $category,
                        'compare' => '=',
                    ];
                }
                $metaQuery[] = $meta;
            }
            else {
                $metaQuery[] = [
                    'key'     => 'wpis_category_label',
                    'value'   => $filters->categories,
                    'compare' => '=',
                ];
            }
        }

        if( $filters->cities && 'null' !== $filters->cities ){
            if( is_array($filters->cities) ){
                $meta = [];
                $meta['relation'] = 'OR';
                foreach( $filters->cities as $city ){
                    $meta[] = [
                        'key'     => 'wpis_address_city',
                        'value'   => $city,
                        'compare' => '=',
                    ];
                }
                $metaQuery[] = $meta;
            }
            else {
                $metaQuery[] = [
                    'key'     => 'wpis_address_city',
                    'value'   => $filters->cities,
                    'compare' => '=',
                ];
            }
        }

        if( $filters->priceRange ){
            $filters->priceRange[1] = $filters->priceRange[1] === -1 ? 1e10 : $filters->priceRange[1];
            $metaQuery[] = [
                'key'     => 'wpis_finance_price',
                'value'   => $filters->priceRange,
                'compare' => 'BETWEEN',
                'type'    => 'SIGNED'
            ];
        }

        if( $filters->bedroomRange && $filters->bedroomRange[0] !== 0 ){
            $metaQuery[] = [
                'key'     => 'wpis_configuration_bedrooms',
                'value'   => $filters->bedroomRange,
                'compare' => 'BETWEEN',
                'type'    => 'SIGNED'
            ];
        }

        if( $filters->bathroomRange && $filters->bathroomRange[0] !== 0 ){
            $metaQuery[] = [
                'key'     => 'wpis_configuration_bathrooms',
                'value'   => $filters->bathroomRange,
                'compare' => 'BETWEEN',
                'type'    => 'SIGNED'
            ];
        }

        if( $filters->areaRange && $filters->areaRange[0] !== 0 ){
            $metaQuery[] = [
                'key'     => 'wpis_areas_total',
                'value'   => $filters->areaRange,
                'compare' => 'BETWEEN',
                'type'    => 'SIGNED'
            ];
        }

        if( $filters->hideSoldEstates ){
            $metaQuery[] = [
                'key'     => 'wpis_status_id',
                'value'   => 3,
                'compare' => '!=',
                'type'    => 'SIGNED'
            ];
        }

        $args = [
            'paged'          => $page,
            'posts_per_page' => $limit,
            'post_type'      => $this->postTypeEstateName,
            'meta_query'     => $metaQuery
        ];

        if( $sort ){
            if( !in_array( $sort, ['price-asc', 'price-desc', 'date-asc', 'date-desc'] ) ){
                $sort = 'ASC';
            }
            $sort = strtoupper($sort);
            $sortData = explode('-', $sort);
            $type = $sortData[0];
            $sort = $sortData[1];

            if( $type === 'PRICE' ) {
                $args['meta_key'] = 'wpis_finance_price';
                $args['orderby']  = 'meta_value_num';
                $args['order']    = $sort;
            }
            if( $type === 'DATE' ) {
                $args['orderby']  = 'date';
                $args['order']    = $sort;
            }
        }

        $query = new \WP_Query($args);
        $estates = [];

        foreach( $query->posts as $post ){
            $post->featured_image = get_the_post_thumbnail_url($post->ID, 'medium_large');
            $post->post_metas = [];
            foreach( PostTypesManager::$postTypeMetas as $group){
                foreach($group['fields'] as $property){
                    $meta = 'wpis_' . str_replace('.', '_', $property['reference']);
                    $post->post_metas[$meta] = get_post_meta($post->ID, $meta, true);
                }
            }
            $estates[] = $post;
        }

        return rest_ensure_response( [
            'total' => $query->found_posts,
            'limit' => $limit,
            'page'  => $page,
            'data'  => $estates
        ] );
    }

    public function getFilters( $request ) {

        $filtersConfiguration = [
            'enabledfilters' => [
                'purpose_dropdown',
                'category_dropdown',
                'city_dropdown',
                'price_dropdown',
                //'price_slider',
                'bedroom_slider',
                'bathroom_slider',
                'area_slider',
            ],
            'values' => []
        ];

        $estatesSellIDs = $this->getPostsByPurpose('À vendre', $this->postTypeEstateName);
        $estatesRentIDs = $this->getPostsByPurpose('À louer', $this->postTypeEstateName);

        $filtersConfiguration['values']['categories'] = $this->getMetaValues('wpis_category_label', $this->postTypeEstateName );
        $filtersConfiguration['values']['cities'] = $this->getMetaValues('wpis_address_city', $this->postTypeEstateName );
        $filtersConfiguration['values']['purposes'] = $this->getMetaValues('wpis_purpose_label', $this->postTypeEstateName );
        $filtersConfiguration['values']['areas'] = $this->getMetaMinMax('wpis_areas_total', $this->postTypeEstateName);
        $filtersConfiguration['values']['bedrooms'] = $this->getMetaMinMax('wpis_configuration_bedrooms', $this->postTypeEstateName);
        $filtersConfiguration['values']['bathrooms'] = $this->getMetaMinMax('wpis_configuration_bathrooms', $this->postTypeEstateName);
        $filtersConfiguration['values']['prices'] = [
            'selling' => $this->getMetaMinMax('wpis_finance_price', $this->postTypeEstateName, 'publish', $estatesSellIDs),
            'renting' => $this->getMetaMinMax('wpis_finance_price', $this->postTypeEstateName, 'publish', $estatesRentIDs)
        ];

        return rest_ensure_response( $filtersConfiguration );
    }

    private function getMetaValues( $key = '', $type = 'post', $status = 'publish' ) {

        if( empty( $key ) )
            return [];

        $wpdb = DatabaseManager::db();
        $values = $wpdb->get_col( $wpdb->prepare( "
            SELECT DISTINCT pm.meta_value FROM {$wpdb->postmeta} pm
            LEFT JOIN {$wpdb->posts} p ON p.ID = pm.post_id
            WHERE pm.meta_key = %s
            AND p.post_status = %s
            AND p.post_type = %s
            ORDER BY pm.meta_value ASC
        ", $key, $status, $type ) );

        $associativeArray = [];

        foreach($values as $value){
            $associativeArray[] = [
                'key' => $value,
                'value' => $value
            ];
        }

        return $values;
    }

    private function getMetaMinMax( $key = '', $type = 'post', $status = 'publish', $posts = [] ) {

        $wpdb = DatabaseManager::db();

        $postsCondition = '';
        if( !empty($posts) ){
            $postsCondition = 'AND p.id IN (' . implode(', ', $posts) . ')';
        }

        $range = $wpdb->get_row( $wpdb->prepare( "

        SELECT MIN(CAST(meta_value AS SIGNED)) AS min, MAX(CAST(meta_value AS SIGNED)) AS max FROM (
            SELECT pm.meta_value FROM {$wpdb->postmeta} pm
            LEFT JOIN {$wpdb->posts} p ON p.ID = pm.post_id
            WHERE pm.meta_key = %s
            AND p.post_status = %s
            AND p.post_type = %s"
            . $postsCondition .
        ") tmp
        ", $key, $status, $type ) );

        return [0, (int) $range->max];
    }

    private function getPostsByPurpose( $purpose = 'À vendre', $type = 'post', $status = 'publish' ){

        $wpdb = DatabaseManager::db();

        $values = $wpdb->get_col( $wpdb->prepare( "
            SELECT p.ID FROM {$wpdb->posts} p
            LEFT JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id
            WHERE pm.meta_key = 'wpis_purpose_label'
            AND pm.meta_value = %s
            AND p.post_status = %s
            AND p.post_type = %s
        ", $purpose, $status, $type ) );

        return $values;
    }

    public function sendFormData( $request ){
        $response = FormManager::init()->handleFormData($request->get_params());
        return rest_ensure_response( $response );
    }

    public function contactSync( $request ){
        $response = FormManager::init()->handleContactSync();
        return rest_ensure_response( $response );
    }

    public function ltsContactHook(){
        ImmosyncClient::init()->createContact();
    }
}