<?php

namespace App\Http\Controllers\Backend\Sale;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\Accounts;
use App\Models\AccountTransaction;
use App\Models\Sale;
use App\Models\Category;
use App\Models\Customer;
use App\Models\Branch;
use App\Models\Adjust;
use App\Models\Product;
use App\Models\ChartOfAccount;
use App\Models\StockSummary;
use App\Models\Company;
use App\Models\CustomerGroup;
use App\Models\customerLedger;
use App\Models\Fabric;
use App\Models\PurchasesDetails;
use App\Models\ReturnDeposit;
use App\Models\sales_Details;
use App\Models\Transection;
use App\Services\Sale\SwingSalesService;
use App\Transformers\SalesTransformer;
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\ValidationException;

class SwingSaleController extends Controller
{

    /**
     * @var SwingSalesService
     */
    private $systemService;

    /**
     * @var SalesTransformer
     */
    private $systemTransformer;

    /**
     * SaleController constructor.
     * @param SwingSalesService $systemService
     * @param SwingSalesService $systemTransformer
     */
    public function __construct(SwingSalesService $saleService, SalesTransformer $saleTransformer)
    {
        $this->systemService = $saleService;
        $this->systemTransformer = $saleTransformer;
    }

    /**
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
     */
    public function index(Request $request)
    {
        $title = 'Swing Sale List';
        return view('backend.pages.swing_sale.index', get_defined_vars());
    }

    public function dataProcessingSale(Request $request)
    {
        $json_data = $this->systemService->getList($request);
        return json_encode($this->systemTransformer->dataTable($json_data));
    }


    public function quiceAddCustomer(Request $request)
    {
         $request->validate([
        'phone' => 'required|unique:customers,phone',
        'name' => 'required',
       
    ], [
        'phone.unique' => 'This phone number is already in use.',
        'phone.required' => 'Phone number is required.',
        'name.required' => 'Name is required.',
        
    ]);
        $customertLastData = Customer::latest('id')->first();
        if ($customertLastData) :
            $customerData = $customertLastData->id + 1;
        else :
            $customerData = 1;
        endif;
        $customerCode = 'CU' . str_pad($customerData, 5, "0", STR_PAD_LEFT);

        $customer = new Customer();
        $customer->customergroup_id = $request->customergroup_id;
        $customer->name = $request->name;
        $customer->email = $request->email ?? "";
        $customer->phone = $request->phone;
        $customer->address = $request->address ?? "";
        $customer->bin = $request->bin;
         $customer->branch_id = $request->branch_id ?? "";
        $customer->co_name = $request->co_name ?? "";
        $customer->customerCode = $customerCode;
        $customer->status = 'Active';
        $customer->created_by = Auth::user()->id;
        $customer->save();

        $Accounts = new Accounts();
        $Accounts->account_name = "$request->name";
        $Accounts->parent_id = 5;
         $Accounts->branch_id = $request->branch_id;
        $Accounts->accountable_id = $customer->id;
        $Accounts->accountable_type = "App\Models\Customer";
        $Accounts->bill_by_bill = 1;
        $Accounts->status = 'Active';
        $Accounts->created_by = Auth::user()->id;
        $Accounts->save();

        return response()->json([
            'success' => true,
            'accounts' => $Accounts,
        ]);
    }

    /**
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
     */
    public function create()
    {
        $title = 'Add New sale';
        $category_info = Category::get()->where('status', 'Active');
        $customer = Customer::get()->where('status', 'Active');
        // $ledgers = ChartOfAccount::whereIn('id', [getAccountByUniqueID(5)->id])->get();
          $auth = Auth::user();
       $userRole = $auth->role_id;
         if ($userRole > 1) {
        $ledgers = ChartOfAccount::whereIn('parent_id', [5])->where('branch_id',$auth->branch_id)->get();
         }else{
            $ledgers = ChartOfAccount::whereIn('parent_id', [5])->get();
         }

        $accounts = ChartOfAccount::whereIn('id', [getAccountByUniqueID(6)->id])->get();
        // $branch = Branch::get()->where('status', 'Active');
        $user = auth()->user();
        $branch = Branch::where("parent_id", 0)->where('status', 'Active');
               $products = Product::where('branch_id',1)->get();
        $fabricType = Fabric::pluck('name', 'id')->toArray();

        if ($user->branch_id) {
            $branch = $branch->where('id', $user->branch_id);
        }
        $branch = $branch->get();
        $customerGroup = CustomerGroup::all();

        $wearhouses = Branch::where("parent_id", "!=", 0)->where('status', 'Active')->get();

        if ($user->type == "Admin" || $user->branch_id) {
            $account = ChartOfAccount::whereIn('id', [16, 17])->get()->where('status', 'Active');
        } elseif ($user->type == "Admin" || !$user->branch_id) {
            $account = ChartOfAccount::whereIn('id', [16, 17])->get()->where('status', 'Active')->where('branch_id', $user->branch_id);
        }

        $saleLastData = Sale::latest('id')->first();
        if ($saleLastData) :
            $saleData = $saleLastData->id + 1;
        else :
            $saleData = 1;
        endif;

        $invoice_no = 'SV' . str_pad($saleData, 5, "0", STR_PAD_LEFT);
        return view('backend.pages.swing_sale.create', get_defined_vars(), compact('fabricType'));
    }

    public function show(Request $request, $id)
    {
        $title = 'Sale Invoice';

        $invoice = Sale::with(['details.product.category', 'branch', 'customer','account'])->findOrFail($id);
        
        $companyInfo = Company::latest('id')->first();
        return view('backend.pages.swing_sale.invoice', get_defined_vars());
    }

    public function challan(Request $request, $id)
    {
        $title = 'Delivery Chalans Invoice';

        $invoice = Sale::with(['details.product.category', 'branch', 'customer'])->findOrFail($id);
        $companyInfo = Company::latest('id')->first();
        return view('backend.pages.swing_sale.chalans', get_defined_vars());
    }

    public function unitPrice(Request $request)
    {
        $proid = $request->productId;
        $productPrice = Product::get()->where('id', $proid)->first();
        $lastPurchasePrice = PurchasesDetails::where('product_id', $proid)->latest('id')->pluck('unit_price')->first();
        return response()->json(["sale_price" => $productPrice->sale_price ?? 0, 'lastPurchasePrice' => $lastPurchasePrice ?? 0]);
    }
    /**
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function store(Request $request)
    {
        // dd($request->all());
        try {
            $this->validate($request, $this->systemService->storeValidation($request));
        } catch (ValidationException $e) {
            session()->flash('error', 'Validation error !!');
            return redirect()->back()->withErrors($e->errors())->withInput();
        }
        $this->systemService->store($request);
        session()->flash('success', 'Data successfully save!!');
        return redirect()->route('sale.swing.index');
    }

    /**
     * @param $slug
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
     */
    public function edit($id)
    {
        if (!is_numeric($id)) {
            session()->flash('error', 'Edit id must be numeric!!');
            return redirect()->back();
        }
        $editInfo = $this->systemService->details($id);
        $transection = Transection::where('type', 10)->orWhere('payment_id', $id)->first();
        if (!$editInfo) {
            session()->flash('error', 'Edit info is invalid!!');
            return redirect()->back();
        }
        $title = 'Add New Sale';
        // $ledgers = ChartOfAccount::whereIn('id', [getAccountByUniqueID(5)->id, getAccountByUniqueID(16)->id])->get();
    //     $ledgers = ChartOfAccount::where('branch_id', 1)
    // ->where('status', 'Active')
    // ->get();

       $auth = Auth::user();
       $userRole = $auth->role_id;
         if ($userRole > 1) {
        $ledgers = ChartOfAccount::whereIn('parent_id', [5])->where('branch_id',$auth->branch_id)->get();
         }else{
            $ledgers = ChartOfAccount::whereIn('parent_id', [5])->get();
         }


        $category_info = Category::get()->where('status', 'Active');
        $customer = Customer::get()->where('status', 'Active');
        $user = auth()->user();
        $customerGroup = CustomerGroup::all();
        $fabricType = Fabric::pluck('name', 'id')->toArray();
         $products = Product::where('branch_id',1)->get();
        $branch = Branch::where("parent_id", 0)->where('status', 'Active');
        if ($user->branch_id) {
            $branch = $branch->where('id', $user->branch_id);
        }
        $branch = $branch->get();
        $accounts = ChartOfAccount::whereIn('id', [getAccountByUniqueID(6)->id])->get();

        if ($user->type == "Admin" || !$user->branch_id) {
            $account = ChartOfAccount::get()->where('status', 'Active');
        } elseif ($user->type == "Admin" || $user->branch_id) {
            $account = ChartOfAccount::get()->where('status', 'Active')->where('branch_id', $user->branch_id);
        }
        $saletlist = Sale::findOrFail($id);
        $subWarehouses = Branch::where("parent_id", "!=", 0)->where('status', 'Active')->get();
        $saledetails = sales_Details::where('sale_id', $id)->get();
        return view('backend.pages.swing_sale.edit', get_defined_vars());
    }

    /**
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function update(Request $request, $id)
    {
        if (!is_numeric($id)) {
            session()->flash('error', 'Edit id must be numeric!!');
            return redirect()->back();
        }
        $editInfo = $this->systemService->details($id);
        if (!$editInfo) {
            session()->flash('error', 'Edit info is invalid!!');
            return redirect()->back();
        }
        try {
            $this->validate($request, $this->systemService->updateValidation($request, $id));
        } catch (ValidationException $e) {
            session()->flash('error', 'Validation error !!');
            return redirect()->back()->withErrors($e->errors())->withInput();
        }
        $this->systemService->update($request, $id);
        session()->flash('success', 'Data successfully updated!!');
        return redirect()->route('sale.swing.index');
    }

    /**
     * @param $slug
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
     */
    public function statusUpdate($id, $status)
    {
        if (!is_numeric($id)) {
            return response()->json($this->systemTransformer->invalidId($id), 200);
        }
        $detailsInfo = $this->systemService->details($id);
        if (!$detailsInfo) {
            return response()->json($this->systemTransformer->notFound($detailsInfo), 200);
        }
        $statusInfo = $this->systemService->statusUpdate($id, $status);
        if ($statusInfo) {
            return response()->json($this->systemTransformer->statusUpdate($statusInfo), 200);
        }
    }

    /**
     * @param $slug
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
     */
    public function destroy($id)
    {
        if (!is_numeric($id)) {
            return response()->json($this->systemTransformer->invalidId($id), 200);
        }
        $detailsInfo = $this->systemService->details($id);
        if (!$detailsInfo) {
            return response()->json($this->systemTransformer->notFound($detailsInfo), 200);
        }
        $deleteInfo = $this->systemService->destroy($id);
        if ($deleteInfo) {
            return response()->json($this->systemTransformer->delete($deleteInfo), 200);
        }
    }

    public function getProductListForSale(Request $request)
    {
        // dd($request->all());
        $cat_id = $request->cat_id;
        $productList = Product::get()->where('category_id', $cat_id);
        $add = '';
        if (!empty($productList)) :
            $add .= "<option value=''>Select Product</option>";

            foreach ($productList as $key => $value) :
                // $stocksummerylst = StockSummary::where('branch_id', $request->branch_id)->where('product_id', $value->id)->first();
                $add .= '<option proName="' . $value->name . '"   value="' . $value->id . '">' . $value->name . '</option>';
                if (!$value->subproduct->isEmpty()) {
                    foreach ($value->subproduct as $key => $itel) :
                        $add .= '<option proName="' . $itel->name . '"   value="' . $itel->id . '">- ' . $itel->name . '</option>';
                    endforeach;
                }
            endforeach;
            echo $add;
            die;
        else :
            echo "<option value='' selected disabled>No Product Available</option>";
            die;
        endif;
    }

    public function getCustomerBalance(Request $request)
    {

        $finalValue = 0;
        $conditionalArray = array(
            'customer_id' => $request->customer_id,
            'payment_type' => $request->payment_type,
        );

        $debit = Adjust::where($conditionalArray)->sum('debit');
        $credit = Adjust::where($conditionalArray)->sum('credit');
        $return = ReturnDeposit::where('customer_id', $request->customer_id)->sum('amount');
        $customerlager = customerLedger::where($conditionalArray)->sum('credit');

        $adjustArray = array(
            'customer_id' => $request->customer_id,
            'payment_type' => $request->payment_type,
        );

        $expireData = Adjust::where($adjustArray)->orderBy('id', 'desc')->first();
        $finalValue = ($debit - $credit - $return) - $customerlager;
        echo json_encode(array('finalBalance' => $finalValue, 'expireData' => $expireData->expire_date ?? 0));
    }

    public function unitPiceForSale(Request $request)
    {
        $proid = $request->productId;
        $productPrice = Product::get()->where('id', $proid)->first();
        echo json_encode(array('purchases_price' => $productPrice->purchases_price, 'sale_price' => $productPrice->sale_price));
    }

    function getProductStock(Request $request)
    {
        $product_id = $request->productId;
        $productStock = StockSummary::get()->where('product_id', $product_id)->whereIn('branch_id', [$request->sub_branch_id])->where('type', 'Branch')->where('purchasetype', $request->type)->first();
        // dd($request->branch_id,$request->sub_branch_id,$product_id,$request->type);
        if (!empty($productStock->quantity) && $productStock->quantity > 0) :
            echo $productStock->quantity;
        endif;
    }

    function olddueamount(Request $request)
    {
        $title = 'Ledger Report';

        $accounts = ChartOfAccount::where("parent_id", 0)->get();
        $companyInfo = Company::latest('id')->first();

        $selectedAccountId = $request->input('account_id');
        $startDate = $request->input('start_date') ?? now();
        $endDate = $request->input('end_date') ?? now();

        $ledgerEntries = [];
        $openingBalance = 0;
        $runningBalance = 0;
        $account = null;
        if ($selectedAccountId) {
            $account = ChartOfAccount::findOrFail($selectedAccountId);

            // Calculate the opening balance as of the start date
            $debitSumBeforeStartDate = AccountTransaction::where('account_id', $selectedAccountId)
                ->whereDate('created_at', '<', $startDate)
                ->sum('debit');

            $creditSumBeforeStartDate = AccountTransaction::where('account_id', $selectedAccountId)
                ->whereDate('created_at', '<', $startDate)
                ->sum('credit');

            // Adjust opening balance based on the balance type
            if ($account->balance_type === 'debit') {
                $openingBalance = $account->opening_balance + $debitSumBeforeStartDate - $creditSumBeforeStartDate;
            } else {
                $openingBalance = $account->opening_balance + $debitSumBeforeStartDate - $creditSumBeforeStartDate;
            }

            $runningBalance = $openingBalance;

            $transactions = AccountTransaction::where('account_id', $selectedAccountId)
                ->when($startDate, function ($query) use ($startDate) {
                    return $query->whereDate('created_at', '>=', $startDate);
                })
                ->when($endDate, function ($query) use ($endDate) {
                    return $query->whereDate('created_at', '<=', $endDate);
                })
                ->orderBy('created_at')
                ->get();

            foreach ($transactions as $transaction) {
                $relatedAccountTransaction = AccountTransaction::where('invoice', $transaction->invoice)
                    ->where('account_id', '!=', $selectedAccountId);
                if ($transaction->debit) {
                    $relatedAccountTransaction = $relatedAccountTransaction->whereNotNull('credit');
                }
                if ($transaction->credit) {
                    $relatedAccountTransaction = $relatedAccountTransaction->whereNotNull('debit');
                }
                $relatedAccountTransaction = $relatedAccountTransaction->first();

                $debit = $transaction->debit ?? 0;
                $credit = $transaction->credit ?? 0;

                if ($account->balance_type == "debit") {
                    $runningBalance += $debit - $credit;
                } else {
                    $runningBalance += $credit -  $debit;
                }

                $ledgerEntries[] = [
                    'date' => $transaction->created_at,
                    'invoice' => $transaction->invoice,
                    'description' => $transaction->remark,
                    'debit' => $debit,
                    'credit' => $credit,
                    'balance' => $runningBalance,
                    'account_name' => (($relatedAccountTransaction->account->account_name ?? '') . " " . ($relatedAccountTransaction->account->bank_name ?? "") . '' . ($relatedAccountTransaction->account->account_code ?? ""))
                ];
            }
        }
        return $runningBalance ?? 0;
    }
}
