<?php

namespace App\Services\ProductOwner\Drivers;

use App\Contracts\ProductOwnerClientContract;
use App\DTOs\ProductOwner\ActivationRequestData;
use App\DTOs\ProductOwner\ActivationResponseData;
use App\DTOs\ProductOwner\AdminUpdateCheckData;
use App\DTOs\ProductOwner\HeartbeatPayloadData;
use App\DTOs\ProductOwner\LicenseValidationResponseData;
use App\DTOs\ProductOwner\ModulePurchaseResponseData;
use App\DTOs\ProductOwner\WalletBalanceData;
use App\DTOs\ProductOwner\WalletLedgerData;
use App\Support\PlatformCurrency;
use App\Support\PlatformVersion;
use Illuminate\Support\Str;

class MockProductOwnerDriver implements ProductOwnerClientContract
{
    private float $mockWalletBalance = 1000.00;

    /** @var list<array<string, mixed>> */
    private array $mockLedger = [];

    /** @var list<string> */
    private array $mockPurchasedModules = [];

    public function activate(ActivationRequestData $request): ActivationResponseData
    {
        return new ActivationResponseData(
            success: true,
            installationId: $request->installationId ?? (string) Str::uuid(),
            activationToken: 'mock-activation-'.Str::random(32),
            apiSecret: 'mock-secret-'.Str::random(32),
            message: 'License activated successfully (mock).',
            expiresAt: now()->addYear()->toIso8601String(),
        );
    }

    public function validateLicense(string $licenseKey, string $installationId): LicenseValidationResponseData
    {
        return new LicenseValidationResponseData(
            valid: ! empty($licenseKey) && ! empty($installationId),
            status: 'active',
            message: 'License is valid (mock).',
            expiresAt: now()->addYear()->toIso8601String(),
        );
    }

    public function sendHeartbeat(string $installationId, ?HeartbeatPayloadData $payload = null): bool
    {
        return ! empty($installationId);
    }

    public function fetchAdminIntegrityManifest(string $installationId, string $version): ?array
    {
        if (empty($installationId) || empty($version)) {
            return null;
        }

        return [
            'version' => $version,
            'algorithm' => 'sha256',
            'generated_at' => now()->toIso8601String(),
            'files' => [],
        ];
    }

    public function listMarketplaceModules(): array
    {
        return [
            [
                'uuid' => 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
                'name' => 'Finance',
                'slug' => 'finance',
                'description' => 'Income, expense, transactions and reports.',
                'specs' => '<h3>Finance Module</h3><p>Complete accounting toolkit for your admin platform.</p><ul><li>Income &amp; expense categories</li><li>Transaction ledger</li><li>Financial reports</li></ul>',
                'category' => 'Accounting',
                'pricing_type' => 'one_time',
                'price' => 49.00,
                'currency' => PlatformCurrency::code(),
                'version' => '1.0.0',
            ],
        ];
    }

    public function getWalletBalance(string $installationId): ?WalletBalanceData
    {
        if (empty($installationId)) {
            return null;
        }

        return new WalletBalanceData(balance: $this->mockWalletBalance, currency: PlatformCurrency::code());
    }

    public function getWalletLedger(string $installationId): ?WalletLedgerData
    {
        if (empty($installationId)) {
            return null;
        }

        return new WalletLedgerData(
            balance: $this->mockWalletBalance,
            currency: PlatformCurrency::code(),
            entries: $this->mockLedger,
        );
    }

    public function purchaseModule(string $installationId, string $moduleUuid): ModulePurchaseResponseData
    {
        if (empty($installationId)) {
            return new ModulePurchaseResponseData(success: false, message: 'Installation ID is required.');
        }

        $module = collect($this->listMarketplaceModules())->firstWhere('uuid', $moduleUuid);

        if (! $module) {
            return new ModulePurchaseResponseData(success: false, message: 'Module not found in marketplace.');
        }

        if (in_array($moduleUuid, $this->mockPurchasedModules, true)) {
            return new ModulePurchaseResponseData(
                success: true,
                message: 'Module already purchased for this installation.',
                amountCharged: 0,
                walletBalance: $this->mockWalletBalance,
                currency: $module['currency'] ?? PlatformCurrency::code(),
            );
        }

        $price = (float) ($module['price'] ?? 0);
        $isFree = ($module['pricing_type'] ?? 'free') === 'free' || $price <= 0;
        $openingBalance = $this->mockWalletBalance;
        $referenceNumber = null;
        $recordedAt = now();

        if (! $isFree) {
            if ($this->mockWalletBalance < $price) {
                return new ModulePurchaseResponseData(success: false, message: 'Insufficient wallet balance.');
            }

            $this->mockWalletBalance -= $price;
            $referenceNumber = 'WL-MOCK-'.strtoupper(Str::random(10));

            $ledgerEntry = [
                'type' => 'debit',
                'amount' => $price,
                'opening_balance' => $openingBalance,
                'closing_balance' => $this->mockWalletBalance,
                'reference_number' => $referenceNumber,
                'transaction_type' => 'module_purchase',
                'description' => 'Purchase: '.($module['name'] ?? 'Module'),
                'recorded_at' => $recordedAt->toIso8601String(),
            ];

            array_unshift($this->mockLedger, $ledgerEntry);
        }

        $this->mockPurchasedModules[] = $moduleUuid;

        return new ModulePurchaseResponseData(
            success: true,
            message: $isFree ? 'Free module activated.' : 'Module purchased successfully.',
            amountCharged: $isFree ? 0 : $price,
            walletBalance: $this->mockWalletBalance,
            currency: $module['currency'] ?? PlatformCurrency::code(),
            referenceNumber: $referenceNumber,
            openingBalance: $isFree ? null : $openingBalance,
            closingBalance: $isFree ? null : $this->mockWalletBalance,
            transactionType: $isFree ? null : 'module_purchase',
            ledgerDescription: $isFree ? null : ('Purchase: '.($module['name'] ?? 'Module')),
            recordedAt: $isFree ? null : $recordedAt,
        );
    }

    public function initializeModule(string $installationId, string $moduleUuid): bool
    {
        return ! empty($installationId) && ! empty($moduleUuid);
    }

    public function checkAdminUpdate(string $installationId, string $currentVersion): AdminUpdateCheckData
    {
        $current = PlatformVersion::current();
        $latestVersion = '1.0.1';
        $updateAvailable = version_compare($latestVersion, $currentVersion, '>');

        if (! $updateAvailable) {
            return AdminUpdateCheckData::upToDate($current);
        }

        return AdminUpdateCheckData::fromRemote([
            'success' => true,
            'update_available' => true,
            'latest_version' => $latestVersion,
            'latest_build' => '1.0.1-release.1',
            'channel' => 'General Release',
            'release_notes_url' => 'https://example.com/admin/release-notes',
            'changelog_url' => 'https://example.com/admin/changelog',
            'download_url' => null,
            'message' => 'An update is available (mock).',
        ], $current);
    }
}
