<?php

namespace App\Http\Controllers;

use App\AccountsPermissions;
use App\Employees;
use App\PaymentVoucher;
use App\Http\Controllers\Controller;
use App\Payment;
use App\TransactionAccount;
use App\Voucher;
use App\VouchersUniqueNumber;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Yajra\DataTables\Facades\DataTables;

class PaymentVoucherController extends Controller
{

    protected string $module = 'Payment Vouchers';

    public function __construct()
    {
        $module = $this->module;

        $this->middleware("permission:$module list")->only(['index']);
        $this->middleware("permission:$module view")->only(['show']);
        $this->middleware("permission:$module add")->only(['create', 'store']);
        $this->middleware("permission:$module edit")->only(['edit', 'update']);
        $this->middleware("permission:$module delete")->only(['destroy']);
    }

    public function index()
    {
        // $vouchersNumber = VouchersUniqueNumber::with('vouchers')->where('voucher_type', 'Payment Voucher')->get();

        return view('payment_voucher.index');
    }

    public function voucher_listing(Request $request)
    {
        $vouchers = Voucher::with('uniqueNumber')
            ->whereHas('uniqueNumber', function ($q) {
                $q->where('voucher_type', 'Payment Voucher');
            })
            ->select([
                'id_vouchers',
                'vouchers_unique_number_id',
                'voucher_date',
                'voucher_giver',
                'net_amount',
                'payment_mode',
                'voucher_invno',
                'adaegi_array',
                'created_at'
            ])
            ->orderByDesc('id_vouchers');

        return DataTables::eloquent($vouchers)
            ->addColumn('voucher_number', function ($voucher) {
                return optional($voucher->uniqueNumber)->voucher_number ?? '';
            })
            ->addColumn('action', function ($voucher) {
                return view('components.voucher-actions', [
                    'viewRoute' => route('voucher.p_view', Crypt::encrypt($voucher->vouchers_unique_number_id)),
                    'editRoute' => route('payment_voucher.edit', Crypt::encrypt($voucher->id_vouchers)),
                    'deleteRoute' => route('payment_voucher.destroy', Crypt::encrypt($voucher->id_vouchers)),
                    'viewPermission' => 'Payment Vouchers view',
                    'editPermission' => 'Payment Vouchers edit',
                ])->render();
            })
            ->addColumn('suppliers', function ($vouchers) {
                $badges = [];

                $items = json_decode($vouchers->adaegi_array, true);

                if (is_array($items)) {
                    $ids = collect($items)->pluck('adaegi_khata')->filter()->unique()->toArray();

                    $customerNames = \App\Suppliers::whereIn('id_supplier', $ids)
                        ->pluck('supplier_name', 'id_supplier');

                    foreach ($ids as $id) {
                        $name = $customerNames[$id] ?? 'ID#' . $id;
                        $badges[] = "<span class='badge badge-secondary me-1'>$name</span>";
                    }
                }

                return implode(' ', $badges);
            })
            ->editColumn('voucher_date', function ($voucher) {
                return \Carbon\Carbon::parse($voucher->voucher_date)->format('d M Y');
            })
            ->editColumn('net_amount', function ($voucher) {
                return number_format($voucher->net_amount, 2);
            })
            ->rawColumns(['action', 'suppliers'])
            ->make(true);
    }

    // public function voucher_listing(Request $request)
    // {
    //     // Fetch vouchers with related vouchers and necessary fields
    //     $vouchers = VouchersUniqueNumber::with(['vouchers' => function ($query) {
    //         $query->select(
    //             'vouchers.*',
    //             'account_title',
    //             'business_partner_type',
    //             'partner_name',
    //             DB::raw('IFNULL(debit, 0) as debit'),
    //             DB::raw('IFNULL(credit, 0) as credit')
    //         );
    //     }])->where('voucher_type', 'Payment Voucher')->get();

    //     // Return a DataTable instance, but treat each voucher as a new row

    //     $accountNames = AccountsPermissions::pluck('account_name')->toArray();

    //     return DataTables::of($vouchers->flatMap(function ($vouchersUnique) use ($accountNames) {
    //         return $vouchersUnique->vouchers->filter(function ($voucher) use ($accountNames) {
    //             return in_array($voucher->account_title, $accountNames);
    //         })->map(function ($voucher) use ($vouchersUnique) {
    //             return [
    //                 'voucher_number' => $vouchersUnique->voucher_number,
    //                 'voucher_date' => date('d F Y', strtotime($voucher->date)),
    //                 'debit' => number_format($voucher->debit, 2),
    //                 'credit' => number_format($voucher->credit, 2),
    //                 'account_title' => $voucher->account_title ?? '', // Transaction account name
    //                 'bp_type' => $voucher->business_partner_type ?? '', // Business partner type
    //                 'bp_name' => $voucher->partner_name ?? '',
    //                 'action' => '<a class="btn btn-outline-success btn-sm rounded-pill shadow-sm" '
    //                     . 'title="View Service Purchase Voucher" '
    //                     . 'href="' . route('voucher.p_view', Crypt::encrypt($voucher->vouchers_unique_number_id)) . '" '
    //                     . 'target="_blank"><i class="fa-solid fa-eye"></i> View</a>'
    //             ];
    //         });
    //     }))
    //         ->rawColumns(['action']) // Ensure action column is processed as raw HTML
    //         ->make(true);
    // }


    public function create()
    {
        $employees = Employees::all();
        $accounts = TransactionAccount::all();
        return view('payment_voucher.create', compact('employees', 'accounts'));
    }

    public function store(Request $request)
    {
        // Validate the incoming data
        $validatedData = $request->validate([
            'voucher_date' => 'required|date',
            'payment_mode' => 'required|string|in:cash,bank',
            'account' => 'required|string',
            'voucher_chqdate' => 'nullable|date',
            'voucher_depdate' => 'nullable|date',
            'voucher_depslipno' => 'nullable|string',
            'items' => 'required|array',
            'items.*.adaegi_khata' => 'required|integer|exists:suppliers,id_supplier',
            'items.*.credit_amount' => 'required|numeric',
            'items.*.employee' => 'nullable|string',
        ]);

        try {
            DB::beginTransaction();

            $uniqueVoucherNumber = 'RV-' . str_pad(rand(0, 99999), 5, '0', STR_PAD_LEFT);

            $voucherUniqueNumber = new VouchersUniqueNumber();
            $voucherUniqueNumber->voucher_type = 'Payment Voucher';
            $voucherUniqueNumber->voucher_number = $uniqueVoucherNumber;
            $voucherUniqueNumber->save();

            // array for JSON
            $itemsArray = [];
            $totalAmount = 0;

            foreach ($request->items as $item) {
                $itemsArray[] = [
                    'adaegi_khata' => $item['adaegi_khata'],
                    'credit_amount' => $item['credit_amount'],
                    'employee' => $item['employee'] ?? null,
                ];
                $totalAmount += $item['credit_amount'];
            }

            // Create the voucher record
            $voucher = new Voucher();
            $voucher->vouchers_unique_number_id = $voucherUniqueNumber->id_vouchers_unique_number;
            $voucher->voucher_date = $request->voucher_date;
            $voucher->payment_mode = $request->payment_mode;
            $voucher->account = $request->account;
            $voucher->voucher_details = $request->voucher_details;
            $voucher->voucher_chqno = $request->voucher_chqno;
            $voucher->voucher_chqdate = $request->voucher_chqdate;
            $voucher->voucher_depdate = $request->voucher_depdate;
            $voucher->voucher_depslipno = $request->voucher_depslipno;
            $voucher->transaction_type = $request->transaction_type;
            $voucher->net_amount = $totalAmount;
            $voucher->adaegi_array = json_encode($itemsArray); // JSON

            $voucher->save();

            DB::commit();

            return redirect()->route('payment.list')->with('success', 'Payment voucher created successfully!');
        } catch (\Exception $e) {
            DB::rollBack();
            return redirect()->back()->with('error', 'Error creating voucher: ' . $e->getMessage())->withInput();
        }
    }

    // public function store(Request $request)
    // {
    //     // Validate the incoming data
    //     $validate =   $request->validate([
    //         'voucherDate.*' => 'required|date',
    //         'accountNo.*' => 'required|string',
    //         'accountName.*' => 'required|string',
    //         'paymentMode.*' => 'required|string',
    //         'instrumentAmount.*' => 'nullable|string',
    //         'netAmount.*' => 'required|numeric',
    //         'noteRemarks.*' => 'nullable|string',
    //         'debitAMount.*' => 'nullable|numeric',
    //         'creditAmount.*' => 'nullable|numeric',
    //         'businessPartnerName.*' => 'nullable|string',
    //         'taxDebitYesNo.*' => 'nullable|required|string',
    //         'transactionAccountId.*' => 'required|string',
    //         'transactionAccountName.*' => 'required|string',
    //         'vDescription.*' => 'nullable|string',
    //         // 'voucherStatus.*' => 'required|string',
    //     ]);

    //     // Generate a unique journal voucher number (e.g., JV-XXXXX)
    //     $uniqueVoucherNumber = 'RV-' . str_pad(rand(0, 99999), 5, '0', STR_PAD_LEFT);

    //     // Create a new VouchersUniqueNumber record
    //     $voucherUniqueNumber = new VouchersUniqueNumber();
    //     $voucherUniqueNumber->voucher_type = 'Payment Voucher';
    //     $voucherUniqueNumber->voucher_number = $uniqueVoucherNumber;
    //     $voucherUniqueNumber->save();  // Save the unique voucher number record first
    //     if ($validate) {
    //         for ($i = 0; $i < count($request->accountNo); $i++) {
    //             $voucher = new Voucher();
    //             $voucher->vouchers_unique_number_id = $voucherUniqueNumber->id_vouchers_unique_number;  // Associate with unique voucher number
    //             $voucher->date = $request->voucherDate[$i];
    //             $voucher->account_no = $request->accountNo[$i];
    //             $voucher->account_title = $request->accountName[$i];
    //             $voucher->payment_mode = $request->paymentMode[$i];
    //             $voucher->instrument = $request->instrumentAmount[$i];
    //             $voucher->business_partner_type = $request->business_partner;
    //             $voucher->partner_name = $request->partner_name;
    //             $voucher->transaction_acc_no = $request->transaction_account;
    //             $voucher->transaction_acc_name = $request->transaction_account;
    //             $voucher->amount = $request->netAmount[$i];
    //             $voucher->remarks = 'Null';
    //             $voucher->debit = $request->debitAmount[$i];
    //             $voucher->credit = $request->creditAmount[$i];
    //             $voucher->tax_debit = 'No';
    //             $voucher->desciption = 'Null';
    //             $voucher->status = 'Posted';
    //             // Save the voucher
    //             $voucher->save();
    //         }
    //         return redirect()->route('payment.list')->with('success', 'Vouchers have been created successfully.');
    //     } else {
    //         // Return back with validation errors and input data
    //         return redirect()->back()->with('danger', 'Please fill up the fields.');
    //     }
    // }


    public function view($id)
    {
        try {
            $id = Crypt::decrypt($id);

            $voucherDetails = VouchersUniqueNumber::with('vouchers')
                ->where('id_vouchers_unique_number', $id)
                ->firstOrFail();

            $accountVouchers = $voucherDetails->vouchers;
            $vou_other_detail = $accountVouchers->first();

            return view('payment_voucher.view', compact('voucherDetails', 'accountVouchers', 'vou_other_detail'));
        } catch (\Illuminate\Contracts\Encryption\DecryptException $e) {
            return redirect()->back()->with('error', 'Invalid voucher ID');
        } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
            return redirect()->back()->with('error', 'Voucher not found');
        }
    }

    // public function view($id)
    // {
    //     $id = Crypt::decrypt($id);
    //     $voucherDetails = VouchersUniqueNumber::with('vouchers')->where('voucher_type', 'Payment Voucher')->where('id_vouchers_unique_number', $id)->first();
    //     $accountVouchers = $voucherDetails->vouchers->where('vouchers_unique_number_id', $id);
    //     $vou_other_detail = $voucherDetails->vouchers->where('vouchers_unique_number_id', $id)->first();

    //     return view('payment_voucher.view', compact('voucherDetails', 'accountVouchers', 'vou_other_detail'));
    // }



    public function edit($encryptedId)
    {
        try {
            $id = Crypt::decrypt($encryptedId);

            // Get the voucher with its unique number
            $voucher = Voucher::with('uniqueNumber')
                ->where('id_vouchers', $id)
                ->firstOrFail();

            // Get all related vouchers for this unique number
            $accountVouchers = Voucher::where('vouchers_unique_number_id', $voucher->vouchers_unique_number_id)
                ->get();

            // Calculate totals if needed
            $totalCredit = $accountVouchers->sum('credit');
            $totalDebit = $accountVouchers->sum('debit');

            // Get other necessary data
            $accounts = TransactionAccount::all(); // For account dropdown
            $employees = Employees::all(); // For employee dropdown if needed

            return view('payment_voucher.edit', [
                'voucher' => $voucher,
                'accountVouchers' => $accountVouchers,
                'totalCredit' => $totalCredit,
                'totalDebit' => $totalDebit,
                'accounts' => $accounts,
                'employees' => $employees
            ]);
        } catch (\Illuminate\Contracts\Encryption\DecryptException $e) {
            return redirect()->route('payment.list')->with('error', 'Invalid voucher ID');
        } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
            return redirect()->route('payment.list')->with('error', 'Voucher not found');
        }
    }

    public function update(Request $request, $encryptedId)
    {
        try {
            $id = Crypt::decrypt($encryptedId);

            $validatedData = $request->validate([
                'voucher_date' => 'required|date',
                'payment_mode' => 'required|string|in:cash,bank',
                'account' => 'required|string',
                'voucher_chqno' => 'nullable|string',
                'voucher_chqdate' => 'nullable|date',
                'voucher_depdate' => 'nullable|date',
                'voucher_depslipno' => 'nullable|string',
                'items' => 'required|array',
                'items.*.adaegi_khata' => 'required|integer|exists:suppliers,id_supplier',
                'items.*.credit_amount' => 'required|numeric',
                'items.*.employee' => 'nullable|string',
                'transaction_type' => 'required|string|in:Credit,Debit'
            ]);

            DB::beginTransaction();

            $voucher = Voucher::findOrFail($id);

            $itemsArray = [];
            $totalAmount = 0;

            foreach ($request->items as $item) {
                $itemsArray[] = [
                    'adaegi_khata' => $item['adaegi_khata'],
                    'credit_amount' => $item['credit_amount'],
                    'employee' => $item['employee'] ?? null,
                ];
                $totalAmount += $item['credit_amount'];
            }

            $voucher->update([
                'voucher_date' => $request->voucher_date,
                'payment_mode' => $request->payment_mode,
                'account' => $request->account,
                'voucher_details' => $request->voucher_details,
                'voucher_chqno' => $request->voucher_chqno,
                'voucher_chqdate' => $request->voucher_chqdate,
                'voucher_depdate' => $request->voucher_depdate,
                'voucher_depslipno' => $request->voucher_depslipno,
                'transaction_type' => $request->transaction_type,
                'net_amount' => $totalAmount,
                'adaegi_array' => json_encode($itemsArray),
            ]);

            DB::commit();

            return redirect()->route('payment.list')
                ->with('success', 'Payment voucher updated successfully');
        } catch (\Illuminate\Contracts\Encryption\DecryptException $e) {
            return redirect()->back()->with('error', 'Invalid voucher ID');
        } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
            return redirect()->back()->with('error', 'Voucher not found');
        } catch (\Exception $e) {
            DB::rollBack();
            return redirect()->back()
                ->with('error', 'Error updating voucher: ' . $e->getMessage())
                ->withInput();
        }
    }



    // public function edit($encryptedId)
    // {
    //     $id = Crypt::decrypt($encryptedId);
    //     $vouchersNumber = VouchersUniqueNumber::with('vouchers')->where('voucher_type', 'Payment Voucher')->findOrFail($id);
    //     $voucherSingle = $vouchersNumber->vouchers->first();
    //     $totalCredit = 0;
    //     $totalDebit = 0;

    //     // Loop through each voucher and accumulate the totals
    //     foreach ($vouchersNumber->vouchers as $voucher) {
    //         $totalCredit += $voucher->credit; // Sum credit amounts
    //         $totalDebit += $voucher->debit;   // Sum debit amounts
    //     }
    //     // Fetch employees and accounts for the form
    //     $employees = Employees::all();
    //     $accounts = TransactionAccount::all();

    //     $voucherDetails = VouchersUniqueNumber::with('vouchers')->where('voucher_type', 'Payment Voucher')->where('id_vouchers_unique_number', $id)->first();

    //     $vou_other_detail = $voucherDetails->vouchers->where('vouchers_unique_number_id', $id)->first();

    //     return view('payment_voucher.edit', compact('vou_other_detail', 'totalCredit', 'totalDebit', 'employees', 'accounts', 'vouchersNumber', 'voucherSingle'));
    // }

    // public function update(Request $request, $encryptedId)
    // {
    //     // Validate the incoming data
    //     $validatedData = $request->validate([
    //         'voucherDate.*' => 'required|date',
    //         'accountNo.*' => 'required|string',
    //         'accountName.*' => 'required|string',
    //         'paymentMode.*' => 'required|string',
    //         'instrumentAmount.*' => 'nullable|string',
    //         'netAmount.*' => 'required|numeric',
    //         'noteRemarks.*' => 'nullable|string',
    //         'debitAmount.*' => 'nullable|numeric',
    //         'creditAmount.*' => 'nullable|numeric',
    //         'partner_name.*' => 'required|string',
    //         'business_partner.*' => 'required|string',
    //         'taxDebitYesNo.*' => 'required|string',
    //         'vDescription.*' => 'nullable|string',
    //     ]);

    //     // Decrypt the ID
    //     $id = Crypt::decrypt($encryptedId);

    //     // Find the voucher record by the decrypted ID
    //     $voucherUniqueNumber = VouchersUniqueNumber::with('vouchers')->findOrFail($id);

    //     // Check for deleted vouchers
    //     $deletedVoucherIds = explode(',', $request->deletedVouchers);
    //     if (!empty($deletedVoucherIds)) {
    //         Voucher::whereIn('id_vouchers', $deletedVoucherIds)->delete();
    //     }

    //     // Loop through each existing voucher and update its data
    //     foreach ($voucherUniqueNumber->vouchers as $index => $voucher) {
    //         $voucher->update([
    //             'date' => $validatedData['voucherDate'][$index] ?? $voucher->date,
    //             'account_no' => $validatedData['accountNo'][$index] ?? $voucher->account_no,
    //             'account_title' => $validatedData['accountName'][$index] ?? $voucher->account_title,
    //             'payment_mode' => $validatedData['paymentMode'][$index] ?? null,
    //             'instrument' => $validatedData['instrumentAmount'][$index] ?? null,
    //             'amount' => $validatedData['netAmount'][$index] ?? null,
    //             'remarks' => $validatedData['noteRemarks'][$index] ?? null,
    //             'debit' => $validatedData['debitAmount'][$index] ?? null,
    //             'credit' => $validatedData['creditAmount'][$index] ?? null,
    //             $voucher->partner_name = $request->partner_name,
    //             $voucher->business_partner_type = $request->business_partner,

    //             'tax_debit' => 'Null',
    //             'desciption' => $validatedData['vDescription'][$index] ?? null,
    //         ]);
    //     }

    //     // Add new vouchers if they exist in the request
    //     for ($i = count($voucherUniqueNumber->vouchers); $i < count($request->accountNo); $i++) {
    //         $voucher = new Voucher();
    //         $voucher->vouchers_unique_number_id = $voucherUniqueNumber->id_vouchers_unique_number;
    //         $voucher->date = $request->voucherDate[$i];
    //         $voucher->account_no = $request->accountNo[$i];
    //         $voucher->account_title = $request->accountName[$i];
    //         $voucher->payment_mode = $request->paymentMode[$i];
    //         $voucher->instrument = $request->instrumentAmount[$i] ?? null;
    //         $voucher->amount = $request->netAmount[$i];
    //         $voucher->remarks = $request->noteRemarks[$i] ?? 'Null';
    //         $voucher->debit = $request->debitAmount[$i] ?? null;
    //         $voucher->credit = $request->creditAmount[$i] ?? null;
    //         $voucher->business_partner_type = $request->business_partner;
    //         $voucher->partner_name = $request->partner_name;
    //         $voucher->tax_debit = $request->taxDebitYesNo[$i] ?? 'No';
    //         $voucher->desciption = 'Null';
    //         $voucher->status = 'Posted';
    //         // dd($voucher);
    //         // Save the voucher
    //         $voucher->save();
    //     }

    //     // Redirect back with success message
    //     return redirect()->back()->with('success', 'Voucher updated successfully.');
    // }

    public function destroy($encryptedId)
    {
        try {
            DB::beginTransaction();

            $id = Crypt::decrypt($encryptedId);
            $voucher = Voucher::findOrFail($id);
            $uniqueNumber = $voucher->uniqueNumber;
            Voucher::where('vouchers_unique_number_id', $uniqueNumber->id_vouchers_unique_number)
                ->delete();
            $uniqueNumber->delete();
            DB::commit();

            return redirect()->route('payment.list')
                ->with('success', 'Payment voucher deleted successfully');
        } catch (\Illuminate\Contracts\Encryption\DecryptException $e) {
            DB::rollBack();
            return redirect()->route('payment.list')
                ->with('error', 'Invalid voucher ID');
        } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
            DB::rollBack();
            return redirect()->route('payment.list')
                ->with('error', 'Voucher not found');
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('Error deleting payment voucher: ' . $e->getMessage());
            return redirect()->route('payment.list')
                ->with('error', 'Error deleting voucher. Please try again.');
        }
    }
}
