<?php
/**
 * RefundService
 * Handles refund request, Admin approval/rejection
 */

require_once __DIR__ . '/../Models/Refund.php';
require_once __DIR__ . '/../Models/Payment.php';
require_once __DIR__ . '/../Models/AdminAuditLog.php';

class RefundService {
    private Refund        $refundModel;
    private Payment       $paymentModel;
    private AdminAuditLog $auditLog;
    private PDO           $db;

    public function __construct() {
        $this->refundModel  = new Refund();
        $this->paymentModel = new Payment();
        $this->auditLog     = new AdminAuditLog();

        require_once __DIR__ . '/../../database/Database.php';
        $this->db = Database::getInstance();
    }

    public function getAdminRefunds(array $filters = [], int $page = 1, int $perPage = 20): array {
        $offset = ($page - 1) * $perPage;
        $items  = $this->refundModel->getAdminRefunds($filters, $perPage, $offset);
        $total  = $this->refundModel->countAdminRefunds($filters);
        $stats  = $this->refundModel->getRefundStats();

        return [
            'items'      => $items,
            'total'      => $total,
            'page'       => $page,
            'per_page'   => $perPage,
            'total_pages' => (int)ceil($total / $perPage),
            'stats'      => $stats,
        ];
    }

    public function findById(int $id): ?array {
        return $this->refundModel->findById($id);
    }

    /**
     * Customer requests a refund for a confirmed payment
     */
    public function requestRefund(int $paymentId, int $userId, string $reason, ?float $amount = null): array {
        $payment = $this->paymentModel->findById($paymentId);
        if (!$payment || (int)$payment['customer_id'] !== $userId) {
            return ['success' => false, 'message' => 'ไม่พบรายการชำระเงิน'];
        }

        if ($payment['payment_status'] !== 'confirmed') {
            return ['success' => false, 'message' => 'สามารถขอคืนเงินได้เฉพาะการชำระที่ยืนยันแล้วเท่านั้น'];
        }

        $orderId = (int)$payment['order_id'];
        if ($this->refundModel->hasActiveRefund($orderId)) {
            return ['success' => false, 'message' => 'มีคำขอคืนเงินที่อยู่ระหว่างดำเนินการอยู่แล้ว'];
        }

        $order = $this->db->query("SELECT * FROM `orders` WHERE `id` = {$orderId}")->fetch(PDO::FETCH_ASSOC);
        $storeId = $order ? (int)$order['store_id'] : 0;

        $refundAmount = $amount ?? (float)$payment['amount'];
        if ($refundAmount > (float)$payment['amount']) {
            return ['success' => false, 'message' => 'จำนวนเงินคืนต้องไม่เกินยอดที่ชำระ'];
        }

        $this->db->beginTransaction();
        try {
            $refundId = $this->refundModel->insert([
                'order_id'     => $orderId,
                'customer_id'  => $userId,
                'store_id'     => $storeId,
                'amount'       => $refundAmount,
                'reason'       => trim($reason),
                'status'       => 'pending',
                'created_at'   => date('Y-m-d H:i:s'),
                'updated_at'   => date('Y-m-d H:i:s'),
            ]);

            // Update payment status
            $this->paymentModel->updateStatus($paymentId, 'refund_pending');
            $this->db->prepare("UPDATE `orders` SET `payment_status` = 'refund_pending' WHERE `id` = :oid")
                ->execute([':oid' => $orderId]);

            $this->db->commit();
            return ['success' => true, 'refund_id' => $refundId, 'message' => 'ส่งคำขอคืนเงินเรียบร้อยแล้ว'];

        } catch (Exception $e) {
            $this->db->rollBack();
            return ['success' => false, 'message' => 'เกิดข้อผิดพลาด: ' . $e->getMessage()];
        }
    }

    public function approveRefund(int $refundId, int $adminId, ?string $note = null): array {
        $refund = $this->refundModel->findById($refundId);
        if (!$refund || $refund['status'] !== 'pending') {
            return ['success' => false, 'message' => 'ไม่พบคำขอหรือสถานะไม่ถูกต้อง'];
        }

        $this->db->beginTransaction();
        try {
            $this->refundModel->updateStatus($refundId, 'approved', [
                'admin_id'     => $adminId,
                'admin_note'   => $note,
                'processed_at' => date('Y-m-d H:i:s'),
            ]);

            $this->auditLog->record($adminId, 'refund.approve', 'payment', 'refund', $refundId,
                json_encode(['order_no' => $refund['order_no'] ?? $refund['order_id'], 'amount' => $refund['amount'], 'note' => $note]));

            $this->db->commit();
            return ['success' => true, 'message' => 'อนุมัติคำขอคืนเงินแล้ว'];
        } catch (Exception $e) {
            $this->db->rollBack();
            return ['success' => false, 'message' => 'เกิดข้อผิดพลาด: ' . $e->getMessage()];
        }
    }

    public function completeRefund(int $refundId, int $adminId): array {
        $refund = $this->refundModel->findById($refundId);
        if (!$refund || $refund['status'] !== 'approved') {
            return ['success' => false, 'message' => 'ไม่พบคำขอหรือสถานะไม่ถูกต้อง'];
        }

        $this->db->beginTransaction();
        try {
            $this->refundModel->updateStatus($refundId, 'refunded', [
                'admin_id'     => $adminId,
                'processed_at' => date('Y-m-d H:i:s'),
            ]);

            // Update payment & order status to refunded
            $orderId = (int)$refund['order_id'];
            $payment = $this->paymentModel->findByOrderId($orderId);
            if ($payment) {
                $this->paymentModel->updateStatus((int)$payment['id'], 'refunded');
            }

            $this->db->prepare("UPDATE `orders` SET `payment_status` = 'refunded', `order_status` = 'refunded', `updated_at` = NOW() WHERE `id` = :oid")
                ->execute([':oid' => $orderId]);

            $this->auditLog->record($adminId, 'refund.complete', 'payment', 'refund', $refundId,
                json_encode(['order_no' => $refund['order_no'] ?? $refund['order_id'], 'amount' => $refund['amount']]));

            $this->db->commit();
            return ['success' => true, 'message' => 'ดำเนินการคืนเงินสำเร็จ'];
        } catch (Exception $e) {
            $this->db->rollBack();
            return ['success' => false, 'message' => 'เกิดข้อผิดพลาด: ' . $e->getMessage()];
        }
    }

    public function rejectRefund(int $refundId, int $adminId, string $reason): array {
        $refund = $this->refundModel->findById($refundId);
        if (!$refund || $refund['status'] !== 'pending') {
            return ['success' => false, 'message' => 'ไม่พบคำขอหรือสถานะไม่ถูกต้อง'];
        }

        $this->db->beginTransaction();
        try {
            $this->refundModel->updateStatus($refundId, 'rejected', [
                'admin_id'     => $adminId,
                'admin_note'   => $reason,
                'processed_at' => date('Y-m-d H:i:s'),
            ]);

            // Revert payment status back to confirmed
            $orderId = (int)$refund['order_id'];
            $payment = $this->paymentModel->findByOrderId($orderId);
            if ($payment) {
                $this->paymentModel->updateStatus((int)$payment['id'], 'confirmed');
            }

            $this->db->prepare("UPDATE `orders` SET `payment_status` = 'confirmed', `updated_at` = NOW() WHERE `id` = :oid")
                ->execute([':oid' => $orderId]);

            $this->auditLog->record($adminId, 'refund.reject', 'payment', 'refund', $refundId,
                json_encode(['order_no' => $refund['order_no'] ?? $refund['order_id'], 'reason' => $reason]));

            $this->db->commit();
            return ['success' => true, 'message' => 'ปฏิเสธคำขอคืนเงินแล้ว'];
        } catch (Exception $e) {
            $this->db->rollBack();
            return ['success' => false, 'message' => 'เกิดข้อผิดพลาด: ' . $e->getMessage()];
        }
    }
}
