<?php

namespace Modules\POS\Controllers;

use core\Controller;
use core\Auth;
use core\Database;
use core\Session;
use core\Security;

class RefundController extends Controller
{
    public function index(): void
    {
        $this->requirePermission('pos_refund');

        $db = Database::getInstance();
        $dateFrom = $this->request->get('date_from', '');
        $dateTo = $this->request->get('date_to', '');
        $search = $this->request->get('search', '');
        $page = max(1, (int)$this->request->get('page', 1));
        $perPage = PAGINATION_LIMIT;

        $query = $db->table('refunds r')
            ->select('r.*, i.invoice_number, i.total as invoice_total,
                      c.first_name as customer_first_name, c.last_name as customer_last_name,
                      u.first_name as user_first_name, u.last_name as user_last_name')
            ->leftJoin('invoices i', 'r.invoice_id', '=', 'i.id')
            ->leftJoin('customers c', 'i.customer_id', '=', 'c.id')
            ->leftJoin('users u', 'r.created_by', '=', 'u.id');

        if (!empty($dateFrom)) {
            $query->where('r.created_at', '>=', $dateFrom . ' 00:00:00');
        }
        if (!empty($dateTo)) {
            $query->where('r.created_at', '<=', $dateTo . ' 23:59:59');
        }
        if (!empty($search)) {
            $query->where(function ($q) use ($search) {
                $term = '%' . $search . '%';
                $q->where('i.invoice_number', 'LIKE', $term)
                  ->orWhere('r.reason', 'LIKE', $term)
                  ->orWhere('c.first_name', 'LIKE', $term)
                  ->orWhere('c.last_name', 'LIKE', $term);
            });
        }

        $refunds = $query->orderBy('r.created_at', 'DESC')
            ->paginate($perPage, $page);

        $this->view('POS/refunds', [
            'title' => 'Refunds',
            'breadcrumb' => ['Refunds' => url('refunds')],
            'refunds' => $refunds,
            'dateFrom' => $dateFrom,
            'dateTo' => $dateTo,
            'search' => $search,
        ]);
    }

    public function store(int $invoiceId): void
    {
        $this->requirePermission('pos_refund');

        $db = Database::getInstance();
        $invoice = $db->table('invoices')->find($invoiceId);

        if (!$invoice || $invoice->deleted_at) {
            $this->error('Invoice not found.', 404);
        }

        if ($invoice->payment_status === 'refunded') {
            $this->error('Invoice is already refunded.');
        }

        $validated = $this->validate([
            'refund_amount' => 'required|numeric|min:0.01|max:' . $invoice->paid_amount,
            'refund_reason' => 'required|max_length:2000',
        ]);

        $db->beginTransaction();

        try {
            $refundId = $db->table('refunds')->insert([
                'invoice_id' => $invoiceId,
                'amount' => (float)$validated['refund_amount'],
                'reason' => $validated['refund_reason'],
                'refund_method' => 'cash',
                'created_by' => Auth::id(),
                'created_at' => date(DATE_TIME_FORMAT),
            ]);

            $totalRefunded = (float)$validated['refund_amount'];

            $newPaidAmount = $invoice->paid_amount - $totalRefunded;
            $paymentStatus = 'refunded';

            if ($newPaidAmount <= 0) {
                $paymentStatus = 'refunded';
                $newPaidAmount = 0;
            } elseif ($newPaidAmount < $invoice->total) {
                $paymentStatus = 'partial';
            }

            $db->table('invoices')
                ->where('id', $invoiceId)
                ->update([
                    'paid_amount' => $newPaidAmount,
                    'balance_amount' => $invoice->total - $newPaidAmount,
                    'payment_status' => $paymentStatus,
                    'updated_at' => date(DATE_TIME_FORMAT),
                ]);

            $db->commit();

            $this->logActivity('refund', 'Refunded ' . currency($totalRefunded) . ' for invoice #' . $invoice->invoice_number);
            $this->logAudit('create', 'refunds', $refundId, null, $validated);

            $this->success(['refund_id' => $refundId], 'Refund processed successfully.');
        } catch (\Throwable $e) {
            $db->rollback();
            $this->error('Failed to process refund: ' . $e->getMessage());
        }
    }
}
