<?php

namespace App\Libraries;

use App\Models\PaymentTransactionModel;

class TransactionManagementService
{
    private $paymentTransactionModel;

    public function __construct()
    {
        $this->paymentTransactionModel = new PaymentTransactionModel();
    }

    /**
     * Initiate a chargeback for a transaction
     */
    public function initiateChargeback(string $transactionId, string $reason, array $additionalData = []): array
    {
        $transaction = $this->paymentTransactionModel->where('transaction_id', $transactionId)->first();
        
        if (!$transaction) {
            return [
                'success' => false,
                'message' => 'Transaction not found'
            ];
        }

        if ($transaction['status'] !== 'SUCCESS') {
            return [
                'success' => false,
                'message' => 'Chargebacks can only be initiated for successful transactions'
            ];
        }

        if ($transaction['chargeback_status'] !== 'none') {
            return [
                'success' => false,
                'message' => 'Chargeback already exists for this transaction'
            ];
        }

        // Update transaction with chargeback information
        $updateData = [
            'chargeback_status' => 'pending',
            'chargeback_reason' => $reason,
            'chargeback_date' => date('Y-m-d H:i:s'),
            'updated_at' => date('Y-m-d H:i:s'),
            'metadata' => json_encode(array_merge(
                json_decode($transaction['metadata'] ?? '{}', true),
                ['chargeback_data' => $additionalData]
            ))
        ];

        $result = $this->paymentTransactionModel->where('transaction_id', $transactionId)
            ->set($updateData)
            ->update();

        if ($result) {
            log_message('info', "Chargeback initiated for transaction: {$transactionId}");
            return [
                'success' => true,
                'message' => 'Chargeback initiated successfully',
                'chargeback_id' => $transactionId . '_cb_' . time()
            ];
        }

        return [
            'success' => false,
            'message' => 'Failed to initiate chargeback'
        ];
    }

    /**
     * Update chargeback status
     */
    public function updateChargebackStatus(string $transactionId, string $status, string $reason = null): array
    {
        $validStatuses = ['pending', 'disputed', 'won', 'lost'];
        
        if (!in_array($status, $validStatuses)) {
            return [
                'success' => false,
                'message' => 'Invalid chargeback status'
            ];
        }

        $updateData = [
            'chargeback_status' => $status,
            'updated_at' => date('Y-m-d H:i:s')
        ];

        if ($reason) {
            $updateData['chargeback_reason'] = $reason;
        }

        $result = $this->paymentTransactionModel->where('transaction_id', $transactionId)
            ->set($updateData)
            ->update();

        if ($result) {
            log_message('info', "Chargeback status updated for transaction: {$transactionId} to {$status}");
            return [
                'success' => true,
                'message' => 'Chargeback status updated successfully'
            ];
        }

        return [
            'success' => false,
            'message' => 'Failed to update chargeback status'
        ];
    }

    /**
     * Process a refund for a transaction
     */
    public function processRefund(string $transactionId, float $amount, string $reason = null): array
    {
        $transaction = $this->paymentTransactionModel->where('transaction_id', $transactionId)->first();
        
        if (!$transaction) {
            return [
                'success' => false,
                'message' => 'Transaction not found'
            ];
        }

        if ($transaction['status'] !== 'SUCCESS') {
            return [
                'success' => false,
                'message' => 'Refunds can only be processed for successful transactions'
            ];
        }

        if ($amount > $transaction['amount']) {
            return [
                'success' => false,
                'message' => 'Refund amount cannot exceed transaction amount'
            ];
        }

        // Check if there's already a refund
        $existingRefundAmount = $transaction['refund_amount'] ?? 0;
        if (($existingRefundAmount + $amount) > $transaction['amount']) {
            return [
                'success' => false,
                'message' => 'Total refund amount would exceed transaction amount'
            ];
        }

        // Generate refund reference
        $refundReference = 'REF_' . $transactionId . '_' . time();

        $updateData = [
            'refund_status' => 'pending',
            'refund_amount' => $existingRefundAmount + $amount,
            'refund_reference' => $refundReference,
            'updated_at' => date('Y-m-d H:i:s'),
            'metadata' => json_encode(array_merge(
                json_decode($transaction['metadata'] ?? '{}', true),
                ['refund_data' => [
                    'amount' => $amount,
                    'reason' => $reason,
                    'processed_at' => date('Y-m-d H:i:s')
                ]]
            ))
        ];

        $result = $this->paymentTransactionModel->where('transaction_id', $transactionId)
            ->set($updateData)
            ->update();

        if ($result) {
            log_message('info', "Refund initiated for transaction: {$transactionId}, amount: {$amount}");
            return [
                'success' => true,
                'message' => 'Refund initiated successfully',
                'refund_reference' => $refundReference,
                'refund_amount' => $amount
            ];
        }

        return [
            'success' => false,
            'message' => 'Failed to process refund'
        ];
    }

    /**
     * Update refund status
     */
    public function updateRefundStatus(string $transactionId, string $status): array
    {
        $validStatuses = ['pending', 'processed', 'failed'];
        
        if (!in_array($status, $validStatuses)) {
            return [
                'success' => false,
                'message' => 'Invalid refund status'
            ];
        }

        $result = $this->paymentTransactionModel->where('transaction_id', $transactionId)
            ->set([
                'refund_status' => $status,
                'updated_at' => date('Y-m-d H:i:s')
            ])
            ->update();

        if ($result) {
            log_message('info', "Refund status updated for transaction: {$transactionId} to {$status}");
            return [
                'success' => true,
                'message' => 'Refund status updated successfully'
            ];
        }

        return [
            'success' => false,
            'message' => 'Failed to update refund status'
        ];
    }

    /**
     * Get transaction details with comprehensive information
     */
    public function getTransactionDetails(string $transactionId): array
    {
        $transaction = $this->paymentTransactionModel->where('transaction_id', $transactionId)->first();
        
        if (!$transaction) {
            return [
                'success' => false,
                'message' => 'Transaction not found'
            ];
        }

        return [
            'success' => true,
            'transaction' => [
                'id' => $transaction['id'],
                'transaction_id' => $transaction['transaction_id'],
                'reference' => $transaction['reference'],
                'gateway_reference' => $transaction['gateway_reference'],
                'msisdn' => $transaction['msisdn'],
                'amount' => $transaction['amount'],
                'currency' => $transaction['currency'],
                'status' => $transaction['status'],
                'description' => $transaction['description'],
                'payment_method' => $transaction['payment_method'],
                'client_ip' => $transaction['client_ip'],
                'failure_reason' => $transaction['failure_reason'],
                'created_at' => $transaction['created_at'],
                'processed_at' => $transaction['processed_at'],
                'updated_at' => $transaction['updated_at'],
                'chargeback_status' => $transaction['chargeback_status'],
                'chargeback_reason' => $transaction['chargeback_reason'],
                'chargeback_date' => $transaction['chargeback_date'],
                'refund_status' => $transaction['refund_status'],
                'refund_amount' => $transaction['refund_amount'],
                'refund_reference' => $transaction['refund_reference'],
                'webhook_attempts' => $transaction['webhook_attempts'],
                'last_webhook_attempt' => $transaction['last_webhook_attempt'],
                'metadata' => json_decode($transaction['metadata'] ?? '{}', true)
            ]
        ];
    }

    /**
     * Get transactions with chargebacks
     */
    public function getChargebackTransactions(): array
    {
        $transactions = $this->paymentTransactionModel->where('chargeback_status !=', 'none')
            ->orderBy('chargeback_date', 'DESC')
            ->findAll();

        return [
            'success' => true,
            'transactions' => $transactions,
            'count' => count($transactions)
        ];
    }

    /**
     * Get transactions with refunds
     */
    public function getRefundTransactions(): array
    {
        $transactions = $this->paymentTransactionModel->where('refund_status !=', 'none')
            ->orderBy('updated_at', 'DESC')
            ->findAll();

        return [
            'success' => true,
            'transactions' => $transactions,
            'count' => count($transactions)
        ];
    }

    /**
     * Generate transaction report
     */
    public function generateTransactionReport(string $startDate, string $endDate): array
    {
        $transactions = $this->paymentTransactionModel->where('created_at >=', $startDate . ' 00:00:00')
            ->where('created_at <=', $endDate . ' 23:59:59')
            ->findAll();

        $stats = [
            'total_transactions' => count($transactions),
            'total_amount' => 0,
            'successful_transactions' => 0,
            'failed_transactions' => 0,
            'pending_transactions' => 0,
            'successful_amount' => 0,
            'failed_amount' => 0,
            'pending_amount' => 0,
            'chargebacks' => 0,
            'refunds' => 0,
            'refund_amount' => 0
        ];

        foreach ($transactions as $transaction) {
            $stats['total_amount'] += $transaction['amount'];
            
            switch ($transaction['status']) {
                case 'SUCCESS':
                    $stats['successful_transactions']++;
                    $stats['successful_amount'] += $transaction['amount'];
                    break;
                case 'FAILED':
                    $stats['failed_transactions']++;
                    $stats['failed_amount'] += $transaction['amount'];
                    break;
                case 'PENDING':
                    $stats['pending_transactions']++;
                    $stats['pending_amount'] += $transaction['amount'];
                    break;
            }

            if ($transaction['chargeback_status'] !== 'none') {
                $stats['chargebacks']++;
            }

            if ($transaction['refund_status'] !== 'none') {
                $stats['refunds']++;
                $stats['refund_amount'] += $transaction['refund_amount'];
            }
        }

        return [
            'success' => true,
            'report' => [
                'period' => [
                    'start_date' => $startDate,
                    'end_date' => $endDate
                ],
                'statistics' => $stats,
                'transactions' => $transactions
            ]
        ];
    }
}
