<?php

namespace App\Http\Controllers\Accounting;

use App\Http\Controllers\Controller;
use App\Models\CustomerBalance;
use App\Models\PaymentVoucher;
use App\Models\ReceiptVoucher;
use App\Models\Settings\DataSettings\PaymentMethod;
use App\Models\Subscription;
use App\Models\VoucherAttachment;
use App\Traits\Basics\HandlesJsonExceptions;
use App\Traits\Basics\HasCrudActions;
use App\Traits\Basics\Yajra\Accounting\PaymentVouchersTable;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Illuminate\View\View;
use Exception;

class PaymentVoucherController extends Controller
{
    use PaymentVouchersTable;
    use HasCrudActions, HandlesJsonExceptions;

    /** ==============* Properties *============== */
    protected string $model = PaymentVoucher::class;
    protected string $viewPath = 'accounting.payment-vouchers.';


    /** ==============* Index & View *============== */
    public function index(): View
    {
        return view("{$this->viewPath}.index");
    }

    /** ==============* Create & Store *============== */
    public function create()
    {
        return view("{$this->viewPath}.create-edit");
    }

    public function store(Request $request): ?JsonResponse
    {
        $lock = acquire_lock("{$this->model}_lock");
        if ($lock instanceof JsonResponse) return $lock;

        $request->validate([
            'customer_id' => 'nullable|exists:customers,id',
            'subscription_id' => 'nullable|exists:subscriptions,id',
            'payment_method_id' => 'required|exists:payment_methods,id',
            'amount' => 'required|numeric|min:0.01',
            'payment_date' => 'required|date',
            'type' => 'required|in:internal,external',
            'payee_name' => 'required_if:type,external',
            'reference_number' => 'nullable|string|max:100',
            'notes' => 'nullable|string',
            'attachments.*' => 'nullable|file|mimes:pdf,jpg,jpeg,png|max:2048'
        ]);

        $paymentMethod = PaymentMethod::active()->find($request->payment_method_id);

        if ($paymentMethod?->payment_type === 'bank' && !$request->filled('bank_id')) {
            return response()->json([
                'error' => true,
                'message' => __('Bank is required for bank payment methods')
            ], 422);
        }

        if ($request->type === 'external' && !$request->filled('payee_name')) {
            return response()->json([
                'error' => true,
                'message' => __('Payee name is required for external payments')
            ], 422);
        }

        try {
            DB::beginTransaction();

            $voucher = PaymentVoucher::create([
                'customer_id' => $request->customer_id,
                'subscription_id' => $request->subscription_id,
                'payment_method_id' => $request->payment_method_id,
                'amount' => $request->amount,
                'payment_date' => $request->payment_date,
                'type' => $request->type,
                'payee_name' => $request->payee_name,
                'reference_number' => $request->reference_number,
                'notes' => $request->notes,
                'status' => 'active',
                'created_by' => Auth::id(),
            ]);

            if ($request->hasFile('attachments')) {
                foreach ($request->file('attachments') as $file) {
                    $path = $file->store('vouchers/payment/' . $voucher->voucher_number, 'public');

                    VoucherAttachment::create([
                        'voucherable_type' => PaymentVoucher::class,
                        'voucherable_id' => $voucher->id,
                        'file_name' => $file->getClientOriginalName(),
                        'file_path' => $path,
                        'file_type' => $file->getClientMimeType(),
                        'file_size' => $file->getSize(),
                        'uploaded_by' => Auth::id()
                    ]);
                }
            }

            if ($voucher->customer_id) {
                $currentBalance = $item->customer->current_balance ?? 0;
                if ($currentBalance < $request->amount) {
                    return response()->json([
                        'error' => true,
                        'message' => __('Insufficient Balance'),
                    ]);
                }

                $walletDisabled = settings("activate_wallet") == 0;
                if (!$walletDisabled) {
                    $customerBalance = CustomerBalance::getOrCreateForCustomer($voucher->customer_id);
                    $customerBalance->updateBalance($voucher->amount, 'expense', $voucher->id, 'صرف مبلغ', Auth::id());
                }

            }

            DB::commit();

            return response()->json([
                'success' => true,
                'message' => __("messages.success_creating_item"),
                'redirect' => $voucher->type === "external",
                'redirect_route' => route('accounting.external-payment-vouchers.index'),
            ]);

        } catch (Exception $e) {
            DB::rollBack();
            return response()->json([
                'error' => true,
                'message' => $e->getMessage()
            ]);
        } finally {
            optional($lock)->release();
        }
    }

    public function cancel(Request $request): ?JsonResponse
    {
        $request->validate([
            'cancellation_reason' => 'required|string',
        ]);

        try {
            DB::beginTransaction();

            $voucher = PaymentVoucher::find($request->id);

            if ($voucher->status === 'canceled') {
                return response()->json([
                    'error' => true,
                    'message' => __("This payment voucher is already canceled.")
                ], 400);
            }

            $amount = $voucher->amount ?? 0;

            $voucher->status = 'canceled';
            $voucher->cancellation_reason = $request->cancellation_reason;
            $voucher->canceled_at = now();
            $voucher->canceled_by = Auth::id();
            $voucher->save();

            if (!empty($voucher->customer_id)) {
                $receipt = ReceiptVoucher::create([
                    'customer_id'         => $voucher->customer_id,
                    'subscription_id'     => $voucher->subscription_id,
                    'payment_method_id'   => $voucher->payment_method_id,
                    'created_by'          => Auth::id(),
                    'amount'              => $amount,
                    'payment_date'        => now(),
                    'type'                => !empty($voucher->subscription_id) ? 'subscription' : 'other',
                    'reference_number'    => $voucher->reference_number,
                    'notes'               => 'سند قبض لسند صرف تم الغاءه',
                ]);

                $walletDisabled = settings("activate_wallet") == 0;
                if (!$walletDisabled) {
                    $customerBalance = CustomerBalance::getOrCreateForCustomer($receipt->customer_id);
                    $customerBalance->updateBalance($amount, 'deposit', $receipt->id, 'سند قبض لسند صرف تم الغاءه', Auth::id());
                }
            }

            DB::commit();

            return response()->json([
                'success' => true,
                'message' => __('The payment voucher has been successfully canceled'),
//                'message' => __("The payment voucher has been successfully canceled, and the amount of :amount has been credited to the customer's account.", [
//                    'amount' => getPriceFormat($amount)
//                ])
            ]);

        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json([
                'error' => true,
                'message' => $e->getMessage()
            ], 500);
        }
    }

    public function print($id)
    {
        try {
            $voucher = PaymentVoucher::with([
                'customer',
                'subscription.plan',
                'paymentMethod',
                'creator',
                'approver'
            ])->findOrFail($id);

            return view('payment-vouchers.print', compact('voucher'));

        } catch (Exception $e) {
            return redirect()->back()->with('error', 'حدث خطأ: ' . $e->getMessage());
        }
    }

}
