<?php

namespace App\Services\Admin\Finances;

use App\Enums\PaymentStatus;
use App\Models\TuitionInvoice;
use App\Models\TuitionPayment;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Http\UploadedFile;

class TuitionPaymentService
{
    public function forInvoice(TuitionInvoice $invoice): Collection
    {
        return $invoice->payments()
            ->with('recorder.profile')
            ->latest('paid_at')
            ->get();
    }

    public function create(TuitionInvoice $invoice, array $data, ?UploadedFile $file): TuitionPayment
    {
        $payment = $invoice->payments()->create([
            'amount_paid' => $data['amount_paid'],
            'paid_at' => $data['paid_at'],
            'payment_method' => $data['payment_method'] ?? null,
            'status' => $this->resolveStatus($invoice, $data['amount_paid']),
            'recorded_by' => auth()->id(),
            'notes' => $data['notes'] ?? null,
        ]);

        if ($file) {
            $payment->addMedia($file)->toMediaCollection('payment_proof');
        }

        return $payment;
    }

    public function update(TuitionPayment $payment, array $data, ?UploadedFile $file): TuitionPayment
    {
        $payment->amount_paid = $data['amount_paid'];
        $payment->paid_at = $data['paid_at'];
        $payment->payment_method = $data['payment_method'] ?? null;
        $payment->status = $this->resolveStatus($payment->invoice, $data['amount_paid'], excludePaymentId: $payment->id);
        $payment->notes = $data['notes'] ?? null;
        $payment->update();

        if ($file) {
            $payment->addMedia($file)->toMediaCollection('payment_proof');
        }

        return $payment;
    }

    public function delete(TuitionPayment $payment): bool
    {
        return $payment->delete();
    }

    private function resolveStatus(TuitionInvoice $invoice, float|string $amountPaid, ?int $excludePaymentId = null): PaymentStatus
    {
        $otherPaidTotal = $invoice->payments()
            ->when($excludePaymentId, fn ($query) => $query->where('id', '!=', $excludePaymentId))
            ->sum('amount_paid');

        $totalPaid = round($otherPaidTotal + (float) $amountPaid, 2);
        $amountDue = round((float) $invoice->amount_due, 2);

        return $totalPaid >= $amountDue ? PaymentStatus::Paid : PaymentStatus::Partial;
    }
}
