<?php

namespace inpost_shipping\Model\Quote;

class QuoteHandler
{
    /**
     * @param array $address
     * @param $ocRegistry
     *
     * @return array
     */
    public function getQuotes(array $address, $ocRegistry): array
    {
        date_default_timezone_set('Europe/Warsaw');
        $methods = $ocRegistry->db
            ->query("SELECT * FROM `".DB_PREFIX."inpost_shipping_methods` WHERE status = '1'")
            ->rows;

        $quotes = [];
        $weight = $ocRegistry->cart->getWeight();

        foreach ($methods as $method) {
            if (!$method['status']) {
                continue;
            }

            $ranges = json_decode($method['ranges'], true);

            if (empty($ranges) || !is_array($ranges)) {
                continue;
            }

            $quote_data = [];

            $deliveryService = '';
            $deliveryServiceInfo = [];

            if (!empty($method['fk_delivery_service']) && $method['fk_delivery_service'] !== 0) {
                $deliveryServiceInfo = $ocRegistry->db
                    ->query("SELECT * FROM `" . DB_PREFIX . "inpost_shipping_delivery_services` WHERE id_delivery_service ='".$method['fk_delivery_service']."'")->row;
                if (empty($deliveryServiceInfo)) {
                    continue;
                }

                $deliveryService = $deliveryServiceInfo['deliveryService'];
            }

            if (
                !empty($deliveryServiceInfo) &&
                (int)$deliveryServiceInfo['weekendDelivery'] == 1 &&
                !empty($ocRegistry->config->get('shipping_inpost_shipping_settings')['weekend_day_start']) &&
                !empty($ocRegistry->config->get('shipping_inpost_shipping_settings')['weekend_day_end']) &&
                !empty($ocRegistry->config->get('shipping_inpost_shipping_settings')['weekend_time_start']) &&
                !empty($ocRegistry->config->get('shipping_inpost_shipping_settings')['weekend_time_end'])
            ) {
                $weekDays = [
                    'monday' => 1,
                    'tuesday' => 2,
                    'wednesday' => 3,
                    'thursday' => 4,
                    'friday' => 5,
                    'saturday' => 6,
                    'sunday' => 7,
                ];

                $wdDayStart = (int)$ocRegistry->config->get('shipping_inpost_shipping_settings')['weekend_day_start'];
                $wdDayEnd = (int)$ocRegistry->config->get('shipping_inpost_shipping_settings')['weekend_day_end'];
                $wdTimeStart = $ocRegistry->config->get('shipping_inpost_shipping_settings')['weekend_time_start'];
                $wdTimeEnd = $ocRegistry->config->get('shipping_inpost_shipping_settings')['weekend_time_end'];

                $currentDay = $weekDays[strtolower(date('l'))];
                if ($currentDay < $wdDayStart) {
                    continue;
                }

                if ($currentDay <= $wdDayEnd) {
                    $timeNow = date('Y-m-d H:i:s');
                    if ($currentDay === $wdDayStart) {
                        $timeStart = sprintf('%s %s:%s', date('Y-m-d'), $wdTimeStart, date('s'));
                        if (strtotime($timeNow) < strtotime($timeStart)) {
                            continue;
                        }
                    }

                    if ($currentDay === $wdDayEnd) {
                        $timeEnd = sprintf('%s %s:%s', date('Y-m-d'), $wdTimeEnd, date('s'));
                        if (strtotime($timeNow) < strtotime($timeEnd)) {
                            continue;
                        }
                    }
                }
            }

            if (!$this->isMethodValidForOrderProducts($method['id_shipping_method'], $ocRegistry)) {
                continue;
            }

            foreach ($ranges as $geoZone) {
                $cost = null;

                if (!$geoZone['status']) {
                    continue;
                }

                $query = $ocRegistry->db->query("SELECT * FROM " . DB_PREFIX . "zone_to_geo_zone WHERE geo_zone_id = '" . (int)$geoZone['geo_zone_id'] . "' AND country_id = '" . (int)$address['country_id'] . "' AND (zone_id = '" . (int)$address['zone_id'] . "' OR zone_id = '0')");

                if (!$query->num_rows) {
                    continue;
                }

                if ($method['free_shipping']) {
                    $cost = 0.0000;
                }

                if ($cost === null) {
                    $rates = explode(',', $geoZone['range']);

                    foreach ($rates as $rate) {
                        $data = explode(':', $rate);

                        if ($data[0] >= $weight) {
                            if (isset($data[1])) {
                                $cost = $data[1];
                            }

                            break;
                        }
                    }
                }

                $lockerServices = [
                    'inpost_locker_standard',
                    'inpost_locker_allegro',
                    'inpost_locker_pass_thru',
                    'inpost_courier_c2c',
                ];

                if (!is_null($cost)) {
                    $method['logo'] = !empty($method['logo']) ? $method['logo'] : 'no_image.png';
                    $geoZoneName = $ocRegistry->db->query("SELECT * FROM `".DB_PREFIX."geo_zone` WHERE geo_zone_id = '".(int)$geoZone['geo_zone_id']."'")->row['name'];
                    $quote_data['inpost_shipping_' . $method['id_shipping_method'] . '_' . $geoZone['geo_zone_id']] = array(
                        'code' => 'inpost_shipping_' . $method['id_shipping_method'] . '.inpost_shipping_' . $method['id_shipping_method'] . '_' . $geoZone['geo_zone_id'],
                        'title' => '<img src="image/'.$method['logo'].'" alt="image/'.$method['logo'].'" class="inpost-logo-img" />' . $method['name'] . ': ' . $geoZoneName,
                        'cost' => $cost,
                        'tax_class_id' => $method['tax_class'],
                        'text' => $ocRegistry->currency->format($ocRegistry->tax->calculate($cost, $method['tax_class'], $ocRegistry->config->get('config_tax')), $ocRegistry->session->data['currency']),
                        'parcelLocker' => in_array($deliveryService, $lockerServices),
                    );
                }
            }

            if (!empty($quote_data)) {
                $quotes[] = [
                    'code' => 'inpost_shipping_' . $method['id_shipping_method'],
                    'title' => $method['name'],
                    'sort_order' => $method['sort_order'],
                    'quote' => $quote_data,
                    'error' => ''
                ];
            }
        }

        return $quotes;
    }

    /**
     * @param $idShippingMethod
     * @param $ocRegistry
     *
     * @return bool
     */
    public function isMethodValidForOrderProducts($idShippingMethod, $ocRegistry): bool
    {
        $products = $ocRegistry->cart->getProducts();
        if (empty($products)) {
            return false;
        }

        $result = true;
        foreach ($products as $product) {
            $availableCarriers = json_decode(
                $ocRegistry->db
                    ->query("SELECT * FROM `" . DB_PREFIX . "product` WHERE product_id='" . (int)$product['product_id'] . "'")
                    ->row['availableCarriers'],
                1);

            if (is_null($availableCarriers) || (count($availableCarriers) === 1 && $availableCarriers[0] === '[]')) {
                continue;
            }

            if (!in_array($idShippingMethod, $availableCarriers)) {
                $result = false;
                break;
            }
        }

        return $result;
    }
}