<?php

namespace Modules\POS\Controllers;

use core\Controller;
use core\Auth;
use core\Database;
use core\Session;
use core\Security;
use Modules\POS\Models\Payment;

class PaymentController extends Controller
{
    private Payment $paymentModel;

    public function __construct()
    {
        parent::__construct();
        $this->paymentModel = new Payment();
    }

    public function index(): void
    {
        $this->requirePermission('invoices_payment');

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

        $query = $db->table('invoice_payments p')
            ->select('p.*, i.invoice_number, i.total as invoice_total,
                      c.first_name as customer_first_name, c.last_name as customer_last_name')
            ->leftJoin('invoices i', 'p.invoice_id', '=', 'i.id')
            ->leftJoin('customers c', 'i.customer_id', '=', 'c.id')
            ->where('i.deleted_at', 'IS', null);

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

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

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

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

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

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

        $validated = $this->validate([
            'payment_method' => 'required|in:cash,card,bank_transfer,gift_card,advance',
            'amount' => 'required|numeric|min:0.01',
            'reference' => 'max_length:255',
        ]);

        $db->beginTransaction();

        try {
            $paymentId = $db->table('invoice_payments')->insert([
                'invoice_id' => $invoiceId,
                'payment_method' => $validated['payment_method'],
                'amount' => (float)$validated['amount'],
                'reference_number' => $validated['reference'] ?? null,
                'created_at' => date(DATE_TIME_FORMAT),
            ]);

            $totalPaid = $db->table('invoice_payments')
                ->where('invoice_id', $invoiceId)
                ->sum('amount');

            $newStatus = $totalPaid >= $invoice->total ? 'paid' : 'partial';
            $balance = $invoice->total - $totalPaid;

            $db->table('invoices')
                ->where('id', $invoiceId)
                ->update([
                    'paid_amount' => $totalPaid,
                    'balance_amount' => max(0, $balance),
                    'payment_status' => $newStatus,
                    'updated_at' => date(DATE_TIME_FORMAT),
                ]);

            $db->commit();

            $this->logActivity('payment', 'Recorded payment of ' . currency((float)$validated['amount']) . ' for invoice #' . $invoice->invoice_number);
            $this->logAudit('create', 'invoice_payments', $paymentId, null, $validated);

            $this->success(['payment_id' => $paymentId], 'Payment recorded successfully.');
        } catch (\Throwable $e) {
            $db->rollback();
            $this->error('Failed to record payment: ' . $e->getMessage());
        }
    }
}
