<?php

declare(strict_types=1);

namespace Instinctor\Services;

use Instinctor\Core\Config;
use Instinctor\Core\DB;
use Instinctor\Core\Auth;


if ( ! defined( 'ABSPATH' ) ) exit;

/**
 * Refund Service
 * Manages order refunds
 */
class RefundService
{
    public static function getOrderRefunds(int $orderId): array
    {
        $p = DB::prefix();
        return DB::get_results(DB::prepare(
            "SELECT * FROM {$p}instinctor_refunds WHERE order_id = %d ORDER BY created_at DESC",
            $orderId
        ));
    }

    public static function getRefund(int $id): ?object
    {
        return DB::get_row(DB::prepare(
            "SELECT * FROM {$p}instinctor_refunds WHERE id = %d",
            $id
        ));
    }

    public static function createRefund(array $data): int
    {
        
        DB::insert(
            DB::prefix() . 'instinctor_refunds',
            [
                'order_id' => (int) $data['order_id'],
                'amount' => (float) $data['amount'],
                'reason' => sanitize_textarea_field($data['reason'] ?? ''),
                'refunded_by' => Auth::userId() ?: null,
                'payment_refund_id' => sanitize_text_field($data['payment_refund_id'] ?? ''),
                'line_items' => !empty($data['line_items']) ? json_encode($data['line_items']) : null,
                'status' => $data['status'] ?? 'completed',
            ],
            ['%d', '%f', '%s', '%d', '%s', '%s', '%s']
        );
        
        $refundId = (int) DB::insert_id();
        
        if ($refundId) {
            // Update order total and status if fully refunded
            self::updateOrderAfterRefund((int) $data['order_id']);
            
            // Restore stock if requested
            if (!empty($data['restore_stock']) && !empty($data['line_items'])) {
                self::restoreStock($data['line_items']);
            }
            
            // Add order note
            OrderNoteService::addNote(
                (int) $data['order_id'],
                sprintf(
                    /* translators: placeholder values */
                    __('Refund of %1$s processed. %2$s', 'instinctor'),
                    '$' . number_format((float) $data['amount'], 2),
                    $data['reason'] ?? ''
                ),
                false
            );
        }
        
        return $refundId;
    }

    public static function getOrderTotalRefunded(int $orderId): float
    {
        $p = DB::prefix();
        return (float) DB::get_var(DB::prepare(
            "SELECT COALESCE(SUM(amount), 0) FROM {$p}instinctor_refunds 
             WHERE order_id = %d AND status = 'completed'",
            $orderId
        ));
    }

    public static function processStripeRefund(int $orderId, float $amount, string $reason = ''): array
    {
        $p = DB::prefix();
        
        $order = DB::get_row(DB::prepare(
            "SELECT * FROM {$p}instinctor_orders WHERE id = %d",
            $orderId
        ));
        
        if (!$order) {
            return ['success' => false, 'error' => 'Order not found'];
        }
        
        $paymentIntentId = $order->payment_intent_id ?? '';
        if (empty($paymentIntentId)) {
            return ['success' => false, 'error' => 'No payment intent found for this order'];
        }
        
        $secretKey = Config::get('instinctor_stripe_secret_key', '');
        if (empty($secretKey)) {
            return ['success' => false, 'error' => 'Stripe not configured'];
        }
        
        // Create refund via Stripe API
        $response = wp_remote_post('https://api.stripe.com/v1/refunds', [
            'headers' => [
                'Authorization' => 'Bearer ' . $secretKey,
                'Content-Type' => 'application/x-www-form-urlencoded',
            ],
            'body' => [
                'payment_intent' => $paymentIntentId,
                'amount' => (int) ($amount * 100), // Convert to cents
                'reason' => 'requested_by_customer',
            ],
        ]);
        
        if (is_wp_error($response)) {
            return ['success' => false, 'error' => $response->get_error_message()];
        }
        
        $body = json_decode(wp_remote_retrieve_body($response), true);
        
        if (!empty($body['error'])) {
            return ['success' => false, 'error' => $body['error']['message']];
        }
        
        // Create refund record
        $refundId = self::createRefund([
            'order_id' => $orderId,
            'amount' => $amount,
            'reason' => $reason,
            'payment_refund_id' => $body['id'] ?? '',
            'status' => 'completed',
        ]);
        
        return ['success' => true, 'refund_id' => $refundId, 'stripe_refund_id' => $body['id']];
    }

    private static function updateOrderAfterRefund(int $orderId): void
    {
        $p = DB::prefix();
        $order = DB::get_row(DB::prepare(
            "SELECT total FROM {$p}instinctor_orders WHERE id = %d",
            $orderId
        ));
        
        if (!$order) {
            return;
        }
        
        $totalRefunded = self::getOrderTotalRefunded($orderId);
        
        // If fully refunded, update status
        if ($totalRefunded >= $order->total) {
            DB::update(
                DB::prefix() . 'instinctor_orders',
                ['status' => 'refunded'],
                ['id' => $orderId],
                ['%s'],
                ['%d']
            );
        }
    }

    private static function restoreStock(array $lineItems): void
    {
        
        foreach ($lineItems as $item) {
            if (!empty($item['product_id']) && !empty($item['quantity'])) {
                $p = DB::prefix();
                DB::query(DB::prepare(
                    "UPDATE {$p}instinctor_products 
                     SET stock_quantity = stock_quantity + %d 
                     WHERE id = %d AND manage_stock = 1",
                    (int) $item['quantity'],
                    (int) $item['product_id']
                ));
            }
        }
    }
}
