<?php

namespace App\Services\Commerce;

use App\Models\Streamer;
use App\Models\User;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class PaymentService
{
    /**
     * Process successful payment: add gold to user and handle streamer rewards.
     */
    public function processSuccessfulPayment(
        Model $transaction,
        ?Model $settings = null
    ): bool {
        try {
            DB::beginTransaction();

            // Add gold to user
            $this->addGoldToUser($transaction->user_id, $transaction->gold_amount);

            // Process streamer reward if applicable
            if ($transaction->streamer_code && $settings) {
                $this->processStreamerReward(
                    $transaction->streamer_code,
                    $transaction->amount,
                    $settings->gold_rate ?? 1000,
                    $transaction->id,
                    get_class($transaction)
                );
            }

            DB::commit();
            return true;
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('Failed to process payment', [
                'transaction_id' => $transaction->id,
                'transaction_type' => get_class($transaction),
                'error' => $e->getMessage(),
            ]);
            return false;
        }
    }

    /**
     * Add gold to user account.
     */
    public function addGoldToUser(int $userId, int $goldAmount): void
    {
        $user = User::find($userId);
        if ($user) {
            $user->increment('gold', $goldAmount);
        }
    }

    /**
     * Process streamer reward.
     */
    public function processStreamerReward(
        string $streamerCode,
        int $transactionAmount,
        int $goldRate,
        int $transactionId,
        string $gateway
    ): void {
        $streamer = Streamer::where('code', $streamerCode)
            ->where('is_active', true)
            ->first();

        if (!$streamer || $goldRate <= 0) {
            return;
        }

        // Calculate base gold (before bonuses) from transaction amount
        $baseGold = floor($transactionAmount / $goldRate);
        $streamerReward = $streamer->calculateReward($baseGold);

        if ($streamerReward > 0) {
            $streamer->addGoldReward($streamerReward);
            
            Log::info('Streamer reward credited', [
                'gateway' => $gateway,
                'transaction_id' => $transactionId,
                'streamer_code' => $streamer->code,
                'streamer_user_id' => $streamer->user_id,
                'transaction_amount' => $transactionAmount,
                'gold_rate' => $goldRate,
                'base_gold' => $baseGold,
                'streamer_reward' => $streamerReward,
                'percentage' => $streamer->percentage,
            ]);
        }
    }

    /**
     * Calculate gold amount from transaction amount.
     */
    public function calculateGoldAmount(
        int $amount,
        int $goldRate,
        float $factionBonusPercentage = 0,
        int $promoBonusGold = 0,
        int $streamerBonusGold = 0
    ): int {
        $baseGold = floor($amount / $goldRate);
        $factionBonusGold = floor($baseGold * ($factionBonusPercentage / 100));
        return $baseGold + $factionBonusGold + $promoBonusGold + $streamerBonusGold;
    }

    /**
     * Validate transaction amount is within allowed range.
     */
    public function validateAmount(int $amount, int $minAmount, int $maxAmount): bool
    {
        return $amount >= $minAmount && $amount <= $maxAmount;
    }

    /**
     * Map status from payment gateway specific format to internal format.
     */
    public function normalizeStatus(string $status, string $gateway): string
    {
        return match($gateway) {
            'tripay' => match(strtolower($status)) {
                'paid', 'berhasil' => 'paid',
                'unpaid', 'pending' => 'pending',
                'expired' => 'expired',
                'failed', 'gagal' => 'failed',
                default => 'pending',
            },
            'duitku' => match($status) {
                '00' => 'success',
                '01' => 'pending',
                '02' => 'failed',
                default => 'pending',
            },
            'ipaymu' => match(strtolower($status)) {
                'berhasil', 'sukses', 'success' => 'success',
                'gagal', 'failed' => 'failed',
                'expired' => 'expired',
                default => 'pending',
            },
            default => 'pending',
        };
    }

    /**
     * Generate unique transaction reference.
     */
    public function generateReference(string $prefix = 'TRX'): string
    {
        return $prefix . '-' . time() . '-' . strtoupper(substr(md5(uniqid()), 0, 8));
    }

    /**
     * Check if payment gateway is active and configured.
     */
    public function isGatewayActive(string $gateway): bool
    {
        $settings = match($gateway) {
            'tripay' => \App\Models\TripaySettings::first(),
            'duitku' => \App\Models\DuitkuSettings::first(),
            'ipaymu' => \App\Models\IpaymuSettings::first(),
            default => null,
        };

        return $settings && $settings->is_active && $settings->isConfigured();
    }

    /**
     * Get all active payment gateways.
     */
    public function getActiveGateways(): array
    {
        $gateways = [];

        if ($this->isGatewayActive('tripay')) {
            $gateways[] = 'tripay';
        }
        if ($this->isGatewayActive('duitku')) {
            $gateways[] = 'duitku';
        }
        if ($this->isGatewayActive('ipaymu')) {
            $gateways[] = 'ipaymu';
        }

        return $gateways;
    }
}
