<?php

namespace App\Http\Controllers;

use App\Exports\BandPurchaseExport;
use App\Models\BandProvider;
use App\Models\BandPurchase;
use App\Models\BandPurchaseItem;
use App\Models\BandSale;
use App\Models\BandService;
use App\Models\BandStock;
use App\Models\Expense;
use App\Models\ExpenseHead;
use App\Models\BankTransfar;
use App\Models\Banking;
use Brian2694\Toastr\Facades\Toastr;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Maatwebsite\Excel\Facades\Excel;
use Illuminate\Support\Facades\Storage;

class BandPurchaseController extends Controller
{

    public function index()
    {
        $data = [
            'list' => BandPurchase::get()
        ];

        return view('bandPurchase.index', $data);
    }

    public function create()
    {
        $data = [
            'provider' => BandProvider::all(),
            'start' => Carbon::now()->startOfMonth(),
            'end' => today()
        ];

        return view('bandPurchase.create', $data);
    }

    public function productinfo(Request $request)
    {
        $product = BandService::where('id', $request->data)->first();
        return $product;
    }

    public function productDetails(Request $request)
    {
        $name = $request->data;
        $product = BandService::where('name', 'like', "%{$name}%")->get();

        return $product;
    }

    public function store(Request $request)
    {

        if (!isset($request->service_id)) {
            Toastr::error('Please add at least one service item', '', ["progressBar" => true]);
            return back();
        }


        DB::beginTransaction();
        try {

            $paid = 0;

            if ($request->paidAmount > $request->totalPrice) {
                $paid = $request->totalPrice;
            } else {
                $paid = $request->paidAmount;
            }

            $purchase = new BandPurchase();
            $purchase->provider_id = $request->provider_id;
            $purchase->invoice_no = $request->invoice_no;
            $purchase->billing_date = Carbon::parse($request->billing_date)->format('Y-m-d');
            $purchase->total_price = $request->totalPrice;
            $purchase->paid = $paid;
            $purchase->bank_account_id = !empty($request->bank_account_id) ? $request->bank_account_id : null;

            if ($request->document != null) {
                // save file to s3 or local storage
                if (checkSettings('store_image_to_s3') === 'enable') {
                    $fileName = strtolower(trim(time() . '.' . $request->document->extension()));
                    $path = 'bandPurchase/' . $fileName;

                    $request->document->storeAs('bandPurchase', $fileName, 's3');
                    Storage::disk('s3')->setVisibility($path, 'public');
                    $purchase->document  = Storage::disk('s3')->url($path);
                } else {
                    // save file to local storage
                    $fileName = time() . '.' . $request->document->extension();
                    $request->document->move(storage_path('app/public/bandPurchase'), $fileName);
                    $purchase->document = $fileName;
                }
            }

            $purchase->save();


            $len = sizeof($request->service_id);
            for ($i = 0; $i < $len; $i++) {
                $purchaseItem = new BandPurchaseItem();
                $purchaseItem->bandPurchaseId = $purchase->id;
                $purchaseItem->service_id = $request->service_id[$i];
                $purchaseItem->quantity = $request->quantity[$i];
                $purchaseItem->rate = $request->rate[$i];
                $purchaseItem->vat = $request->vat[$i];
                $purchaseItem->from_date = Carbon::parse($request->from_date[$i]);
                $purchaseItem->to_date = Carbon::parse($request->to_date[$i]);
                // $purchaseItem->status = $request->status[$i];
                $purchaseItem->line_total = $request->lineTotal[$i];
                $purchaseItem->save();
            }

            $expense_head = ExpenseHead::where('name', "BandWith Buy")->first();
            if ($expense_head == null) {
                (new FixCommonIssueController)->addBandwidthBuyExpenseHeadInExpenseHeadTable();
                $expense_head = ExpenseHead::where('name', "BandWith Buy")->first();
            }

            $expense = new Expense();
            $note = "Bandwidth Buy added by " . auth()->user()->name;
            $expense->name = "Bandwidth Buy";
            $expense->invoice_number = $request->invoice_no;
            $expense->date = Carbon::parse(now());
            $expense->amount = $request->totalPrice;
            $expense->description =  $note;
            $expense->expenseHead = $expense_head->id;
            $expense->created_by = auth()->user()->id;
            $expense->band_with_buy_id = $purchase->id;
            $expense->status = "approved";


            $expense->save();

            // Check if bank account is selected and withdraw amount
            if ($request->filled('bank_account_id') && !empty($request->bank_account_id)) {
                // Check bank balance before withdrawal
                $banking = Banking::find($request->bank_account_id);
                if ($banking) {
                    $total_deposit = BankTransfar::where('account_id', $request->bank_account_id)->sum('diposit_amount');
                    $total_withdrawal = BankTransfar::where('account_id', $request->bank_account_id)->sum('withdraw_amount');
                    $balance = $banking->opening_balance + $total_deposit - $total_withdrawal;

                    if ($request->totalPrice > $balance) {
                        DB::rollBack();
                        Toastr::error('Withdraw Amount is greater than Bank Balance', 'Error');
                        return redirect()->back()->withInput();
                    }

                    // Withdraw from bank account
                    $bankWithdrawal = new BankTransfar();
                    $bankWithdrawal->account_id = $request->bank_account_id;
                    $bankWithdrawal->withdraw_amount = $request->totalPrice;
                    $bankWithdrawal->description = 'Band Purchase [ID:' . $purchase->id . ']: Invoice ' . $request->invoice_no . ' - ' . $note;
                    $bankWithdrawal->by = auth()->user()->name ?? 'System';
                    $bankWithdrawal->save();
                }
            }

            DB::commit();
            Toastr::success('Purchase Added Successfully', '', ["progressBar" => true]);
            return back();
        } catch (\Exception $ex) {
            dd($ex);
            DB::rollback();
            Toastr::error('Some Problem Happen', '', ["progressBar" => true]);
            return back();
        }
    }

    public function show($id)
    {
        //
    }

    public function edit($id)
    {
        $data = [
            'purchase' => BandPurchase::with('purchaseItem.service')->find($id),
            'provider' => BandProvider::all(),
            'start' => Carbon::now()->startOfMonth(),
            'end' => today()
        ];

        return view('bandPurchase.edit', $data);
    }

    public function update(Request $request, $id)
    {
        if (!isset($request->service_id)) {
            Toastr::error('Please add at least one service item', '', ["progressBar" => true]);
            return back();
        }
        $purchaseId = BandPurchase::find($id);
        $this->validate($request, [
            'invoice_no' => 'unique:band_purchases,invoice_no,' . $purchaseId->id,
        ]);



        DB::beginTransaction();
        try {

            $paid = 0;

            if ($request->paidAmount > $request->totalPrice) {
                $paid = $request->totalPrice;
            } else {
                $paid = $request->paidAmount;
            }

            $purchase = BandPurchase::find($id);
            $purchase->provider_id = $request->provider_id;
            $purchase->invoice_no = $request->invoice_no;
            $purchase->billing_date = Carbon::parse($request->billing_date)->format('Y-m-d');
            $purchase->total_price = $request->totalPrice;
            $purchase->paid = $paid;
            $purchase->bank_account_id = !empty($request->bank_account_id) ? $request->bank_account_id : null;

            if ($request->document != null) {
                // save file to s3 or local storage
                if (checkSettings('store_image_to_s3') === 'enable') {
                    $fileName = strtolower(trim(time() . '.' . $request->document->extension()));
                    $path = 'bandPurchase/' . $fileName;

                    $request->document->storeAs('bandPurchase', $fileName, 's3');
                    Storage::disk('s3')->setVisibility($path, 'public');
                    $purchase->document  = Storage::disk('s3')->url($path);
                } else {
                    $fileName = time() . '.' . $request->document->extension();
                    $request->document->move(storage_path('app/public/bandPurchase'), $fileName);
                    $purchase->document = $fileName;
                }
            }

            $purchase->save();

            BandPurchaseItem::where('bandPurchaseId', $id)->delete();


            $len = sizeof($request->service_id);
            for ($i = 0; $i < $len; $i++) {
                $purchaseItem = new BandPurchaseItem();
                $purchaseItem->bandPurchaseId = $purchase->id;
                $purchaseItem->service_id = $request->service_id[$i];
                $purchaseItem->quantity = $request->quantity[$i];
                $purchaseItem->rate = $request->rate[$i];
                $purchaseItem->vat = $request->vat[$i];
                $purchaseItem->from_date = Carbon::parse($request->from_date[$i]);
                $purchaseItem->to_date = Carbon::parse($request->to_date[$i]);
                // $purchaseItem->status = $request->status[$i];
                $purchaseItem->line_total = $request->lineTotal[$i];
                $purchaseItem->save();
            }

            $expense = Expense::where('band_with_buy_id', $id)->first();

            if ($expense) {
                $expense->invoice_number = $request->invoice_no;
                $expense->amount = $request->totalPrice;
                $expense->created_by = auth()->user()->id;
                $expense->bank_account_id = !empty($request->bank_account_id) ? $request->bank_account_id : null;
                $expense->save();
            }

            // Handle bank withdrawal update
            // Find existing bank withdrawal for this purchase
            $existingWithdrawal = BankTransfar::where('description', 'like', '%Band Purchase [ID:' . $purchase->id . ']%')
                ->whereNotNull('withdraw_amount')
                ->first();

            // Check if bank account is selected
            if ($request->filled('bank_account_id') && !empty($request->bank_account_id)) {
                // Check bank balance before withdrawal
                $banking = Banking::find($request->bank_account_id);
                if ($banking) {
                    $total_deposit = BankTransfar::where('account_id', $request->bank_account_id)->sum('diposit_amount');
                    $total_withdrawal = BankTransfar::where('account_id', $request->bank_account_id)->sum('withdraw_amount');

                    // If updating existing withdrawal on the same account, exclude it from balance calculation
                    if ($existingWithdrawal && $existingWithdrawal->account_id == $request->bank_account_id) {
                        $total_withdrawal -= $existingWithdrawal->withdraw_amount;
                    }

                    $balance = $banking->opening_balance + $total_deposit - $total_withdrawal;

                    if ($request->totalPrice > $balance) {
                        DB::rollBack();
                        Toastr::error('Withdraw Amount is greater than Bank Balance', 'Error');
                        return redirect()->back()->withInput();
                    }

                    // If existing withdrawal is on a different account, delete it first
                    if ($existingWithdrawal && $existingWithdrawal->account_id != $request->bank_account_id) {
                        $existingWithdrawal->delete();
                        $existingWithdrawal = null; // Reset to create new one
                    }

                    // Update or create withdrawal
                    if ($existingWithdrawal) {
                        // Update existing withdrawal
                        $existingWithdrawal->account_id = $request->bank_account_id;
                        $existingWithdrawal->withdraw_amount = $request->totalPrice;
                        $existingWithdrawal->description = 'Band Purchase [ID:' . $purchase->id . ']: Invoice ' . $request->invoice_no . ' - Bandwidth Buy added by ' . auth()->user()->name;
                        $existingWithdrawal->by = auth()->user()->name ?? 'System';
                        $existingWithdrawal->save();
                    } else {
                        // Create new withdrawal
                        $bankWithdrawal = new BankTransfar();
                        $bankWithdrawal->account_id = $request->bank_account_id;
                        $bankWithdrawal->withdraw_amount = $request->totalPrice;
                        $bankWithdrawal->description = 'Band Purchase [ID:' . $purchase->id . ']: Invoice ' . $request->invoice_no . ' - Bandwidth Buy added by ' . auth()->user()->name;
                        $bankWithdrawal->by = auth()->user()->name ?? 'System';
                        $bankWithdrawal->save();
                    }
                }
            } else {
                // If bank account is not selected but withdrawal exists, delete it
                if ($existingWithdrawal) {
                    $existingWithdrawal->delete();
                }
            }

            DB::commit();
            Toastr::success('Purchase Updated Successfully', '', ["progressBar" => true]);
            return redirect()->back();
        } catch (\Exception $ex) {
            DB::rollback();
            Toastr::error('Some Problem Happen', '', ["progressBar" => true]);
            dd($ex);
            return back();
        }
    }

    public function destroy($id)
    {
        //
    }

    public function makePayment(Request $request)
    {
        // dd($request->all());

        $purchase = BandPurchase::find($request->purchaseId);
        $purchase->subTotal = $request->subTotal;
        $purchase->marketing_total = $request->paid + $request->newPaid;
        $purchase->total = $request->due;
        $purchase->update();

        Toastr::success('Paid Successfully', '', ["progressBar" => true]);
        return redirect(route('band-purchase.index'));
    }

    public function invoice($id)
    {
        $data = [
            'invoice' => BandPurchase::with('purchaseItem.service', 'provider')->find($id),
        ];

        // dd($data['invoice']);

        return view('bandPurchase.invoice', $data);
    }

    public function bandwidthReport()
    {
        $start = today()->firstOfMonth();
        $end = today();

        return view('bandPurchase.search', [
            'page_title' => 'Bandwidth Report',
            'start'      => $start,
            'end'        => $end,
            'services'   => BandService::all(),
            'providers'  => BandProvider::all(),
        ]);
    }

    public function bandwidthSearch(Request $request)
    {
        if ($request->ajax()) {

            $from = $request->from_date == '' ? today() : Carbon::parse($request->from_date);
            $to   = $request->to_date == '' ? today() : Carbon::parse($request->to_date);

            $from = Carbon::parse($from)->format('Y-m-d 00:00:00');
            $to   = Carbon::parse($to)->format('Y-m-d 23:59:59');
            $list = BandPurchase::with('purchaseItem')->whereBetween('billing_date', [$from, $to]);

            if ($request->provider != null) {
                $list->where('provider_id', $request->provider);
            }

            if ($request->service != null) {
                $list->whereHas('purchaseItem', function ($query) use ($request) {
                    $query->where('service_id', $request->service);
                });
            }

            return view('bandPurchase.result', [
                'list'       =>  $list->get()
            ]);
        }
    }

    public function checkInvoiceNo(Request $request)
    {
        if (request()->ajax()) {
            $inv_no = $request->inv;
            if (!checkAPI()) {
                if (preg_match('/[\'^£$%*()}{~?><>,|=+¬]/', $inv_no)) {
                    return false;
                }
                // if (preg_match('/^\S.*\s.*\S$/', $inv_no)) {
                //     return false;
                // }
            }
            $result = BandPurchase::where('invoice_no', $inv_no)->first();

            if (empty($result)) {
                return true;
            } else {
                return false;
            }
        }
    }

    public function bandwidthBuyExport(Request $request)
    {
        $from = $request->from_date == '' ? today() : Carbon::parse($request->from_date);
        $to   = $request->to_date == '' ? today() : Carbon::parse($request->to_date);

        $from = Carbon::parse($from)->format('Y-m-d 00:00:00');
        $to   = Carbon::parse($to)->format('Y-m-d 23:59:59');

        $query = BandPurchase::with(['purchaseItem.service', 'provider'])
            ->whereBetween('billing_date', [$from, $to]);

        if ($request->provider) {
            $query->where('provider_id', $request->provider);
        }

        if ($request->service) {
            $query->whereHas('purchaseItem', function ($q) use ($request) {
                $q->where('service_id', $request->service);
            });
        }

        $data = $query->get();

        return Excel::download(new BandPurchaseExport($data), 'bandwidth_buy_report_' . date('d_m_Y') . '.xlsx');
    }
}
