<?php

namespace App\Services\System\Setting;

use App\Enums\OrderChannel;
use App\Enums\OwnerVerificationAction;
use App\Enums\OwnerVerificationStatus;
use App\Enums\Permission;
use App\Models\OwnerVerificationRequest;
use App\Models\User;
use App\Services\System\PushNotificationService;
use App\Settings\MarketplaceSettings;
use App\Support\Marketplace\MarketplaceFeeCalculator;
use App\Support\Marketplace\MarketplaceFeeRule;
use Illuminate\Validation\ValidationException;

class MarketplaceService
{
    public function __construct(
        private readonly PushNotificationService $pushNotificationService,
    ) {}

    private function tiktokFeeKeys(): array
    {
        return [
            'tiktok_shop_platform_commission',
            'tiktok_shop_logistics_service_fee',
            'tiktok_shop_dynamic_commission',
            'tiktok_shop_order_processing_fee',
            'tiktok_shop_affiliate',
            'tiktok_shop_pre_order_service_fee',
        ];
    }

    private function shopeeFeeKeys(): array
    {
        return [
            'shopee_admin_fee',
            'shopee_program_fee',
            'shopee_shipping_savings',
            'shopee_premium',
            'shopee_service_fee',
            'shopee_order_processing_fee',
            'shopee_ams_commission_fee',
            'shopee_pre_order',
            'shopee_live_extra',
        ];
    }

    public function marketplaceData(): array
    {
        $settings = app(MarketplaceSettings::class);

        return [
            'tiktok_shop_platform_commission' => $this->presentFeeRule($settings->tiktok_shop_platform_commission),
            'tiktok_shop_logistics_service_fee' => $this->presentFeeRule($settings->tiktok_shop_logistics_service_fee),
            'tiktok_shop_dynamic_commission' => $this->presentFeeRule($settings->tiktok_shop_dynamic_commission),
            'tiktok_shop_order_processing_fee' => $this->presentFeeRule($settings->tiktok_shop_order_processing_fee),
            'tiktok_shop_affiliate' => $this->presentFeeRule($settings->tiktok_shop_affiliate),
            'tiktok_shop_pre_order_service_fee' => $this->presentFeeRule($settings->tiktok_shop_pre_order_service_fee),
            'shopee_admin_fee' => $this->presentFeeRule($settings->shopee_admin_fee),
            'shopee_program_fee' => $this->presentFeeRule($settings->shopee_program_fee),
            'shopee_shipping_savings' => $this->presentFeeRule($settings->shopee_shipping_savings),
            'shopee_premium' => $this->presentFeeRule($settings->shopee_premium),
            'shopee_service_fee' => $this->presentFeeRule($settings->shopee_service_fee),
            'shopee_order_processing_fee' => $this->presentFeeRule($settings->shopee_order_processing_fee),
            'shopee_ams_commission_fee' => $this->presentFeeRule($settings->shopee_ams_commission_fee),
            'shopee_pre_order' => $this->presentFeeRule($settings->shopee_pre_order),
            'shopee_live_extra' => $this->presentFeeRule($settings->shopee_live_extra),
        ];
    }

    public function updateMarketplace(array $validated, User $user): void
    {
        if ($user->can(Permission::OWNER_VERIFICATIONS_VERIFY->value)) {
            $this->saveSettings($validated);

            return;
        }

        $hasPending = OwnerVerificationRequest::query()
            ->where('subject_type', MarketplaceSettings::class)
            ->pending()
            ->exists();

        if ($hasPending) {
            throw ValidationException::withMessages([
                'system' => 'Perubahan pengaturan marketplace sedang menunggu verifikasi owner.',
            ]);
        }

        $settings = app(MarketplaceSettings::class);
        $oldPayload = [];
        $newPayload = [];

        foreach ($this->tiktokFeeKeys() as $key) {
            $oldPayload[$key] = $this->presentFeeRule($settings->{$key});
            $newPayload[$key] = $this->normalizeFeeRule($validated[$key]);
        }

        foreach ($this->shopeeFeeKeys() as $key) {
            $oldPayload[$key] = $this->presentFeeRule($settings->{$key});
            $newPayload[$key] = $this->normalizeFeeRule($validated[$key]);
        }

        OwnerVerificationRequest::create([
            'action' => OwnerVerificationAction::UPDATE,
            'status' => OwnerVerificationStatus::PENDING,
            'subject_type' => MarketplaceSettings::class,
            'subject_id' => null,
            'submitted_by_id' => $user->id,
            'payload' => [
                'old' => $oldPayload,
                'new' => $newPayload,
            ],
        ]);

        $this->pushNotificationService->sendToRoles(
            '⚙️ Pengaturan Marketplace Menunggu Persetujuan Owner',
            "Pengajuan ubah pengaturan marketplace oleh '{$user->username}' menunggu verifikasi owner.",
            ['owner', 'developer'],
            route('admin.system.settings.index'),
        );

        $this->pushNotificationService->sendToUser(
            '📤 Pengajuan Terkirim',
            'Pengajuan ubah pengaturan marketplace menunggu verifikasi owner.',
            $user->id,
            route('admin.system.settings.index'),
        );
    }

    public function saveSettings(array $validated): void
    {
        $settings = app(MarketplaceSettings::class);

        foreach ($this->tiktokFeeKeys() as $key) {
            $settings->{$key} = $this->normalizeFeeRule($validated[$key]);
        }

        foreach ($this->shopeeFeeKeys() as $key) {
            $settings->{$key} = $this->normalizeFeeRule($validated[$key]);
        }

        $settings->save();
    }

    public function applyVerificationRequest(OwnerVerificationRequest $request): void
    {
        $newPayload = $request->payload['new'] ?? [];
        $this->saveSettings($newPayload);
    }

    public function buildOrderSnapshot(OrderChannel $channel, int $totalAmount, array $lineItems, bool $isAffiliate = false): ?array
    {
        $feeSnapshot = $this->feeRulesForChannel($channel);

        if ($feeSnapshot === null) {
            return null;
        }

        if (! $isAffiliate) {
            $feeSnapshot['fees'] = $this->excludeAffiliateFee($feeSnapshot['fees'], $channel);
        }

        $calculation = app(MarketplaceFeeCalculator::class)->calculate(
            $feeSnapshot['fees'],
            $totalAmount,
            $lineItems,
        );

        return [
            'platform' => $feeSnapshot['platform'],
            'is_affiliate' => $isAffiliate,
            'fees' => $feeSnapshot['fees'],
            'base_amount' => $totalAmount,
            'base_amount_formatted' => 'Rp '.number_format($totalAmount, 0, ',', '.'),
            'results' => $calculation['results'],
            'total_fee_amount' => $calculation['total_fee_amount'],
            'total_fee_amount_formatted' => 'Rp '.number_format($calculation['total_fee_amount'], 0, ',', '.'),
            'net_amount' => $calculation['net_amount'],
            'net_amount_formatted' => 'Rp '.number_format($calculation['net_amount'], 0, ',', '.'),
        ];
    }

    private function excludeAffiliateFee(array $fees, OrderChannel $channel): array
    {
        $affiliateKey = match ($channel) {
            OrderChannel::TIKTOK => 'tiktok_shop_affiliate',
            OrderChannel::SHOPEE => 'ams_commission_fee',
            default => null,
        };

        if ($affiliateKey !== null && isset($fees[$affiliateKey])) {
            $fees[$affiliateKey] = [
                'scope' => $fees[$affiliateKey]['scope'],
                'value_type' => $fees[$affiliateKey]['value_type'],
                'value' => 0,
            ];
        }

        return $fees;
    }

    private function feeRulesForChannel(OrderChannel $channel): ?array
    {
        $settings = app(MarketplaceSettings::class);

        return match ($channel) {
            OrderChannel::TIKTOK => [
                'platform' => 'tiktok',
                'fees' => [
                    'platform_commission' => $this->presentFeeRule($settings->tiktok_shop_platform_commission),
                    'logistics_service_fee' => $this->presentFeeRule($settings->tiktok_shop_logistics_service_fee),
                    'dynamic_commission' => $this->presentFeeRule($settings->tiktok_shop_dynamic_commission),
                    'order_processing_fee' => $this->presentFeeRule($settings->tiktok_shop_order_processing_fee),
                    'affiliate' => $this->presentFeeRule($settings->tiktok_shop_affiliate),
                    'pre_order_service_fee' => $this->presentFeeRule($settings->tiktok_shop_pre_order_service_fee),
                ],
            ],
            OrderChannel::SHOPEE => [
                'platform' => 'shopee',
                'fees' => [
                    'admin_fee' => $this->presentFeeRule($settings->shopee_admin_fee),
                    'program_fee' => $this->presentFeeRule($settings->shopee_program_fee),
                    'shipping_savings' => $this->presentFeeRule($settings->shopee_shipping_savings),
                    'premium' => $this->presentFeeRule($settings->shopee_premium),
                    'service_fee' => $this->presentFeeRule($settings->shopee_service_fee),
                    'order_processing_fee' => $this->presentFeeRule($settings->shopee_order_processing_fee),
                    'ams_commission_fee' => $this->presentFeeRule($settings->shopee_ams_commission_fee),
                    'pre_order' => $this->presentFeeRule($settings->shopee_pre_order),
                    'live_extra' => $this->presentFeeRule($settings->shopee_live_extra),
                ],
            ],
            OrderChannel::STORE => null,
        };
    }

    private function presentFeeRule(array $data): array
    {
        return MarketplaceFeeRule::fromArray($data)->toArray();
    }

    private function normalizeFeeRule(array $data): array
    {
        return MarketplaceFeeRule::fromArray($data)->toArray();
    }
}
