<?php

namespace App\Services;

use App\Models\Vendor;
use App\Services\Providers\ProviderFactory;
use Illuminate\Support\Arr;

class VendorPlanCatalogService
{
    public function __construct(protected ProviderFactory $providerFactory)
    {
    }

    public function fetch(Vendor $vendor, array $context = []): array
    {
        $provider = $this->providerFactory->forVendor($vendor);
        $type = (string) $vendor->type;

        if (in_array($type, ['msorg', 'vtbox'], true)) {
            return [
                'success' => false,
                'message' => strtoupper($type).' plan auto-fetch is not available because the shared documentation has no standard plans-list endpoint. Add vendor plan IDs manually.',
                'items' => [],
            ];
        }

        if ($type === 'smeplug') {
            $plansResult = $provider->getPlans();
            $networksResult = method_exists($provider, 'getNetworks') ? $provider->getNetworks() : ['body' => []];

            if (! ($plansResult['success'] ?? false)) {
                return [
                    'success' => false,
                    'message' => (string) data_get($plansResult, 'body.message', 'Unable to fetch plans from SMEPlug.'),
                    'items' => [],
                ];
            }

            $networkMap = $this->buildNetworkMap((array) ($networksResult['body'] ?? []));
            $rows = $this->extractRows((array) ($plansResult['body'] ?? []));
            $items = [];

            foreach ($rows as $row) {
                $code = (string) (Arr::get($row, 'id') ?? Arr::get($row, 'plan_id') ?? Arr::get($row, 'code') ?? '');
                if ($code === '') {
                    continue;
                }

                $networkId = (string) (Arr::get($row, 'network_id') ?? Arr::get($row, 'networkId') ?? '');
                $networkName = $networkMap[$networkId] ?? null;
                $name = (string) (Arr::get($row, 'name') ?? Arr::get($row, 'plan_name') ?? Arr::get($row, 'title') ?? "Plan {$code}");
                $amount = Arr::get($row, 'amount') ?? Arr::get($row, 'price');
                $validity = (string) (Arr::get($row, 'validity') ?? Arr::get($row, 'duration') ?? '');

                $hintParts = array_filter([
                    $networkName,
                    is_numeric($amount) ? 'NGN '.number_format((float) $amount, 2) : null,
                    $validity !== '' ? $validity : null,
                ]);

                $items[] = [
                    'code' => $code,
                    'label' => $name,
                    'hint' => implode(' • ', $hintParts),
                    'raw' => $row,
                ];
            }

            return [
                'success' => true,
                'message' => count($items).' plan(s) fetched from SMEPlug.',
                'items' => array_values($items),
            ];
        }

        if ($type === 'vtpass') {
            $categorySlug = strtolower((string) ($context['category_slug'] ?? ''));
            $networkSlug = strtolower((string) ($context['network_slug'] ?? ''));
            $serviceId = filled($context['service_id'] ?? null)
                ? strtolower((string) $context['service_id'])
                : null;

            if (! $serviceId) {
                $serviceId = $this->defaultVtpassServiceId($categorySlug, $networkSlug);
            }

            if (! $serviceId) {
                return [
                    'success' => false,
                    'message' => 'VTpass fetch requires a known serviceID. Set VTpass serviceID in the plan form, or select a compatible network for airtime/data.',
                    'items' => [],
                ];
            }

            $result = method_exists($provider, 'getVariationCodes')
                ? $provider->getVariationCodes($serviceId)
                : ['success' => false, 'body' => ['message' => 'VTpass variation endpoint not implemented.']];

            if (! ($result['success'] ?? false)) {
                return [
                    'success' => false,
                    'message' => (string) data_get($result, 'body.message', 'Unable to fetch VTpass variations.'),
                    'items' => [],
                ];
            }

            $rows = $this->extractRows((array) ($result['body'] ?? []));
            $items = [];

            foreach ($rows as $row) {
                $code = (string) (Arr::get($row, 'variation_code') ?? Arr::get($row, 'code') ?? Arr::get($row, 'id') ?? '');
                if ($code === '') {
                    continue;
                }

                $name = (string) (Arr::get($row, 'name') ?? Arr::get($row, 'variation') ?? "Variation {$code}");
                $amount = Arr::get($row, 'variation_amount') ?? Arr::get($row, 'amount') ?? Arr::get($row, 'price');

                $items[] = [
                    'code' => $code,
                    'label' => $name,
                    'hint' => is_numeric($amount) ? 'NGN '.number_format((float) $amount, 2) : '',
                    'raw' => $row,
                ];
            }

            return [
                'success' => true,
                'message' => count($items).' variation(s) fetched from VTpass.',
                'items' => array_values($items),
            ];
        }

        return [
            'success' => false,
            'message' => 'Vendor type does not support plan catalog fetch yet.',
            'items' => [],
        ];
    }

    protected function buildNetworkMap(array $body): array
    {
        $rows = $this->extractRows($body);
        $map = [];

        foreach ($rows as $row) {
            $id = (string) (Arr::get($row, 'id') ?? Arr::get($row, 'network_id') ?? '');
            if ($id === '') continue;
            $name = (string) (Arr::get($row, 'name') ?? Arr::get($row, 'network') ?? Arr::get($row, 'slug') ?? $id);
            $map[$id] = $name;
        }

        return $map;
    }

    protected function extractRows(array $body): array
    {
        $candidates = [
            Arr::get($body, 'content.variations'),
            Arr::get($body, 'content'),
            Arr::get($body, 'data.plans'),
            Arr::get($body, 'data'),
            Arr::get($body, 'plans'),
            Arr::get($body, 'results'),
            $body,
        ];

        foreach ($candidates as $candidate) {
            if (is_array($candidate) && array_is_list($candidate)) {
                return $candidate;
            }
        }

        return [];
    }

    protected function defaultVtpassServiceId(string $categorySlug, string $networkSlug): ?string
    {
        if (in_array($categorySlug, ['airtime_vtu', 'airtime'], true)) {
            return match ($networkSlug) {
                'mtn' => 'mtn',
                'airtel' => 'airtel',
                'glo' => 'glo',
                '9mobile', 'etisalat', '9_mobile', '9-mobile' => 'etisalat',
                default => null,
            };
        }

        if (in_array($categorySlug, ['data_sme', 'data_gifting', 'data_cg', 'data_direct', 'data'], true)) {
            return match ($networkSlug) {
                'mtn' => 'mtn-data',
                'airtel' => 'airtel-data',
                'glo' => $categorySlug === 'data_sme' ? 'glo-sme-data' : 'glo-data',
                '9mobile', 'etisalat', '9_mobile', '9-mobile' => 'etisalat-data',
                default => null,
            };
        }

        return null;
    }
}
