<?php

namespace App\Services\Finance;

use Illuminate\Database\Query\Builder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;

class FinancialPaymentService
{
    public function paymentsByInvoice(?string $schoolYear, ?string $dateFrom, ?string $dateTo): array
    {
        $query = $this->applyPaymentFilters($this->buildPaymentQuery($schoolYear, $dateFrom, $dateTo));

        return $query
            ->selectRaw('invoice_id, SUM(paid_amount) AS paid_amount')
            ->whereNotNull('invoice_id')
            ->groupBy('invoice_id')
            ->get()
            ->map(fn ($row) => (array) $row)
            ->all();
    }

    public function paymentBreakdown(?string $schoolYear, ?string $dateFrom, ?string $dateTo): array
    {
        $query = $this->applyPaymentFilters($this->buildPaymentQuery($schoolYear, $dateFrom, $dateTo));

        $rows = $query
            ->selectRaw("
                invoice_id,
                CASE
                    WHEN LOWER(TRIM(payment_method)) = 'cash' THEN 'cash'
                    WHEN LOWER(TRIM(payment_method)) IN ('check','cheque') THEN 'check'
                    WHEN LOWER(TRIM(payment_method)) IN ('credit','card','credit card','debit','debit card','visa','mastercard') THEN 'credit'
                    ELSE 'other'
                END AS method,
                SUM(paid_amount) AS amount
            ")
            ->whereNotNull('invoice_id')
            ->groupBy('invoice_id', 'method')
            ->get()
            ->map(fn ($row) => (array) $row)
            ->all();

        $breakdown = [];
        foreach ($rows as $row) {
            $invoiceId = (int) ($row['invoice_id'] ?? 0);
            if ($invoiceId <= 0) {
                continue;
            }
            $method = (string) ($row['method'] ?? '');
            $amount = (float) ($row['amount'] ?? 0);
            if (!isset($breakdown[$invoiceId])) {
                $breakdown[$invoiceId] = [];
            }
            $breakdown[$invoiceId][$method] = $amount;
        }

        return $breakdown;
    }

    public function paymentTotals(?string $schoolYear, ?string $dateFrom, ?string $dateTo): array
    {
        $query = $this->applyPaymentFilters($this->buildPaymentQuery($schoolYear, $dateFrom, $dateTo));

        $row = (array) $query
            ->selectRaw("
                SUM(paid_amount) AS total_all,
                SUM(CASE WHEN LOWER(TRIM(payment_method)) = 'cash' THEN paid_amount ELSE 0 END) AS total_cash,
                SUM(CASE WHEN LOWER(TRIM(payment_method)) IN ('check','cheque') THEN paid_amount ELSE 0 END) AS total_check,
                SUM(CASE WHEN LOWER(TRIM(payment_method)) IN ('credit','card','credit card','debit','debit card','visa','mastercard') THEN paid_amount ELSE 0 END) AS total_credit
            ")
            ->whereNotNull('invoice_id')
            ->first();

        return [
            'total_all' => (float) ($row['total_all'] ?? 0),
            'total_cash' => (float) ($row['total_cash'] ?? 0),
            'total_check' => (float) ($row['total_check'] ?? 0),
            'total_credit' => (float) ($row['total_credit'] ?? 0),
        ];
    }

    private function buildPaymentQuery(?string $schoolYear, ?string $dateFrom, ?string $dateTo): Builder
    {
        $query = DB::table('payments');

        if (!empty($schoolYear)) {
            $query->where('school_year', $schoolYear);
        }
        if (!empty($dateFrom)) {
            $query->whereRaw('DATE(payment_date) >= ?', [$dateFrom]);
        }
        if (!empty($dateTo)) {
            $query->whereRaw('DATE(payment_date) <= ?', [$dateTo]);
        }

        return $query;
    }

    private function applyPaymentFilters(Builder $query): Builder
    {
        $exclude = ['void', 'voided', 'refunded', 'failed', 'chargeback', 'declined', 'reversed', 'canceled', 'cancelled'];

        if (Schema::hasColumn('payments', 'status')) {
            $query->where(function ($q) use ($exclude) {
                $q->whereNotIn('status', $exclude)->orWhereNull('status');
            });
        }

        if (Schema::hasColumn('payments', 'is_void')) {
            $query->where(function ($q) {
                $q->where('is_void', 0)->orWhereNull('is_void');
            });
        }

        return $query;
    }
}
