<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

final class TripaySettings extends Model
{
    use HasFactory;

    protected $fillable = [
        'api_key',
        'private_key',
        'merchant_code',
        'payment_method',
        'production_mode',
        'gold_rate',
        'min_amount',
        'max_amount',
        'is_active',
        'broadcast_enabled',
        'broadcast_message',
        'broadcast_channel',
        'discord_enabled',
        'discord_webhook_url',
        'discord_message',
        'discord_mention_everyone',
    ];

    protected $casts = [
        'production_mode' => 'boolean',
        'gold_rate' => 'integer',
        'min_amount' => 'integer',
        'max_amount' => 'integer',
        'is_active' => 'boolean',
        'broadcast_enabled' => 'boolean',
        'broadcast_channel' => 'integer',
        'discord_enabled' => 'boolean',
        'discord_mention_everyone' => 'boolean',
    ];

    /**
     * Get the API base URL based on production mode.
     */
    public function getApiBaseUrlAttribute(): string
    {
        return $this->production_mode
            ? 'https://tripay.co.id/api'
            : 'https://tripay.co.id/api-sandbox';
    }

    /**
     * Get the merchant API base URL based on production mode.
     */
    public function getMerchantApiUrlAttribute(): string
    {
        return $this->production_mode
            ? 'https://tripay.co.id/api'
            : 'https://tripay.co.id/api-sandbox';
    }

    /**
     * Check if settings are configured.
     */
    public function isConfigured(): bool
    {
        return ! empty($this->api_key)
            && ! empty($this->private_key)
            && ! empty($this->merchant_code);
    }

    /**
     * Validate amount is within allowed range.
     */
    public function isValidAmount(int $amount): bool
    {
        return $amount >= $this->min_amount && $amount <= $this->max_amount;
    }

    /**
     * Calculate gold amount from IDR amount.
     */
    public function calculateGold(int $amount): int
    {
        if ($this->gold_rate <= 0) {
            return 0;
        }

        return (int) floor($amount / $this->gold_rate);
    }

    /**
     * Get formatted broadcast message with placeholders replaced.
     */
    public function getBroadcastMessage($user, $transaction): string
    {
        $template = $this->broadcast_message ?: '&{player_name}& telah melakukan top up {gold} gold';

        // Get character name from API if character_id exists
        $playerName = 'Unknown';
        if ($transaction->character_id) {
            try {
                $api = app(\App\Services\Api\API::class);
                $roleData = $api->getRoleBase($transaction->character_id);
                $playerName = $roleData['name'] ?? $user->name ?? 'Unknown';
            } catch (\Exception $e) {
                \Log::warning('Failed to get character name for broadcast', [
                    'character_id' => $transaction->character_id,
                    'error' => $e->getMessage(),
                ]);
                $playerName = $user->name ?? 'Unknown';
            }
        } else {
            $playerName = $user->name ?? 'Unknown';
        }

        $replacements = [
            '{player_name}' => $playerName,
            '{amount}' => number_format($transaction->amount ?? 0),
            '{gold}' => $transaction->gold_amount ?? 0,
            '{payment_method}' => 'Tripay',
        ];

        return str_replace(array_keys($replacements), array_values($replacements), $template);
    }

    /**
     * Get singleton instance.
     */
    public static function getInstance(): ?self
    {
        return self::first();
    }

    /**
     * Get player name for notification.
     */
    protected function getPlayerName($user, $transaction): string
    {
        $playerName = 'Unknown';
        if ($transaction->character_id) {
            try {
                $api = app(\App\Services\Api\API::class);
                $roleData = $api->getRoleBase($transaction->character_id);
                $playerName = $roleData['name'] ?? $user->name ?? 'Unknown';
            } catch (\Exception $e) {
                $playerName = $user->name ?? 'Unknown';
            }
        } else {
            $playerName = $user->name ?? 'Unknown';
        }

        return $playerName;
    }

    /**
     * Format Discord Embed Array
     */
    public function formatDiscordEmbed($user, $transaction): array
    {
        $playerName = $this->getPlayerName($user, $transaction);
        $amount = number_format($transaction->amount ?? 0);
        $gold = $transaction->gold_amount ?? 0;

        // Use custom template if provided
        $template = $this->discord_message;
        if ($template) {
            $description = str_replace(
                ['{player_name}', '{amount}', '{gold}', '{payment_method}'],
                [$playerName, $amount, $gold, 'Tripay'],
                $template
            );
        } else {
            $description = "**{$playerName}** has donated Rp {$amount} and received **{$gold} gold** via Tripay";
        }

        $embed = [
            'author' => [
                'name' => ' New Donation Received 💰',
            ],
            'description' => $description,
            'color' => 5763719, // Green
            'timestamp' => now()->toIso8601String(),
            'footer' => [
                'text' => 'Perfect World '.config('app.name'),
            ],
        ];

        return $embed;
    }

    /**
     * Send Discord webhook notification with embed.
     */
    public function sendDiscordNotification($user, $transaction): bool
    {
        if (! $this->discord_enabled || empty($this->discord_webhook_url)) {
            return false;
        }

        try {
            $embed = $this->formatDiscordEmbed($user, $transaction);

            $payload = [
                'embeds' => [$embed],
            ];

            if ($this->discord_mention_everyone) {
                $payload['content'] = '@everyone';
                $payload['allowed_mentions'] = [
                    'parse' => ['everyone'],
                ];
            }

            $client = new \GuzzleHttp\Client;
            $response = $client->post($this->discord_webhook_url, [
                'json' => $payload,
                'headers' => [
                    'Content-Type' => 'application/json',
                ],
                'timeout' => 10,
            ]);

            return $response->getStatusCode() === 204;
        } catch (\Exception $e) {
            \Log::error('Failed to send Discord webhook', [
                'gateway' => 'tripay',
                'error' => $e->getMessage(),
            ]);

            return false;
        }
    }
}
