<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

final class DuitkuTransaction extends Model
{
    use HasFactory;

    protected $fillable = [
        'user_id',
        'character_id',
        'merchant_order_id',
        'reference',
        'amount',
        'gold_amount',
        'streamer_code',
        'payment_method',
        'status',
        'payment_url',
        'response_data',
        'expired_at',
        'paid_at',
    ];

    protected $casts = [
        'amount' => 'integer',
        'gold_amount' => 'integer',
        'response_data' => 'array',
        'expired_at' => 'datetime',
        'paid_at' => 'datetime',
    ];

    /**
     * Get the user that owns the transaction.
     */
    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class, 'user_id', 'ID');
    }

    /**
     * Get the streamer associated with this transaction.
     */
    public function streamer(): BelongsTo
    {
        return $this->belongsTo(Streamer::class, 'streamer_code', 'code');
    }

    /**
     * Scope to filter by status.
     */
    public function scopeStatus(Builder $query, string $status): Builder
    {
        return $query->where('status', $status);
    }

    /**
     * Scope to get pending transactions.
     */
    public function scopePending(Builder $query): Builder
    {
        return $query->where('status', 'pending');
    }

    /**
     * Scope to get success transactions.
     */
    public function scopeSuccess(Builder $query): Builder
    {
        return $query->where('status', 'success');
    }

    /**
     * Scope to get failed transactions.
     */
    public function scopeFailed(Builder $query): Builder
    {
        return $query->where('status', 'failed');
    }

    /**
     * Check if transaction is pending.
     */
    public function isPending(): bool
    {
        return $this->status === 'pending';
    }

    /**
     * Check if transaction is success.
     */
    public function isSuccess(): bool
    {
        return $this->status === 'success';
    }

    /**
     * Check if transaction is failed.
     */
    public function isFailed(): bool
    {
        return $this->status === 'failed';
    }

    /**
     * Check if transaction has expired.
     */
    public function isExpired(): bool
    {
        return $this->status === 'failed' || 
               ($this->expired_at && now()->greaterThan($this->expired_at));
    }

    /**
     * Update transaction status.
     */
    public function updateStatus(string $status, array $responseData = null): bool
    {
        $data = ['status' => $status];
        
        if ($status === 'success' && !$this->paid_at) {
            $data['paid_at'] = now();
        }
        
        if ($responseData) {
            $data['response_data'] = $responseData;
        }
        
        return $this->update($data);
    }

    /**
     * Add gold to user and process streamer reward.
     */
    public function processPayment(): bool
    {
        if (!$this->isPending()) {
            return false;
        }

        try {
            // Update transaction status
            $this->updateStatus('success');

            // Use PaymentService to handle payment processing
            $paymentService = app(\App\Services\Commerce\PaymentService::class);
            $settings = DuitkuSettings::first();
            
            return $paymentService->processSuccessfulPayment($this, $settings);
        } catch (\Exception $e) {
            \Log::error('Failed to process Duitku payment', [
                'transaction_id' => $this->id,
                'error' => $e->getMessage(),
            ]);
            return false;
        }
    }

    /**
     * Map Duitku status code to internal status.
     */
    public static function mapDuitkuStatus(string $statusCode): string
    {
        return match($statusCode) {
            '00' => 'success',
            '01' => 'pending',
            '02' => 'failed',
            default => 'pending',
        };
    }
}
