<?php

namespace App\Http\Controllers;

use App\Http\Requests\StoreCustomerPaymentRequest;
use App\Models\Customer;
use App\Models\Sale;
use App\Support\CashSaleCustomer;
use App\Support\CustomerAccountLedger;
use App\Support\CustomerPaymentType;
use App\Support\PurchaseCurrency;
use App\Support\SupplierPaymentMethod;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Inertia\Response;

class CustomerPaymentController extends Controller
{
    public function create(Request $request, Customer $customer): Response
    {
        if (CashSaleCustomer::isCashCustomerModel($customer)) {
            abort(404);
        }

        $defaultType = $request->string('type')->toString();
        if (! in_array($defaultType, CustomerPaymentType::values(), true)) {
            $defaultType = CustomerPaymentType::SALE;
        }

        $openSales = CustomerAccountLedger::openSalesForCustomer($customer, oldestFirst: true)->all();
        $openBalancesAfn = CustomerAccountLedger::openBalancesForCustomer(
            $customer,
            PurchaseCurrency::AFN,
        )->all();
        $openBalancesUsd = CustomerAccountLedger::openBalancesForCustomer(
            $customer,
            PurchaseCurrency::USD,
        )->all();
        $openSalesAfn = array_values(array_filter(
            $openSales,
            fn (array $sale): bool => ($sale['currency'] ?? PurchaseCurrency::AFN) === PurchaseCurrency::AFN,
        ));
        $openSalesUsd = array_values(array_filter(
            $openSales,
            fn (array $sale): bool => ($sale['currency'] ?? null) === PurchaseCurrency::USD,
        ));

        return Inertia::render('customers/payments/create', [
            'customer' => [
                'id' => $customer->id,
                'full_name' => $customer->full_name,
            ],
            'summary' => CustomerAccountLedger::summary($customer),
            'summaries' => CustomerAccountLedger::summaries($customer),
            'defaultPaymentType' => $defaultType,
            'openSales' => $openSales,
            'openBalances' => $openBalancesAfn,
            'openSalesByCurrency' => [
                PurchaseCurrency::AFN => $openSalesAfn,
                PurchaseCurrency::USD => $openSalesUsd,
            ],
            'openBalancesByCurrency' => [
                PurchaseCurrency::AFN => $openBalancesAfn,
                PurchaseCurrency::USD => $openBalancesUsd,
            ],
            'paymentMethods' => SupplierPaymentMethod::values(),
            'currencies' => PurchaseCurrency::values(),
            'paymentTypes' => CustomerPaymentType::values(),
        ]);
    }

    public function store(
        StoreCustomerPaymentRequest $request,
        Customer $customer,
    ): RedirectResponse {
        if (CashSaleCustomer::isCashCustomerModel($customer)) {
            abort(404);
        }

        $validated = $request->validated();

        $paymentData = [
            'currency' => $validated['currency'],
            'amount' => $validated['amount'],
            'bill_payment_amount' => $validated['bill_payment_amount'] ?? null,
            'bill_currency' => $validated['bill_currency'] ?? null,
            'paid_at' => $validated['paid_at'],
            'payment_method' => $validated['payment_method'] ?? null,
            'reference' => $validated['reference'] ?? null,
            'notes' => $validated['notes'] ?? null,
            'exchange_rate' => $validated['exchange_rate'] ?? null,
        ];

        try {
            if ($validated['payment_type'] === CustomerPaymentType::SALE) {
                /** @var Sale $sale */
                $sale = Sale::query()->findOrFail((int) $validated['sale_id']);
                CustomerAccountLedger::recordPaymentForSale($sale, $paymentData);
            } else {
                CustomerAccountLedger::recordOverallPayment($customer, $paymentData);
            }
        } catch (\InvalidArgumentException $exception) {
            return redirect()
                ->back()
                ->withInput()
                ->withErrors(['payment' => $exception->getMessage()]);
        }

        return redirect()
            ->route('customers.account', $customer)
            ->with('status', __('Customer payment recorded.'));
    }
}
