<?php

namespace App\Controllers;

use App\Models\FolioModel;
use App\Models\FolioPaymentModel;
use App\Models\PaymentAttemptModel;
use Config\Lookups;

/**
 * Hotel-wide payments ledger — new page (payments previously only
 * visible one folio at a time). Merges two real sources: FolioPaymentModel
 * (settled payments and refunds — cash/mobile money/card/Hubtel, always
 * "successful" by the time a row exists there — see is_refund) and
 * PaymentAttemptModel (Hubtel checkouts still pending or that failed — a
 * settled Hubtel payment shows up via FolioPaymentModel instead, written
 * by PaymentWebhookController on success, so there's no double-counting).
 */
class PaymentController extends BaseController
{
    public function index()
    {
        $payments = (new FolioPaymentModel())
            ->select('folio_payments.*, folios.guest_id, guests.full_name as guest_name')
            ->join('folios', 'folios.id = folio_payments.folio_id')
            ->join('guests', 'guests.id = folios.guest_id')
            ->orderBy('folio_payments.paid_at', 'desc')
            ->findAll();

        foreach ($payments as $p) {
            $p->tx_status = $p->is_refund ? 'refunded' : 'success';
            $p->when      = $p->paid_at;
        }

        $pendingAttempts = (new PaymentAttemptModel())
            ->select('payment_attempts.*, folios.guest_id, guests.full_name as guest_name')
            ->join('folios', 'folios.id = payment_attempts.folio_id', 'left')
            ->join('guests', 'guests.id = folios.guest_id', 'left')
            ->where('payment_attempts.purpose', 'folio_payment')
            ->whereIn('payment_attempts.status', ['pending', 'failed'])
            ->orderBy('payment_attempts.created_at', 'desc')
            ->findAll();

        foreach ($pendingAttempts as $a) {
            $a->method    = 'hubtel_momo';
            $a->tx_status = $a->status;
            $a->when      = $a->created_at;
            $a->guest_name = $a->guest_name ?? 'Unknown';
        }

        $all = array_merge($payments, $pendingAttempts);
        usort($all, static fn ($a, $b) => strtotime($b->when) <=> strtotime($a->when));

        $today        = date('Y-m-d');
        $monthStart   = date('Y-m-01');
        $todayTotal   = '0.00';
        $monthTotal   = '0.00';
        $refundToday  = '0.00';

        foreach ($payments as $p) {
            if ($p->is_refund) {
                if (substr($p->paid_at, 0, 10) === $today) {
                    $refundToday = money_add($refundToday, $p->amount);
                }

                continue; // refunds tracked separately, not counted as collections
            }

            if (substr($p->paid_at, 0, 10) === $today) {
                $todayTotal = money_add($todayTotal, $p->amount);
            }

            if (substr($p->paid_at, 0, 10) >= $monthStart) {
                $monthTotal = money_add($monthTotal, $p->amount);
            }
        }

        $outstanding = '0.00';

        foreach ((new FolioModel())->where('status', 'open')->findAll() as $folio) {
            $outstanding = money_add($outstanding, (new FolioModel())->balanceDue($folio->id));
        }

        return view('payments/index', [
            'pageTitle'    => 'Payments',
            'pageSubtitle' => 'Track and manage guest payments and transactions.',
            'transactions' => $all,
            'stats'        => [
                'today'    => $todayTotal,
                'todayCount' => count(array_filter($payments, static fn ($p) => ! $p->is_refund && substr($p->paid_at, 0, 10) === $today)),
                'month'    => $monthTotal,
                'pending'  => count(array_filter($pendingAttempts, static fn ($a) => $a->status === 'pending')),
                'outstanding' => $outstanding,
                'refundedToday' => $refundToday,
            ],
            'lookups' => new Lookups(),
        ]);
    }
}
