<?php

namespace Core\App\Controllers;

use Core\App\Support\DzLocation;
use Core\App\Support\ShippingProviderPriceResolver;
use Core\App\Services\MaystroLocationService;
use Core\App\Models\ShippingIntegrationModel;
use Core\App\Integrations\Shipping\MaystroClient;

class LocationController
{
    /**
     * ============================
     * Load Shipping Settings
     * ============================
     */
    private function loadShipping(): array
    {
        $file = ROOT_PATH . '/storage/settings/shipping.json';

        if (!file_exists($file)) {
            return [
                'mode'       => 'flat',
                'flat_price' => 0,
                'states'     => [],
                'zones'      => [],
                'pricing_provider' => '',
                'pricing_source' => 'manual',
                'pricing_fallback_manual' => 1,
                'shipping_unavailable_text' => ''
            ];
        }

        $data = json_decode(file_get_contents($file), true);

        return is_array($data) ? $data : [
            'mode'       => 'flat',
            'flat_price' => 0,
            'states'     => [],
            'zones'      => [],
            'pricing_provider' => '',
            'pricing_source' => 'manual',
            'pricing_fallback_manual' => 1,
            'shipping_unavailable_text' => ''
        ];
    }

    /**
     * ============================
     * Load Site Country
     * ============================
     */
    private function getCountry(): string
    {
        $settingsFile = ROOT_PATH . '/settings.json';

        if (!file_exists($settingsFile)) {
            return 'DZ';
        }

        $settings = json_decode(file_get_contents($settingsFile), true);

        return strtoupper($settings['country'] ?? 'DZ');
    }

    /**
     * ============================
     * REGIONS (States / Provinces)
     * ============================
     */
    public function regions()
    {
        $country = $this->getCountry();

        if ($country === 'DZ') {
            $path = ROOT_PATH . '/storage/data/states_dz.json';

            if (!file_exists($path)) {
                echo json_encode([]);
                return;
            }

            $states = DzLocation::states();
            echo json_encode($states, JSON_UNESCAPED_UNICODE);
            return;
        }

        echo json_encode([]);
    }

    /**
     * ============================
     * CITIES
     * ============================
     */
    public function cities($regionCode)
    {
        $country = $this->getCountry();

        if ($country === 'DZ') {
            $path = ROOT_PATH . '/storage/data/cities_dz.json';

            if (!file_exists($path)) {
                echo json_encode([]);
                return;
            }

            $cities = DzLocation::citiesByCode($regionCode);
            echo json_encode($cities, JSON_UNESCAPED_UNICODE);
            return;
        }

        echo json_encode([]);
    }


    private function resolveManualShippingPrice(array $shipping, string $mode, string $stateCode, string $shippingType): ?float
    {
        $price = null;

        if ($mode === 'flat') {
            $key = $shippingType === 'home' ? 'flat_home_price' : 'flat_desk_price';
            return isset($shipping[$key]) && $shipping[$key] !== '' ? (float)$shipping[$key] : null;
        }

        if ($mode === 'state') {
            if (isset($shipping['states'][$stateCode]) && isset($shipping['states'][$stateCode][$shippingType]) && $shipping['states'][$stateCode][$shippingType] !== '') {
                return (float)$shipping['states'][$stateCode][$shippingType];
            }
            return null;
        }

        if ($mode === 'zones') {
            foreach ($shipping['zones'] ?? [] as $zone) {
                if (empty($zone['regions']) || !in_array($stateCode, $zone['regions'], true)) {
                    continue;
                }
                // Zone found for this state — use its price or stop (don't fall through to next zone)
                $key = $shippingType === 'home' ? 'home_price' : 'desk_price';
                $val = $zone[$key] ?? null;
                if ($val !== null && $val !== '') {
                    return (float)$val;
                }
                return null; // Zone matched but price is empty → unavailable
            }
        }

        return null;
    }

    /**
     * ============================
     * SHIPPING PRICE API
     * ============================
     */
    public function shippingPrice($stateCode, $cityId)
    {
        // shipping_type إجباري
        $shippingType = $_GET['shipping_type'] ?? null;

        if (!in_array($shippingType, ['home', 'desk'], true)) {
            http_response_code(400);
            echo json_encode([
                'error' => 'shipping_type_required'
            ]);
            return;
        }

        $shipping = $this->loadShipping();
        $mode     = $shipping['mode'] ?? 'flat';
        $price    = null;
        $displayText = '';

        $globalSource = in_array((string)($shipping['pricing_source'] ?? 'manual'), ['manual', 'api', 'reference'], true)
            ? (string)($shipping['pricing_source'] ?? 'manual')
            : 'manual';
        $globalProvider = trim((string)($shipping['pricing_provider'] ?? ''));
        $fallbackManual = !empty($shipping['pricing_fallback_manual']);
        $displayText = trim((string)($shipping['shipping_unavailable_text'] ?? ''));

        if ($globalSource === 'api' && $globalProvider !== '') {
            $price = ShippingProviderPriceResolver::getImportedPrice($globalProvider, $stateCode, $shippingType);
            if ($price === null && $fallbackManual) {
                $price = $this->resolveManualShippingPrice($shipping, $mode, $stateCode, $shippingType);
            }
        } else {
            $price = $this->resolveManualShippingPrice($shipping, $mode, $stateCode, $shippingType);
        }

        if ($price === null && $displayText !== '') {
            echo json_encode([
                'price' => null,
                'display_text' => $displayText,
                'uses_custom_text' => true
            ], JSON_UNESCAPED_UNICODE);
            return;
        }

        if ($price === null) {
            http_response_code(404);
            echo json_encode([
                'error' => 'shipping_price_not_found'
            ]);
            return;
        }

        echo json_encode([
            'price' => (int)$price,
            'display_text' => null,
            'uses_custom_text' => false
        ], JSON_UNESCAPED_UNICODE);
    }


    public function frontendShippingConfig()
    {
        header('Content-Type: application/json; charset=utf-8');
        $shipping = ShippingSettings::load();
        $integrations = (new ShippingIntegrationModel())->getAllIndexed();
        $providers = [];
        foreach ($integrations as $key => $row) {
            if ((int)($row['is_active'] ?? 0) !== 1) continue;
            $providers[] = [
                'key' => (string)$key,
                'name' => (string)($row['display_name'] ?? ucfirst((string)$key)),
                'supports_dynamic_frontend' => $key === 'maystro' && !empty($shipping['frontend_maystro_enabled']),
            ];
        }
        $maystroActive = isset($integrations['maystro']) && (int)($integrations['maystro']['is_active'] ?? 0) === 1;
        echo json_encode([
            'mode' => (string)($shipping['provider_selection_mode'] ?? 'manual_admin'),
            'forced_provider' => (string)($shipping['forced_provider'] ?? ''),
            'allow_customer_provider_choice' => !empty($shipping['allow_customer_provider_choice']),
            'providers' => $providers,
            'maystro' => [
                'enabled' => $maystroActive,
                'allow_express' => $maystroActive,
                'allow_stopdesk' => $maystroActive,
                'allow_pickup' => $maystroActive,
            ],
        ], JSON_UNESCAPED_UNICODE);
    }

    protected function maystroCachePath(string $name): string
    {
        $dir = ROOT_PATH . '/storage/cache/maystro';
        if (!is_dir($dir)) {
            @mkdir($dir, 0775, true);
        }
        return $dir . '/' . ltrim($name, '/');
    }

    protected function readMaystroCache(string $name): array
    {
        $path = $this->maystroCachePath($name);
        if (!is_file($path)) {
            return [];
        }
        $raw = @file_get_contents($path);
        $decoded = json_decode((string)$raw, true);
        return is_array($decoded) ? $decoded : [];
    }

    protected function writeMaystroCache(string $name, array $data): void
    {
        if (empty($data)) {
            return;
        }
        @file_put_contents($this->maystroCachePath($name), json_encode(array_values($data), JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
    }

    public function maystroWilayas()
    {
        header('Content-Type: application/json; charset=utf-8');

        $service = new MaystroLocationService();
        $result = $service->getWilayas();
        if (empty($result['success'])) {
            http_response_code(($result['message'] ?? '') === 'maystro_not_active' ? 404 : 502);
        }

        echo json_encode([
            'success' => !empty($result['success']),
            'data' => array_values((array)($result['data'] ?? [])),
            'message' => $result['message'] ?? null,
            'source' => $result['source'] ?? null,
        ], JSON_UNESCAPED_UNICODE);
    }

    public function maystroCommunesFrontendIndex()
    {
        $wilayaId = (int) ($_GET['wilaya_id'] ?? $_GET['wilaya'] ?? 0);
        $this->maystroCommunesFrontend($wilayaId);
    }

    public function maystroCommunesFrontend($wilayaId)
    {
        header('Content-Type: application/json; charset=utf-8');

        $service = new MaystroLocationService();
        $result = $service->getCommunes((int)$wilayaId);
        if (empty($result['success']) && ($result['message'] ?? '') === 'maystro_not_active') {
            http_response_code(404);
        }

        echo json_encode([
            'success' => !empty($result['success']),
            'data' => array_values((array)($result['data'] ?? [])),
            'message' => $result['message'] ?? null,
            'source' => $result['source'] ?? null,
        ], JSON_UNESCAPED_UNICODE);
    }

    public function maystroPickupPointsFrontend($communeId)
    {
        header('Content-Type: application/json; charset=utf-8');
        $integration = (new ShippingIntegrationModel())->getByProvider('maystro');
        if (!$integration || (int)($integration['is_active'] ?? 0) !== 1) {
            http_response_code(404);
            echo json_encode(['success' => false, 'message' => 'maystro_not_active']);
            return;
        }
        $client = MaystroClient::fromIntegration($integration);
        $res = $client->getPickupPoints((int)$communeId);
        echo json_encode(['success' => !empty($res['success']), 'data' => $res['data'] ?? [], 'message' => $res['message'] ?? null], JSON_UNESCAPED_UNICODE);
    }

    public function maystroDeliveryPriceFrontend($communeId)
    {
        header('Content-Type: application/json; charset=utf-8');
        $deliveryType = (int)($_GET['delivery_type'] ?? 1);
        if (!in_array($deliveryType, [1, 2, 3], true)) $deliveryType = 1;
        $integration = (new ShippingIntegrationModel())->getByProvider('maystro');
        if (!$integration || (int)($integration['is_active'] ?? 0) !== 1) {
            http_response_code(404);
            echo json_encode(['success' => false, 'message' => 'maystro_not_active']);
            return;
        }
        $client = MaystroClient::fromIntegration($integration);
        $res = $client->getDeliveryPrice((int)$communeId, $deliveryType);
        $price = null;
        if (!empty($res['success'])) {
            $data = $res['data'] ?? [];
            $price = $data['delivery_price'] ?? $data['price'] ?? null;
        }
        echo json_encode(['success' => !empty($res['success']), 'price' => $price, 'data' => $res['data'] ?? [], 'message' => $res['message'] ?? null], JSON_UNESCAPED_UNICODE);
    }

    /**
     * ============================
     * BACKWARD COMPATIBILITY
     * ============================
     */
    public function dzStates()
    {
        $this->regions();
    }

    public function dzCities($stateCode)
    {
        $this->cities($stateCode);
    }
}
