<?php

namespace EstatebudConnect\Models;

if (!defined('WPINC')) {
    die();
}

use EstatebudConnect\Configs\Project as Config;
use EstatebudConnect\Configs\Defaults;
use EstatebudConnect\Core\OptionsAPI;
use EstatebudConnect\Core\Cache;
use EstatebudConnect\Services\Estatebud;
use EstatebudConnect\Utilities\Helper;
use EstatebudConnect\Interfaces\Listing as ListingInterface;

class Project implements ListingInterface
{
    public $id;
    public $external_id;
    public $source;
    public $branch_id;
    public $location_lat;
    public $location_lng;
    public $location_accuracy;
    public $owner_id;
    public $owner_type;
    public $buyer;
    public $category;
    public $street;
    public $zipcode;
    public $city;
    public $country;
    public $area_id;
    public $featured;
    public $archived;
    public $created_time;
    public $updated_time;
    public $area1_id;
    public $area1_name;
    public $area2_id;
    public $area2_name;
    public $area3_id;
    public $area3_name;
    public $reference_id;
    public $status;
    public $floor;
    public $data;
    public $distances;
    public $labels;
    public $facilities;
    public $features;
    public $title;
    public $description;
    public $project_summary;
    public $blocks;
    public $images;
    public $floorplans;
    public $videos;
    public $branch;
    public $agents;
    public $originalprice;
    public $plugins;
    public $public;
    public $matching;

    public function __construct(array $data = [])
    {
        if (isset($data['error'])) {
            throw new \Exception('Failed to initialize ' . esc_html(get_class($this)) . ': ' . esc_html($data['error'] ?? 'Unknown error'));
        }

        $this->id = $data['id'] ?? null;
        $this->external_id = $data['external_id'] ?? null;
        $this->source = $data['source'] ?? null;
        $this->branch_id = $data['branch_id'] ?? null;
        $this->location_lat = $data['location_lat'] ?? null;
        $this->location_lng = $data['location_lng'] ?? null;
        $this->location_accuracy = $data['location_accuracy'] ?? null;
        $this->owner_id = $data['owner_id'] ?? null;
        $this->owner_type = $data['owner_type'] ?? null;
        $this->buyer = $data['buyer'] ?? null;
        $this->category = $data['category'] ?? null;
        $this->street = $data['street'] ?? null;
        $this->zipcode = $data['zipcode'] ?? null;
        $this->city = $data['city'] ?? null;
        $this->country = $data['country'] ?? null;
        $this->area_id = $data['area_id'] ?? null;
        $this->public = $data['public'] ?? null;
        $this->featured = $data['featured'] ?? null;
        $this->archived = $data['archived'] ?? null;
        $this->created_time = $data['created_time'] ?? null;
        $this->updated_time = $data['updated_time'] ?? null;
        $this->area1_id = $data['area1_id'] ?? null;
        $this->area1_name = $data['area1_name'] ?? null;
        $this->area2_id = $data['area2_id'] ?? null;
        $this->area2_name = $data['area2_name'] ?? null;
        $this->area3_id = $data['area3_id'] ?? null;
        $this->area3_name = $data['area3_name'] ?? null;
        $this->reference_id = $data['reference_id'] ?? null;
        $this->status = $data['status'] ?? null;
        $this->floor = $data['floor'] ?? null;
        $this->data = $data['data'] ?? null;
        $this->distances = $data['distances'] ?? [];
        $this->labels = $data['labels'] ?? [];
        $this->facilities = $data['facilities'] ?? [];
        $this->features = $data['features'] ?? [];
        $this->title = $data['title'] ?? null;
        $this->description = $data['description'] ?? null;
        $this->project_summary = $data['project_summary'] ?? null;
        $this->blocks = $data['blocks'] ?? [];
        $this->images = $data['images'] ?? [];
        $this->floorplans = $data['floorplans'] ?? [];
        $this->videos = $data['videos'] ?? [];
        $this->branch = $data['branch'] ?? null;
        $this->agents = $data['agents'] ?? [];
        $this->originalprice = $data['originalprice'] ?? null;
        $this->plugins = $data['plugins'] ?? [];
        $this->public = (bool) ($data['public'] ?? false);
        $this->matching = (bool) ($data['matching'] ?? false);
    }

    public function get_id()
    {
        return $this->id;
    }

    public function get_image()
    {
        foreach ($this->images as $image) {
            if ($image['status'] == '1') {
                $url = $image['url'];
                break;
            }
        }

        return $url ?? Helper::get_url('assets/images/listing-placeholder.png');
    }

    public function get_images()
    {
        $images = [];

        foreach ($this->images as $image) {
            if ($image['status'] == '1') {
                $images[] = [
                    'url' => $image['url'],
                ];
            }
        }

        return $images;
    }

    public function get_floorplans()
    {
        $floorplans = [];

        foreach ($this->floorplans as $floorplan) {
            if ($floorplan['status'] == '1') {
                $floorplans[] = [
                    'url' => $floorplan['url'],
                ];
            }
        }

        return $floorplans;
    }

    public function get_videos()
    {
        $videos = [];

        foreach ($this->videos as $video) {
            $thumbnail = null;

            if ($video['platform'] === 'youtube') {
                $thumbnail = sprintf("https://i.ytimg.com/vi/%s/mqdefault.jpg", $video['platform_id']);
            }

            $videos[] = [
                'platform' => $video['platform'],
                'platform_id' => $video['platform_id'],
                'url' => $video['url'],
                'thumbnail' => $thumbnail ?? $this->get_image()
            ];
        }

        return $videos;
    }

    public function get_virtual_tours()
    {
        $virtual_tours = [];

        foreach ($this->plugins as $plugin => $data) {
            if (isset($data['virtualtour'])) {
                $virtual_tours[] = [
                    'plugin' => $plugin,
                    'url' => $data['virtualtour'],
                    'thumbnail' => $this->get_image(),
                ];
            }
        }

        return $virtual_tours;
    }

    public function get_coordinates()
    {
        if (empty($this->location_lat) || empty($this->location_lng)) {
            return false;
        }
        
        return [
            'lat' => $this->location_lat,
            'lng' => $this->location_lng,
        ];
    }

    public function get_price()
    {
        $price_data = $this->project_summary['price']['min'] ?? null;

        if (!is_array($price_data) || empty($price_data)) {
            return [
                'price' => 0,
                'vat' => false,
                'currency' => null,
            ];
        }

        $currency = key($price_data);
        $price_info = $price_data[$currency];

        $price = $price_info['amount'] ?? 0;
        $vat = $price_info['vat'] ?? false;
        $symbol = $price_info['details']['symbol'] ?? '';

        return [
            'price' => (float) $price,
            'vat' => (bool) $vat,
            'currency' => $currency,
            'symbol' => $symbol,
        ];
    }

    public function get_original_price()
    {
        $price_data = $this->originalprice;

        if (!is_array($price_data) || empty($price_data)) {
            return null;
        }

        $currency = key($price_data);
        $price_info = $price_data[$currency];

        $price = $price_info['amount'] ?? null;
        $vat = $price_info['vat'] ?? false;
        $symbol = $price_info['details']['symbol'] ?? '';

        return [
            'price' => (float) $price,
            'vat' => (bool) $vat,
            'currency' => $currency,
            'symbol' => $symbol,
        ];
    }

    public function get_labels()
    {
        $labels = [];

        if ($this->featured == '1') {
            $labels[] = [
                'id' => null,
                'name' => Helper::term('listing.label.featured'),
                'class' => 'featured',
                'color' => '#050505',
            ];
        }

        if ($this->project_summary['stats']['units']['available'] == 0) {
            $labels[] = [
                'id' => null,
                'name' => Helper::term('listing.label.sold_out'),
                'class' => 'sold-out',
                'color' => '#DC2626',
            ];
        }

        if (isset($this->labels)) {
            foreach ($this->labels as $label) {
                if ($label['public'] != '1') {
                    continue;
                }

                $term = sprintf('estatebud.property_label.%s', $label['id']);
                $value = Helper::term($term);

                $labels[] = [
                    'id' => $label['id'],
                    'name' => $term === $value ? $label['name'] : $value,
                    'class' => null,
                    'color' => '#' . $label['color'],
                ];
            }
        }

        return $labels;
    }

    public function get_reference_id()
    {
        return $this->reference_id;
    }

    public function get_bedrooms()
    {
        if (!isset($this->blocks)) {
            return null;
        }

        $bedrooms = [];
        foreach ($this->blocks as $block) {
            if (!isset($block['units'])) {
                continue;
            }

            foreach ($block['units'] as $unit) {
                $unit_bedrooms = $unit['bedrooms']['value'] ?? null;

                if ($unit_bedrooms !== null && !isset($bedrooms[$unit_bedrooms])) {
                    $bedrooms[$unit_bedrooms] = $unit_bedrooms == '0' ? Helper::term('listing.bedrooms.studio') : $unit_bedrooms;
                }
            }
        }

        ksort($bedrooms);

        return implode(', ', $bedrooms);
    }

    public function get_bathrooms()
    {
        if (!isset($this->blocks)) {
            return null;
        }

        $bathrooms = [];
        foreach ($this->blocks as $block) {
            if (!isset($block['units'])) {
                continue;
            }

            foreach ($block['units'] as $unit) {
                $unit_bathrooms = $unit['bathrooms']['value'] ?? null;

                if ($unit_bathrooms !== null && !in_array($unit_bathrooms, $bathrooms)) {
                    $bathrooms[] = $unit_bathrooms;
                }
            }
        }

        sort($bathrooms);

        return implode(', ', $bathrooms);
    }

    public function get_covered_area()
    {
        if (!isset($this->project_summary['areas']['coveredm2'])) {
            return null;
        }

        return $this->project_summary['areas']['coveredm2']['min'] .
            ' m²' .
            (isset($this->project_summary['areas']['coveredm2']['max'])
                ? ' - ' . $this->project_summary['areas']['coveredm2']['max'] . ' m²'
                : '');
    }

    public function get_plot_area()
    {
        if (!isset($this->project_summary['areas']['plotm2'])) {
            return null;
        }

        return $this->project_summary['areas']['plotm2']['min'] .
            ' m²' .
            (isset($this->project_summary['areas']['plotm2']['max'])
                ? ' - ' . $this->project_summary['areas']['plotm2']['max'] . ' m²'
                : '');
    }

    public function get_type($language = null)
    {
        $types = [];

        foreach ($this->project_summary['type'] ?? [] as $type) {
            $types[] = Helper::get_term_from_array($type, $language);
        }

        $type = implode(' · ', $types);

        if (empty($type)) {
            $type = 'Project';
        }

        return $type;
    }

    public function get_area()
    {
        $area = [];
        if (!empty($this->area3_name ?? '')) {
            $area[] = $this->area3_name;
        }
        if (!empty($this->area2_name ?? '')) {
            $area[] = $this->area2_name;
        }
        if (!empty($this->area1_name ?? '')) {
            $area[] = $this->area1_name;
        }

        return count($area) ? implode(', ', $area) : null;
    }

    public function get_title($language = null)
    {
        $title = Helper::get_term_from_array($this->title, $language);

        if (empty($title)) {
            $title = $this->generate_title($language);
        }

        return $title;
    }

    public function get_slug($language = null)
    {
        $title = $this->get_title($language);
        $slug = Helper::slugify($title);

        return $slug;
    }

    public function get_attributes()
    {
        $estatebud_field_options = Estatebud::instance()
            ->cache(Cache::TTL_1MO)
            ->get_fields(['component' => 'project']);
        $estatebud_field_names = array_column($estatebud_field_options, 'name');

        $whois = Estatebud::instance()->cache(Cache::TTL_1H)->whois();
        $currency = strtolower($whois['currency'] ?? '');

        $possible_attributes = Config::ATTRIBUTES;
        $attributes = [];
        
        foreach ($possible_attributes as $possible_attribute) {
            $name = $possible_attribute['name'];
            $icon = $possible_attribute['icon'];
            $estatebud_field_name = null;
            $value = null;
            $label = null;

            if ($name == 'delivery_date' && (!empty($this->data['deliverydatemonth']) || !empty($this->data['deliverydateyear']))) {
                $label = Helper::term('listing.estimated_delivery');

                if (!empty($this->data['deliverydatemonth'])) {
                    $value = $this->data['deliverydatemonth'];
                }
                if (!empty($this->data['deliverydateyear'])) {
                    $value .= ' / ' . $this->data['deliverydateyear'];
                }
            } else if ($name == 'energyefficiencyrating' && in_array($this->data[$name] ?? '', ['pending', 'exempt'])) {
                if ($this->data[$name] == 'pending') {
                    $value = 'Pending';
                } elseif ($this->data[$name] == 'exempt') {
                    $value = 'Exempt';
                }
            } elseif (isset($this->project_summary[$name]['min'])) {
                $value = $this->project_summary[$name]['min'] == '0' ? Helper::term('listing.bedrooms.studio') : $this->project_summary[$name]['min'];

                if (isset($this->project_summary[$name]['max'])) {
                    $value .= ' - ' . $this->project_summary[$name]['max'];
                }
            } elseif (!empty($this->project_summary[$name]) && is_array($this->project_summary[$name])) {
                foreach ($this->project_summary[$name] as $item) {
                    if (isset($item['translations'])) {
                        $value = (strlen($value) ? $value . ', ' : '') . Helper::get_term_from_array($item);
                    }
                }
            } else if (isset($this->$name['eur']['amount'])) {
                $value = $this->$name['eur']['amount'];
            } else if (isset($this->$name['translations'])) {
                $value = Helper::get_term_from_array($this->$name);
            } else if (!empty($this->$name) && is_array($this->$name)) {
                $values = [];

                foreach ($this->$name as $item) {
                    $values[] = Helper::get_term_from_array($item);
                }

                $value = implode(', ', $values);
            } else if (isset($this->data[$name]) && !is_array($this->data[$name])) {
                $value = $this->data[$name];
            }

            if (!is_null($value)) {
                if (is_null($label) && $key = array_search($estatebud_field_name ?? $name, $estatebud_field_names)) {
                    $label = $estatebud_field_options[$key]['label'];
                }

                if (!is_null($label)) {
                    $attributes[] = [
                        'name' => $name,
                        'label' => $label,
                        'icon' => $icon,
                        'value' => $value
                    ];
                }
            }
        }

        return $attributes;
    }

    public function get_facilities()
    {
        $facilites = [];
        foreach ($this->facilities as $item) {
            $facilites[] = [
                'value' => Helper::get_term_from_array($item) . ($item['value'] != '1' ? ', '.$item['value'] : '')
            ];
        }

        return $facilites;
    }

    public function get_features()
    {
        $features = [];
        foreach ($this->features as $item) {
            $features[] = [
                'value' => Helper::get_term_from_array($item)
            ];
        }

        return $features;
    }

    public function get_distances()
    {
        $estatebud_field_options = Estatebud::instance()
            ->cache(Cache::TTL_1MO)
            ->get_fields(['component' => 'project']);
        $estatebud_field_names = array_column($estatebud_field_options, 'name');

        $possible_distances = Config::DISTANCES;
        $distances = [];

        foreach ($possible_distances as $possible_distance) {
            $name = $possible_distance['name'];
            $icon = $possible_distance['icon'];
            $value = null;

            if (!empty($this->distances[$name])) {
                $unit = str_contains($name, 'km') ? 'km' : 'mi';
                $value = Helper::convert_distance($unit, $this->distances[$name]['value']);
            }

            if (!is_null($value)) {
                $label = null;

                if ($key = array_search($name, $estatebud_field_names)) {
                    $label = $estatebud_field_options[$key]['label'];
                }

                $distances[] = [
                    'name' => $name,
                    'label' => $label,
                    'icon' => $icon,
                    'value' => $value
                ];
            }
        }

        return $distances;
    }

    public function get_areas()
    {
        $estatebud_field_options = Estatebud::instance()
            ->cache(Cache::TTL_1MO)
            ->get_fields(['component' => 'project']);
        $estatebud_field_names = array_column($estatebud_field_options, 'name');
        
        $possible_areas = Config::AREAS;
        $areas = [];
        
        foreach ($possible_areas as $possible_area) {
            $name = $possible_area['name'];
            $icon = $possible_area['icon'];
            $value = null;

            if (!empty($this->areas[$name]['value'])) {
                $value = number_format_i18n($this->areas[$name]['value']) . ' m²';
            } elseif (isset($this->project_summary['areas'][$name])) {
                $value = number_format_i18n($this->project_summary['areas'][$name]['min'] ?? '') . ' m²';

                if (isset($this->project_summary['areas'][$name]['max'])) {
                    $value .= ' - ' . number_format_i18n($this->project_summary['areas'][$name]['max']) . ' m²';
                }
            }

            if (!is_null($value)) {
                $label = null;

                if ($key = array_search($name, $estatebud_field_names)) {
                    $label = $estatebud_field_options[$key]['label'];
                }

                $areas[] = [
                    'name' => $name,
                    'label' => $label,
                    'icon' => $icon,
                    'value' => $value
                ];
            }
        }

        return $areas;
    }

    public function get_planning_zones()
    {
        $planning_zones = [];

        foreach ($this->zones as $item) {
            $planning_zones[] = [
                'code' => $item['code'] ?? '-',
                'cover_factor' => isset($item['cover_factor']) ? $item['cover_factor'] . '%' : '-',
                'build_factor' => isset($item['build_factor']) ? $item['build_factor'] . '%' : '-',
                'max_height' => isset($item['max_height']) ? $item['max_height'] . ' m' : '-',
                'max_floors' => isset($item['max_floors']) ? $item['max_floors'] : '-',
                'affected_percentage' => isset($item['affected_percentage']) ? $item['affected_percentage'] . '%' : '-'
            ];
        }

        return $planning_zones;
    }

    public function get_units()
    {
        $block_items = [];
        $block_headlines = [
            'status',
            'reference',
            'type',
            'floor',
            'floors',
            'parkingspaces',
            'bedrooms',
            'bathrooms',
            'basement',
            'pool',
            'coveredm2',
            'basementm2',
            'coveredverandam2',
            'uncoveredverandam2',
            'coveredparkingm2',
            'roofgardenm2',
            'storagem2',
            'communalaream2',
            'plotm2',
            'price'
        ];

        if (isset($this->blocks)) {
            foreach ($this->blocks as $block) {
                if (!isset($block['units'])) {
                    continue;
                }

                $block_data = [
                    'block_name' => $block['block_name'] ?? '',
                    'header' => [
                        'status' => '',
                    ],
                ];

                if (isset($block['table_head_columns'])) {
                    foreach ($block['table_head_columns'] as $itemName => $itemValue) {
                        if (!in_array($itemName, $block_headlines)) {
                            continue;
                        }

                        $block_data['header'][$itemName] = $itemValue;
                    }
                }

                foreach ($block['units'] as $unit) {
                    $unit_data = [];

                    foreach ($block_data['header'] as $itemName => $itemValue) {
                        if ($itemName == 'price' && $unit['status'] != 'available') {
                            continue;
                        }

                        $value = '';
                        if (isset($unit[$itemName]['translations'])) {
                            $value = Helper::get_term_from_array($unit[$itemName]);
                        } elseif ($itemName == 'price') {
                            $currency = key($unit[$itemName] ?? []);
                            $price_info = $unit[$itemName][$currency] ?? [];

                            $price = $price_info['amount'] ?? null;
                            $vat = $price_info['vat'] ?? false;
                            $symbol = $price_info['details']['symbol'] ?? '';

                            $value = [
                                'price' => (float) $price,
                                'vat' => (bool) $vat,
                                'currency' => $currency,
                                'symbol' => $symbol,
                            ];
                        } elseif (isset($unit[$itemName]) && !is_array($unit[$itemName])) {
                            if (substr($itemName, -2) == 'm2') {
                                $value = $unit[$itemName] . ' m²';
                            } else {
                                $value = $unit[$itemName];
                            }
                        }

                        if (!empty($value)) {
                            $unit_data[$itemName] = $value;
                        }
                    }

                    $block_data['units'][] = $unit_data;
                }

                $block_items[] = $block_data;
            }
        }

        return $block_items;
    }

    public function get_page_title()
    {
        $sep = apply_filters('document_title_separator', '&#8211;');

        return $this->get_title() . ' ' . $sep . ' ' . get_bloginfo('name');
    }

    public function get_meta_description()
    {
        $text = Helper::get_term_from_array($this->description);
        $text = str_replace(["\r", "\n"], ' ', $text);
        $text = preg_replace('/\s+/', ' ', $text);
        $text = mb_substr($text, 0, 200);

        return $text;
    }

    public function get_og_image()
    {
        return $this->get_image();
    }

    public function get_og_title()
    {
        return $this->get_page_title();
    }

    public function get_og_url($language = null)
    {
        return $this->get_url($language);
    }

    public function get_og_description()
    {
        return $this->get_meta_description();
    }

    public function get_url($language = null)
    {
        return Helper::home_url('/' . Helper::slugify(Helper::term('project', 1, $language)) . '/' .  $this->get_reference_id() . '/' . trim($this->get_slug($language), '-') . '/', $language);
    }

    public function generate_title($language = null)
    {
        $active_language = Helper::get_locale();

        if (is_null($language)) {
            $language = $active_language;
        }
        
        if (in_array($this->category, ['res_sale', 'com_sale', 'land'])) {
            $title = sprintf(Helper::term('listing.generate_title.x_for_sale', 1, $language), Helper::term('project', 1, $language));
        } elseif (in_array($this->category, ['res_rent_long', 'res_rent_short'])) {
            $title = sprintf(Helper::term('listing.generate_title.x_to_rent', 1, $language), Helper::term('project', 1, $language));
        }

        $title =
            mb_substr(mb_strtoupper($title ?? '', 'UTF-8'), 0, 1, 'UTF-8') .
            mb_substr(mb_strtolower($title ?? '', 'UTF-8'), 1, null, 'UTF-8');

        return $title;
    }

    public function is_matching_enabled()
    {
        return false;
    }

    public function is_published()
    {
        return $this->public || $this->matching;
    }

    public function is_rental()
    {
        return false;
    }

    public function is_sold()
    {
        return false;
    }

    public function is_rented()
    {
        return false;
    }

    public function get_settings()
    {
        $result = OptionsAPI::instance()->get('project_listing');

        if ($result) {
            return array_merge(Defaults::PROJECT_LISTING, $result);
        } else {
            return Defaults::PROJECT_LISTING;
        }
    }

    public function save_settings($form_data)
    {
        $defaults = Defaults::PROJECT_LISTING;
        $textareas = ['legal_disclaimer'];
        $booleans = ['mortgage_calculator','brochure_show_agent','brochure_white_label'];

        $parsed_form_data = [];

        foreach ($form_data as $key => $value) {
            $key = sanitize_text_field(wp_unslash($key));
            $value = wp_unslash($value);

            if (isset($defaults[$key])) {
                if (in_array($key, $booleans)) {
                    $value = filter_var($value, FILTER_VALIDATE_BOOLEAN);
                } else if (in_array($key, $textareas)) {
                    $value = sanitize_textarea_field($value);
                } else {
                    $value = sanitize_text_field($value);
                }

                $parsed_form_data[$key] = $value;
            }
        }

        $result = OptionsAPI::instance()->update('project_listing', $parsed_form_data);

        return $result;
    }
}



                