<?php

namespace App\Http\Controllers;

use App\Helpers\PointHelper;
use Illuminate\Http\Request;
use App\Models\Stocktransaction;
use App\Models\Substocktransaction;
use App\Models\Product;
use App\Models\Akun;
use App\Models\Cashtransaction;
use App\Models\Credit;
use App\Models\Contact;
use App\Models\ContactPoint;
use App\Models\Language;
use App\Models\LicencesCompanyType;
use App\Models\MultiUnit;
use App\Models\PointTransaction;
use App\Models\Subcashtransaction;
use App\Models\TaxSettingMain;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Validation\ValidationException;

use function PHPSTORM_META\map;

class StockController extends Controller
{
    public function checkTransactionsExist()
    {
        $hasStock = Stocktransaction::query()->exists();
        $hasCash = Cashtransaction::query()->exists();
        $hasData = $hasStock || $hasCash;
        return response([
            'success' => true,
            'has_data' => $hasData,
        ], 200);
    }

    public function getStockOutReport(Request $request)
    {
        $start_date = $request->start_date ? date('Y-m-d', strtotime($request->start_date)) : date('Y-m-01');
        $end_date = $request->end_date ? date('Y-m-d', strtotime($request->end_date)) : date('Y-m-d');

        $data = Product::with('producttype', 'unit')
            ->whereHas('substocktransaction', function ($sub) use ($start_date, $end_date, $request) {
                $sub->whereHas('stocktransaction', function ($stock) use ($start_date, $end_date, $request) {
                    $stock->whereNotNull('cashin_id')
                        ->whereNull('pending')
                        ->whereNull('nonmoney')
                        ->whereNull('return')
                        ->whereBetween('date', [$start_date, $end_date]);

                    // Tambahkan filter untuk staff_name jika ada
                    if (!empty($request->staff_name)) {
                        $stock->where('staff', $request->staff_name);
                    }
                });
            })
            ->withSum(['substocktransaction' => function ($sub) use ($start_date, $end_date, $request) {
                $sub->whereHas('stocktransaction', function ($stock) use ($start_date, $end_date, $request) {
                    $stock->whereNotNull('cashin_id')
                        ->whereNull('pending')
                        ->whereNull('nonmoney')
                        ->whereNull('return')
                        ->whereBetween('date', [$start_date, $end_date]);

                    // Tambahkan filter untuk staff_name jika ada
                    if (!empty($request->staff_name)) {
                        $stock->where('staff', $request->staff_name);
                    }
                });
            }], 'qty')
            ->withSum(['substocktransaction' => function ($sub) use ($start_date, $end_date, $request) {
                $sub->whereHas('stocktransaction', function ($stock) use ($start_date, $end_date, $request) {
                    $stock->whereNotNull('cashin_id')
                        ->whereNull('pending')
                        ->whereNull('nonmoney')
                        ->whereNull('return')
                        ->whereBetween('date', [$start_date, $end_date]);

                    // Tambahkan filter untuk staff_name jika ada
                    if (!empty($request->staff_name)) {
                        $stock->where('staff', $request->staff_name);
                    }
                });
            }], 'total')
            ->with(['substocktransaction' => function ($sub) use ($start_date, $end_date, $request) {
                $sub->whereHas('stocktransaction', function ($stock) use ($start_date, $end_date, $request) {
                    $stock->whereNotNull('cashin_id')
                        ->whereNull('pending')
                        ->whereNull('nonmoney')
                        ->whereNull('return')
                        ->whereBetween('date', [$start_date, $end_date]);

                    // Tambahkan filter untuk staff_name jika ada
                    if (!empty($request->staff_name)) {
                        $stock->where('staff', $request->staff_name);
                    }
                })
                    ->with('stocktransaction.substocktransaction');
            }])
            ->get()
            ->map(function ($product) {
                try {
                    $totalDiscount = $product->substocktransaction->sum(function ($sub) {
                        $discount = (float) ($sub->stocktransaction->discount ?? 0);
                        if ($discount <= 0) {
                            return 0;
                        }
                        $transactionTotal = (float) ($sub->stocktransaction->substocktransaction?->sum('total') ?? 0);
                        if ($transactionTotal <= 0) {
                            return 0;
                        }
                        $lineTotal = (float) ($sub->total ?? 0);
                        return $discount * ($lineTotal / $transactionTotal);
                    });

                    // Hitung total qty_retur
                    $sumQtyRetur = $product->substocktransaction->sum(function ($sub) {
                        return $sub->qty_retur ?? 0;
                    });

                    // Hitung total dari qty_retur * selling_price_unit
                    $totalQtyRetur = $product->substocktransaction->sum(function ($sub) {
                        $qty = $sub->qty_retur ?? 0;
                        $price = $sub->selling_price_unit ?? 0;
                        return $qty * $price;
                    });

                    // Tambahkan semua field baru ke product
                    $product->total_discount = $totalDiscount;
                    $product->sum_qty_retur = $sumQtyRetur;
                    $product->total_qty_retur = $totalQtyRetur;
                } catch (\Throwable $e) {
                    Log::error('Error menghitung field tambahan untuk product ID ' . $product->id, [
                        'error' => $e->getMessage(),
                    ]);
                    // Defaultkan nilai jika terjadi error
                    $product->total_discount = 0;
                    $product->sum_qty_retur = 0;
                    $product->total_qty_retur = 0;
                }

                return $product;
            });

        return response([
            'success' => true,
            'stocktransaction' => $data,
        ], 200);
    }

    public function getStockTransaction(Request $request)
    {
        $data = Stocktransaction::with('contact', 'cashin', 'cashout');

        if (!empty($request->start_date) && !empty($request->end_date)) {
            $start_date = date('Y-m-d', strtotime($request->start_date));
            $end_date = date('Y-m-d', strtotime($request->end_date));
            $data = $data->whereBetween('date', [$start_date, $end_date]);
        }
        // else{
        //     $data = $data->whereBetween('date',[date('Y-m-01',time()),date('Y-m-d',time())]);
        // }

        $data = $data->get();

        $response = [
            'success' => true,
            'stocktransaction' => $data,
        ];

        return response($response, 200);
    }

    public function getStockIn(Request $request)
    {
        $type = isset($request->type) ? $request->type : null;
        $data = Stocktransaction::whereNotNull('cashout_id')->whereNull('pending')->whereNull('nonmoney')->whereNull('return');

        if (!empty($request->start_date) && !empty($request->end_date)) {
            $start_date = date('Y-m-d', strtotime($request->start_date));
            $end_date = date('Y-m-d', strtotime($request->end_date));
            $data = $data->whereBetween('date', [$start_date, $end_date]);
        }
        if (isset($request->contact_id)) {
            $data = $data->where('contact_id', $request->contact_id);
        }

        $data = $data->with('contact', 'cashout', 'substocktransaction.product.unit', 'substocktransaction.multi_unit')->orderBy('created_at', 'DESC')->get();
        foreach ($data as $key => $value) {
            $day = date('Y-m-d', time());
            if ($value->payment_due > $day) {
                $value['due_date'] = Carbon::create($value->payment_due)->diffForHumans(null, true) . " lagi";
            } else {
                $value['due_date'] = Carbon::create($value->payment_due)->diffForHumans(null, true) . " yang lalu";
            }
        }

        $response = [
            'success' => true,
            'stocktransaction' => $data,

        ];

        return response($response, 200);
    }

    public function getStockOut(Request $request)
    {
        $type = isset($request->type) ? $request->type : null;
        $data = Stocktransaction::whereNotNull('cashin_id')->whereNull('pending')->whereNull('nonmoney')->whereNull('return');
        if (!empty($request->start_date) && !empty($request->end_date)) {
            $start_date = date('Y-m-d', strtotime($request->start_date));
            $end_date = date('Y-m-d', strtotime($request->end_date));
            $data = $data->whereBetween('date', [$start_date, $end_date]);
        }
        if (isset($request->contact_id)) {
            $data = $data->where('contact_id', $request->contact_id);
        }
        if (!empty($request->staff)) {
            $data = $data->where('staff', $request->staff);
        }

        $data = $data->with('contact', 'sales', 'cashin', 'credit', 'substocktransaction.product.unit', 'substocktransaction.multi_unit')->orderBy('created_at', 'DESC')->get();

        $response = [
            'success' => true,
            'stocktransaction' => $data,
        ];

        return response($response, 200);
    }

    public function getStockRetur(Request $request)
    {
        $contact = $request->contact_id ?? null;
        $model = $request->model === 'cashin' ? 'cashin_id' : 'cashout_id';

        $data = Stocktransaction::whereNotNull($model)
            ->whereNull('pending')
            ->whereNull('return')
            ->whereNull('beginning_balance')
            ->whereNull('nonmoney');

        if (!empty($request->start_date) && !empty($request->end_date)) {
            $start_date = date('Y-m-d', strtotime($request->start_date));
            $end_date = date('Y-m-d', strtotime($request->end_date));
            $data = $data->whereBetween('date', [$start_date, $end_date]);
        }

        if ($contact) {
            $data = $data->where('contact_id', $contact);
        }

        // Ambil data dengan relasi yang dibutuhkan
        $data = $data->with([
            'contact',
            'cashin',
            'credit',
            'substocktransaction.product.unit',
            'substocktransaction.multi_unit'
        ])->orderBy('created_at', 'DESC')->get();

        // Filter data seperti logika frontend: qty - qty_retur > 0
        $data = $data->filter(function ($transaction) {
            return $transaction->substocktransaction->some(function ($sub) {
                $qty = (float) $sub->qty;
                $qtyRetur = (float) ($sub->qty_retur ?? 0);
                return ($qty - $qtyRetur) > 0;
            });
        })->values();

        return response([
            'success' => true,
            'stocktransaction' => $data,
        ], 200);
    }

    public function getUniqContactRetur(Request $request)
    {
        $model = $request->model === 'cashin' ? 'cashin_id' : 'cashout_id';

        $data = Stocktransaction::selectRaw('MAX(id) as id, contact_id')
            ->whereNotNull($model)
            ->whereNull('pending')
            ->whereNull('return')
            ->whereNull('beginning_balance')
            ->whereNull('nonmoney')
            ->groupBy('contact_id')
            ->with('contact')
            ->get();

        $data = $data->filter(function ($transaction) {
            return $transaction->substocktransaction->some(function ($sub) {
                $qty = (float) $sub->qty;
                $qtyRetur = (float) ($sub->qty_retur ?? 0);
                return ($qty - $qtyRetur) > 0;
            });
        })->values();

        return response([
            'success' => true,
            'data' => $data,
        ], 200);
    }

    public function getStockInPage(Request $request)
    {
        $type = $request->type ?? null;
        $limit = $request->limit ?? 20;
        $search = $request->search ?? null;

        $data = Stocktransaction::whereNotNull('cashout_id')
            ->whereNull('pending')
            ->whereNull('nonmoney')
            ->whereNull('return');

        // Filter tanggal
        if (!empty($request->start_date) && !empty($request->end_date)) {
            $start_date = date('Y-m-d', strtotime($request->start_date));
            $end_date = date('Y-m-d', strtotime($request->end_date));
            $data = $data->whereBetween('date', [$start_date, $end_date]);
        }

        // 🔍 Filter pencarian
        if (!empty($search)) {
            $data = $data->where(function ($query) use ($search) {
                $query->where('description', 'like', "%$search%")
                    ->orWhere('id', 'like', "%$search%")
                    ->orWhereHas('contact', function ($q) use ($search) {
                        $q->where('name', 'like', "%$search%");
                    })
                    ->orWhereHas('substocktransaction.product', function ($q) use ($search) {
                        $q->where('name', 'like', "%$search%");
                    });
            });
        }

        $totalData = (clone $data)->count();

        $data = $data->with([
            'contact',
            'cashout',
            'credit.cashin',
            'credit.cashout',
            'substocktransaction.product.unit',
            'substocktransaction.multi_unit'
        ])
            ->orderBy('created_at', 'DESC')
            ->paginate($limit);

        // Tambahkan kolom 'due_date'
        foreach ($data as $item) {
            if (!empty($item->payment_due)) {
                $day = date('Y-m-d');
                $item->due_date = Carbon::create($item->payment_due)->diffForHumans(null, true) .
                    ($item->payment_due > $day ? ' lagi' : ' yang lalu');
            } else {
                $item->due_date = null;
            }
        }

        $customPagination = [
            'current_page' => $data->currentPage(),
            'data' => $data->items(),
            'from' => $data->firstItem(),
            'to' => $data->lastItem(),
            'per_page' => $data->perPage(),
            'total' => $data->total(),
            'last_page' => $data->lastPage(),
        ];

        return response([
            'success' => true,
            'stocktransaction' => $customPagination,
            'total' => $totalData,
        ], 200);
    }

    public function getStockOutPage(Request $request)
    {
        $type = $request->type ?? null;
        $limit = $request->limit ?? 20;
        $search = $request->search ?? null;

        $data = Stocktransaction::whereNotNull('cashin_id')
            ->whereNull('pending')
            ->whereNull('nonmoney')
            ->whereNull('return');

        // Filter tanggal
        if (!empty($request->start_date) && !empty($request->end_date)) {
            $start_date = date('Y-m-d', strtotime($request->start_date));
            $end_date = date('Y-m-d', strtotime($request->end_date));
            $data = $data->whereBetween('date', [$start_date, $end_date]);
        }

        // 🔍 Tambahkan filter search
        if (!empty($search)) {
            $data = $data->where(function ($query) use ($search) {
                $query->where('description', 'like', "%$search%")
                    ->orWhere('id', 'like', "%$search%")
                    ->orWhereHas('contact', function ($q) use ($search) {
                        $q->where('name', 'like', "%$search%");
                    })
                    ->orWhereHas('substocktransaction.product', function ($q) use ($search) {
                        $q->where('name', 'like', "%$search%");
                    });
            });
        }

        if ($request->isUnderpaid == 'true' || $request->isUnderpaid === true) {
            $data = $data->whereRaw('(COALESCE(total, 0) + COALESCE(total_ppn, 0) - COALESCE(paid, 0) - COALESCE(discount, 0) - COALESCE(pph21_amount, 0) - COALESCE(pph23_amount, 0) - COALESCE(pph22_amount, 0) - COALESCE(pph4_2_amount, 0) - COALESCE(return_credit, 0)) > 0');
        }

        $totalData = $data->count();

        $data = $data->with([
            'contact',
            'sales',
            'cashin',
            'credit.cashin',
            'credit.cashout',
            'substocktransaction.product.unit',
            'substocktransaction.multi_unit'
        ])
            ->orderBy('created_at', 'DESC')
            ->paginate($limit);

        $customPagination = [
            'current_page' => $data->currentPage(),
            'data' => $data->items(),
            'from' => $data->firstItem(),
            'to' => $data->lastItem(),
            'per_page' => $data->perPage(),
            'total' => $data->total(),
            'last_page' => $data->lastPage(),
        ];

        return response([
            'success' => true,
            'stocktransaction' => $customPagination,
            'total' => $totalData,
        ], 200);
    }

    public function getStockOutWidthSalesPerson(Request $request)
    {
        $data = Stocktransaction::whereNotNull('cashin_id')->whereNull('pending')->whereNull('nonmoney')->whereNull('return');
        if (!empty($request->start_date) && !empty($request->end_date)) {
            $start_date = date('Y-m-d', strtotime($request->start_date));
            $end_date = date('Y-m-d', strtotime($request->end_date));
            $data = $data->whereBetween('date', [$start_date, $end_date]);
        }

        $data = $data->with('contact', 'sales', 'cashin', 'credit', 'substocktransaction.product.unit', 'substocktransaction.multi_unit')->orderBy('created_at', 'DESC')->get();

        $response = [
            'success' => true,
            'stocktransaction' => $data,
        ];

        return response($response, 200);
    }

    private function loadAccountMapping($langCode = 'id')
    {
        $jsonPath = config_path("lang/{$langCode}/akun.json");

        // Fallback ke bahasa Indonesia jika file tidak ditemukan
        if (!file_exists($jsonPath)) {
            $jsonPath = config_path('lang/id/akun.json');
        }

        if (!file_exists($jsonPath)) {
            return [];
        }

        return json_decode(file_get_contents($jsonPath), true) ?? [];
    }

    private function translateAccountName($accountName, $companyType, $mappingData)
    {
        // Handle company-specific mappings first
        if ($companyType && isset($mappingData[$companyType][$accountName])) {
            return $mappingData[$companyType][$accountName];
        }

        // Handle general mappings
        if (isset($mappingData['akun_umum'][$accountName])) {
            return $mappingData['akun_umum'][$accountName];
        }

        return $accountName;
    }

    public function getStockTransactionDetail(Request $request)
    {
        // Load language settings
        $activeLang = Language::where('status', 1)->first();
        $langCode = $activeLang ? $activeLang->code : 'id';
        $accountMapping = $this->loadAccountMapping($langCode);

        // Get company type for specific translations
        $companyTypeObj = LicencesCompanyType::first();
        $companyType = ($companyTypeObj && !empty($companyTypeObj->type)) ? $companyTypeObj->type : 'pt';

        $data = Stocktransaction::where('id', $request->id)->with('contact', 'sales', 'cashin', 'cashout', 'substocktransaction', 'substocktransaction.product.unit', 'credit', 'credit.cashout', 'credit.cashin', 'substocktransaction.multi_unit')->get();
        $data = $data->map(function ($item) use ($accountMapping, $companyType) {
            // Translate cashin if exists
            if ($item->cashin) {
                $originalName = $item->cashin->name;
                $translatedName = $this->translateAccountName($originalName, $companyType, $accountMapping);
                $item->cashin->rename = $translatedName;
            }

            // Translate cashout if exists
            if ($item->cashout) {
                $originalName = $item->cashout->name;
                $translatedName = $this->translateAccountName($originalName, $companyType, $accountMapping);
                $item->cashout->rename = $translatedName;
            }

            // Translate credit cashin and cashout
            if ($item->credit) {
                foreach ($item->credit as $credit) {
                    if ($credit->cashin) {
                        $originalName = $credit->cashin->name;
                        $translatedName = $this->translateAccountName($originalName, $companyType, $accountMapping);
                        $credit->cashin->rename = $translatedName;
                    }
                    if ($credit->cashout) {
                        $originalName = $credit->cashout->name;
                        $translatedName = $this->translateAccountName($originalName, $companyType, $accountMapping);
                        $credit->cashout->rename = $translatedName;
                    }
                }
            }

            $sum_qty = $item->substocktransaction->map(function ($item2) {
                return array_merge($item2->toArray(), ['qty' => $item2->qty]);
            });
            return array_merge($item->toArray(), ['substocktransaction' => $sum_qty]);
        });
        $firstData = $data->first();
        $subreturid = $firstData['substocktransaction'][0]['id'];
        $subtransactionid = $firstData['substocktransaction'][0]['return_trans_id'];
        $subtransaction = Substocktransaction::where('id', $subtransactionid)->get();
        $subreturn = Substocktransaction::where('return_trans_id', $subreturid)->get();
        $response = [
            'success' => true,
            'stocktransaction' => $data,
            'subtransaction' => $subtransaction,
            'subreturn' => $subreturn,
        ];

        return response($response, 200);
    }

    public function getListStockOut(Request $request)
    {
        try {
            // Validate request
            $request->validate([
                'product_id' => 'required|exists:products,id',
                'start_date' => 'nullable|date',
                'end_date' => 'nullable|date|after_or_equal:start_date'
            ]);

            $query = Substocktransaction::where('product_id', $request->product_id)
                ->with(['stocktransaction' => function ($query) {
                    $query->with('contact')
                        ->whereNotNull('cashin_id')
                        ->whereNull('pending')
                        ->whereNull('nonmoney')
                        ->whereNull('return');
                }]);

            if ($request->filled(['start_date', 'end_date'])) {
                $start_date = date('Y-m-d', strtotime($request->start_date));
                $end_date = date('Y-m-d', strtotime($request->end_date));
                $query->whereHas('stocktransaction', function ($q) use ($start_date, $end_date) {
                    $q->whereBetween('date', [$start_date, $end_date]);
                });
            }

            $data = $query->get();

            // Filter out entries where stocktransaction is null due to the constraints
            $data = $data->filter(function ($item) {
                return !is_null($item->stocktransaction);
            });

            // Count unique customers
            $uniqueCustomers = $data->pluck('stocktransaction.contact_id')->unique()->count();

            return response()->json([
                'success' => true,
                'stocktransaction' => $data,
                'customers' => $uniqueCustomers,
                'qty' => $data->sum('qty')
            ], 200);
        } catch (ValidationException $e) {
            return response()->json([
                'success' => false,
                'message' => 'Validation error',
                'errors' => $e->errors()
            ], 422);
        } catch (\Exception $e) {
            Log::error('GetListStockOut error: ' . $e->getMessage());
            return response()->json([
                'success' => false,
                'message' => 'An error occurred while processing your request'
            ], 500);
        }
    }

    public function getCardStock(Request $request)
    {
        $query = Substocktransaction::where('product_id', $request->product_id);

        if ($request->filled(['start_date', 'end_date'])) {
            $start_date = date('Y-m-d', strtotime($request->start_date));
            $end_date = date('Y-m-d', strtotime($request->end_date));
            $query->whereHas('stocktransaction', function ($q) use ($start_date, $end_date) {
                $q->whereBetween('date', [$start_date, $end_date]);
            });
        }

        $data = $query->with('stocktransaction', 'stocktransaction.contact')->get()->map(function ($item) {
            $type = 'Unknown';
            $qty = $item->qty;

            $stock = $item->stocktransaction;

            if ($stock) {
                if (!is_null($stock->beginning_balance)) {
                    $type = 'Saldo Awal';
                    $qty = abs($qty);
                } elseif ($stock->type == 'modal_barang') {
                    $type = 'Modal Barang';
                    $qty = abs($qty);
                } elseif ($stock->is_so == true && $stock->nonmoney == 'out') {
                    $type = 'Stok Opname';
                    $qty = -abs($qty);
                } elseif ($stock->is_so == true && $stock->nonmoney == 'in') {
                    $type = 'Stok Opname';
                    $qty = abs($qty);
                } elseif ($stock->is_so == false && $stock->nonmoney == 'out' && is_null($stock->production_id)) {
                    $type = 'Koreksi Stok Keluar';
                    $qty = -abs($qty);
                } elseif ($stock->is_so == false && $stock->nonmoney == 'in' && is_null($stock->production_id)) {
                    $type = 'Koreksi Stok Masuk';
                    $qty = abs($qty);
                } elseif ($stock->is_so == false && $stock->nonmoney == 'out' && !is_null($stock->production_id)) {
                    $type = 'Proses Produksi';
                    $qty = -abs($qty);
                } elseif ($stock->is_so == false && $stock->nonmoney == 'in' && !is_null($stock->production_id)) {
                    $type = 'Produksi';
                    $qty = abs($qty);
                } elseif ($stock->return == 'out') {
                    $type = 'Retur Pembelian';
                    $qty = -abs($qty);
                } elseif ($stock->return == 'in') {
                    $type = 'Retur Penjualan';
                    $qty = abs($qty);
                } elseif (
                    $stock->is_so == false &&
                    is_null($stock->nonmoney) &&
                    is_null($stock->beginning_balance) &&
                    is_null($stock->return) &&
                    is_null($stock->cashout_id)
                ) {
                    $type = 'Penjualan';
                    $qty = -abs($qty);
                } elseif (
                    $stock->is_so == false &&
                    is_null($stock->nonmoney) &&
                    is_null($stock->beginning_balance) &&
                    is_null($stock->return) &&
                    is_null($stock->cashin_id)
                ) {
                    $type = 'Pembelian';
                    $qty = abs($qty);
                }
            }

            $item->type_transaction = $type;
            $item->qty_transaction = $qty;
            return $item;
        });

        // Hitung total qty sebelum start_date
        $totalQtyBeforeStart = 0;
        if ($start_date) {
            $beforeStartData = Substocktransaction::where('product_id', $request->product_id)
                ->whereHas('stocktransaction', function ($q) use ($start_date) {
                    $q->where('date', '<', $start_date);
                })
                ->with('stocktransaction')
                ->get()
                ->map(function ($item) {
                    $qty = $item->qty;
                    $stock = $item->stocktransaction;

                    if ($stock) {
                        if (!is_null($stock->beginning_balance)) {
                            $qty = abs($qty);
                        } elseif ($stock->type == 'modal_barang') {
                            $qty = abs($qty);
                        } elseif ($stock->is_so == true && $stock->nonmoney == 'out') {
                            $qty = -abs($qty);
                        } elseif ($stock->is_so == true && $stock->nonmoney == 'in') {
                            $qty = abs($qty);
                        } elseif ($stock->is_so == false && $stock->nonmoney == 'out') {
                            $qty = -abs($qty);
                        } elseif ($stock->is_so == false && $stock->nonmoney == 'in') {
                            $qty = abs($qty);
                        } elseif (
                            $stock->is_so == false &&
                            is_null($stock->nonmoney) &&
                            is_null($stock->beginning_balance) &&
                            is_null($stock->return) &&
                            is_null($stock->cashout_id)
                        ) {
                            $qty = -abs($qty);
                        } elseif (
                            $stock->is_so == false &&
                            is_null($stock->nonmoney) &&
                            is_null($stock->beginning_balance) &&
                            is_null($stock->return) &&
                            is_null($stock->cashin_id)
                        ) {
                            $qty = abs($qty);
                        }
                    }

                    return $qty;
                });

            $totalQtyBeforeStart = $beforeStartData->sum();
        }

        $sumPlus = $data->filter(function ($item) {
            return $item->qty_transaction > 0;
        })->sum('qty_transaction');

        $sumMinus = $data->filter(function ($item) {
            return $item->qty_transaction < 0;
        })->sum('qty_transaction');

        $response = [
            'success' => true,
            'data' => $data,
            'qty' => $data->sum('qty_transaction'),
            'qty_before' => $totalQtyBeforeStart,
            'sum_plus' => $sumPlus,
            'sum_minus' => $sumMinus,
        ];

        return response($response, 200);
    }

    public function createStockIn(Request $request)
    {
        $request->validate([
            'contact_id' => 'required',
            'cashout_id' => 'nullable',
            'cashin_id' => 'nullable',
            'staff' => 'required',
            'paid' => 'required',
            'discount' => 'nullable',
            'vat_base' => 'nullable',
            'desc' => 'nullable',
            'payment_due' => 'required',
            'date' => 'required',
            'id' => 'nullable',
            'remaind' => 'nullable',
            'pph23_amount' => 'nullable',
            'pph22_amount' => 'nullable',
            'pph22_amount_v2' => 'nullable',
            'pph4_2_amount' => 'nullable',
            'pph21_amount' => 'nullable',
            'product_id.*' => 'required',
            'qty.*'  => 'required',
            'purchase_price.*'  => 'required',
            'purchase_satuan.*'  => 'nullable',
            'purchase_multi_satuan.*'  => 'nullable',
            'ppn_amount.*'  => 'nullable',
            'unit_id.*'  => 'nullable',
            'multi_unit.*'  => 'required',
            'qty_unit.*'  => 'required',
            'purchase_price_unit.*'  => 'required',
            'total.*'  => 'required|numeric',
        ]);

        $paid = 0;
        if (!empty($request->paid) || $request->paid > 0) {
            $request->validate([
                'cashout_id' => 'required',
            ]);
        }
        if (empty($request->cashout_id)) {
            if (empty($request->id)) {
                $request->cashout_id = Akun::where('iscash', true)->first()->id;
            } else {
                $request->cashout_id = Akun::where('name', '=', 'Uang Muka Pesanan Pembelian')->first()->id;
            }
        }

        $request->pph23_amount = $request->pph23_amount ?? 0;
        $request->pph22_amount = $request->pph22_amount ?? 0;
        $request->pph22_amount_v2 = $request->pph22_amount_v2 ?? 0;
        $request->pph4_2_amount = $request->pph4_2_amount ?? 0;
        $request->pph21_amount = $request->pph21_amount ?? 0;

        // Check apakah PKP
        $is_pkp = TaxSettingMain::where('name', 'vat_registered ')->first()->vat_registered ?? false;

        DB::beginTransaction();

        try {
            $stock = new Stocktransaction;
            $stock->contact_id = $request->contact_id;
            $stock->cashout_id = $request->cashout_id;
            $stock->staff = $request->staff;
            $stock->description = $request->desc;
            $stock->pending = null;
            $stock->date = date("Y-m-d", strtotime($request->date));
            $stock->paid = $request->paid;
            $stock->payment_due = date("Y-m-d", strtotime($request->payment_due));
            $stock->pph23_amount = $request->pph23_amount;
            $stock->pph22_amount = $request->pph22_amount;
            $stock->pph22_amount_v2 = $request->pph22_amount_v2;
            $stock->pph4_2_amount = $request->pph4_2_amount;
            $stock->pph21_amount = $request->pph21_amount;
            $stock->is_pkp = $is_pkp;
            $stock->vat_base = $request->vat_base ?? 0;
            // $stock->return_id = $request->id;
            $stock->save();

            if (!empty($request->discount) && $request->discount > 0) {
                $cash = new Cashtransaction;
                $cash->staff = $request->staff;
                $cash->date = date("Y-m-d", strtotime($request->date));
                $cash->transaction_category = 'potongan_pembelian';
                $cash->stocktransaction_id = $stock->id;
                $cash->cashout = 0;
                $cash->cashin = 0;
                $cash->transfer = 0;
                $cash->save();

                $subcash = new Subcashtransaction;
                $subcash->cashtransaction_id = $cash->id;
                $subcash->akun_id = 44;
                $subcash->total = $request->discount;
                $subcash->desc = $request->desc;
                $subcash->save();

                $stock = Stocktransaction::find($stock->id);
                $stock->cashtransaction_id = $cash->id;
                $stock->save();
            }

            $data = $request->product_id;
            $total = 0;
            $total_ppn = 0;
            $substocktransactions = [];

            foreach ($data as $key => $value) {
                $total = $total + $request->total[$key];
                $total_ppn = $total_ppn + ($request->ppn_amount[$key] ?? 0);
                // jika terjadi masalah di $total
                if ($total <= 0) {
                    throw new \Exception('Total cannot be zero or negative.');
                }

                $subtotal = !$is_pkp ? $request->total[$key] : $request->total[$key] - $request->ppn_amount[$key];

                $sub = new Substocktransaction;
                $sub->stocktransaction_id = $stock->id;
                $sub->product_id = $request->product_id[$key];
                $sub->qty = $request->qty[$key];
                $sub->purchase_price = $request->purchase_price[$key];
                $sub->left = $request->qty[$key];
                $sub->total = $subtotal;
                $sub->multi_unit = $request->multi_unit[$key];
                $sub->qty_unit = $request->qty_unit[$key];
                $sub->purchase_price_unit = $request->purchase_price_unit[$key];
                $sub->ppn_amount = $request->ppn_amount[$key];
                $sub->save();

                $substocktransactions[] = $sub;

                $product = Product::find($sub->product_id);
                $product->qty = $product->qty + $sub->qty;
                $product->save();
            }

            $akun = Akun::find($request->cashout_id);
            $akun->total = $akun->total - $stock->paid;
            $akun->save();

            $akun = Akun::where('name', '=', 'Persediaan Barang')->first();
            $akun = Akun::find($akun->id);
            $akun->total = $akun->total + $total;
            $akun->save();

            if ($stock->paid > 0) {
                $credit = new Credit;
                $credit->stocktransaction_id = $stock->id;
                $credit->cashout_id = $stock->cashout_id;
                $credit->total = $stock->paid;
                $credit->staff = $request->staff;
                $credit->date = date("Y-m-d", strtotime($request->date));
                $credit->save();
            }

            if ($stock->pph23_amount > 0) {
                $akun = Akun::where('name', 'Utang_PPh_23')->first();
                $credit = new Credit;
                $credit->stocktransaction_id = $stock->id;
                $credit->cashout_id = $akun->id;
                $credit->total = $stock->pph23_amount;
                $credit->staff = $request->staff;
                $credit->date = date("Y-m-d", strtotime($request->date));
                $credit->save();
            }

            if ($stock->pph22_amount > 0) {
                $akun = Akun::where('name', 'Utang_PPh_22')->first();
                $credit = new Credit;
                $credit->stocktransaction_id = $stock->id;
                $credit->cashout_id = $akun->id;
                $credit->total = $stock->pph22_amount;
                $credit->staff = $request->staff;
                $credit->date = date("Y-m-d", strtotime($request->date));
                $credit->save();
            }

            if ($stock->pph22_amount_v2 > 0) {
                $akun = Akun::where('name', 'Uang_Muka_PPh_22')->first();
                $credit = new Credit;
                $credit->stocktransaction_id = $stock->id;
                $credit->cashout_id = $akun->id;
                $credit->total = $stock->pph22_amount_v2;
                $credit->staff = $request->staff;
                $credit->date = date("Y-m-d", strtotime($request->date));
                $credit->save();
            }

            if ($stock->pph4_2_amount > 0) {
                $akun = Akun::where('name', 'Utang_PPh_Pasal_4_ayat_2')->first();
                $credit = new Credit;
                $credit->stocktransaction_id = $stock->id;
                $credit->cashout_id = $akun->id;
                $credit->total = $stock->pph4_2_amount;
                $credit->staff = $request->staff;
                $credit->date = date("Y-m-d", strtotime($request->date));
                $credit->save();
            }

            if ($stock->pph21_amount > 0) {
                $akun = Akun::where('name', 'Utang_PPh_21')->first();
                $credit = new Credit;
                $credit->stocktransaction_id = $stock->id;
                $credit->cashout_id = $akun->id;
                $credit->total = $stock->pph21_amount;
                $credit->staff = $request->staff;
                $credit->date = date("Y-m-d", strtotime($request->date));
                $credit->save();
            }

            $paid = 0;
            if (!empty($request->id)) {
                $this->pendingToIn($request);
                $pending = Stocktransaction::find($request->id);
                $paid = $pending->paid - $request->remaind;

                $stock->order_id = $request->id;
                $stock->save();

                $total_um = $pending->paid - ($pending->paid - $request->remaind);
                $akun = Akun::where('name', '=', 'Uang Muka Pesanan Pembelian')->first();

                $credit = new Credit;
                $credit->stocktransaction_id = $stock->id;
                // $credit->cashout_id = $pending->cashout_id;
                $credit->cashout_id = $akun->id; // Uang muka pesanan pembelian
                $credit->total = $total_um > 0 ? $total : $pending->paid;
                $credit->staff = $request->staff;
                $credit->date = date("Y-m-d", strtotime($request->date));
                $credit->save();

                if ($total_um > 0) {
                    $cash = new Cashtransaction;
                    $cash->to = $request->cashin_id;
                    $cash->staff = $request->staff;
                    $cash->date = date("Y-m-d", strtotime($request->date));
                    $cash->transaction_category = 'pengembalian_uang_muka';
                    $cash->stocktransaction_id = $stock->id;
                    $cash->cashout = 0;
                    $cash->cashin = $total_um;
                    $cash->transfer = 0;
                    $cash->save();

                    $stock->cashout_id = $akun->id; // Uang muka pesanan pembelian
                    $stock->cashtransaction_id = $cash->id;
                    $stock->save();

                    $sub = new Subcashtransaction;
                    $sub->cashtransaction_id = $cash->id;
                    $sub->akun_id = $akun->id; // Uang muka pesanan pembelian
                    $sub->total = $total_um;
                    $sub->desc = $request->desc;
                    $sub->save();
                } elseif ($paid < $total) {
                    $cash = new Cashtransaction;
                    $cash->staff = $request->staff;
                    $cash->date = date("Y-m-d", strtotime($request->date));
                    $cash->transaction_category = 'kekurangan_pesanan_pembelian';
                    $cash->stocktransaction_id = $stock->id;
                    $cash->cashin = 0;
                    $cash->cashout = $total - $paid;
                    $cash->transfer = 0;
                    $cash->save();

                    $stock->cashtransaction_id = $cash->id;
                    $stock->save();

                    $sub = new Subcashtransaction;
                    $sub->cashtransaction_id = $cash->id;
                    $sub->akun_id = $request->cashout_id;
                    $sub->total = $total - $paid;
                    $sub->desc = $request->desc;
                    $sub->save();
                } elseif ($paid == $total) {
                    $stock->cashout_id = $akun->id; // Uang muka pesanan pembelian
                    $stock->save();
                }
            }

            $akun = Akun::where('name', '=', 'Hutang Pembelian Non Tunai')->first();
            $akun = Akun::find($akun->id);
            $pph_total = $stock->pph23_amount + $stock->pph22_amount + $stock->pph4_2_amount + $stock->pph21_amount;
            $akun->total = $akun->total + (($total - $request->discount - $pph_total) - $stock->paid);
            $akun->save();

            $akun = Akun::where('name', '=', 'Potongan Pembelian')->first();
            $akun = Akun::find($akun->id);
            $akun->total = $akun->total + $request->discount;
            $akun->save();

            $stock = Stocktransaction::find($stock->id);
            $stock->discount = $stock->discount + $request->discount;
            $stock->total = $total;
            $stock->total_ppn = $total_ppn;
            $stock->paid = $stock->paid + $paid;
            $stock->save();

            if ($stock->pph22_amount_v2 > 0) {
                $stock = Stocktransaction::find($stock->id);
                $stock->total += $stock->pph22_amount_v2;
                $stock->save();
            }

            $productData = null;
            $multisData = null;

            foreach ($data as $key => $value) {
                $sub = new Substocktransaction;
                $sub->product_id = $request->product_id[$key];

                $product = Product::find($sub->product_id);

                $multis = MultiUnit::with('multi_unit')
                    ->where('product_id', $sub->product_id)
                    ->get();

                if ($request->purchase_satuan[$key] != 0) {
                    $product->purchase_price = $request->purchase_satuan[$key];

                    if ($product->profit_strategy === 'persentase') {
                        $percent = $product->profit_strategy_percent;

                        $product->selling_price = $product->purchase_price + ($product->purchase_price * ($percent / 100));
                        $product->selling_price = round($product->selling_price, -2);
                    }

                    if ($multis->isNotEmpty()) {
                        foreach ($multis as $m) {
                            $m->multi_purchase_price = $product->purchase_price * $m->multi_qty;

                            if ($product->profit_strategy === 'persentase') {
                                $m->multi_selling_price = $m->multi_purchase_price + ($m->multi_purchase_price * ($percent / 100));
                                $m->multi_selling_price = round($m->multi_selling_price, -2);
                            }

                            $m->save();
                        }
                    }
                }

                if ($request->purchase_multi_satuan[$key] != 0) {
                    if ($request->unit_id[$key] != 'none') {
                        $multi = MultiUnit::where('product_id', $product->id)
                            ->where('multi_unit', $request->unit_id[$key])
                            ->first();
                        if ($multi) {
                            $multi->multi_purchase_price = $request->purchase_multi_satuan[$key];

                            if ($product->profit_strategy === 'persentase') {
                                $percent = $product->profit_strategy_percent;

                                $multi->multi_selling_price = $multi->multi_purchase_price + ($multi->multi_purchase_price * ($percent / 100));
                                $multi->multi_selling_price = round($multi->multi_selling_price, -2);
                            }

                            $multi->save();

                            if ($multi->multi_qty != 0) {
                                $mq = $multi->multi_purchase_price / $multi->multi_qty;
                                $mq = round($mq, -2);

                                if ($product->profit_strategy === 'persentase') {
                                    $product->purchase_price = $mq;
                                    $product->selling_price = $product->purchase_price + ($product->purchase_price * ($percent / 100));
                                    $product->selling_price = round($product->selling_price, -2);
                                }
                            }

                            if ($multis->isNotEmpty()) {
                                foreach ($multis as $m) {
                                    if ($m->id !== $multi->id) {
                                        if ($product->profit_strategy === 'persentase') {
                                            $m->multi_purchase_price = $product->purchase_price * $m->multi_qty;
                                            $m->multi_selling_price = $m->multi_purchase_price + ($m->multi_purchase_price * ($percent / 100));
                                            $m->multi_selling_price = round($m->multi_selling_price, -2);
                                        }

                                        $m->save();
                                    }
                                }
                            }
                        }
                    }
                }

                $product->save();

                // Store last product and multis for response
                $productData = $product;
                $multisData = $multis;
            }

            DB::commit();

            $response = [
                'success' => true,
                'stockktransaction' => $stock,
                'substocktransaction' => $substocktransactions,
                'product' => $productData,
                'multis' => $multisData,
            ];

            return response($response, 200);
        } catch (\Exception $e) {
            DB::rollback();

            $response = [
                'success' => false,
                'message' => 'Terjadi kesalahan saat memproses stock in: ' . $e->getMessage(),
            ];

            return response($response, 500);
        }
    }

    public function createStockOut(Request $request)
    {
        $request->validate([
            'contact_id' => 'required',
            'sales_person' => 'nullable',
            'cashin_id' => 'nullable',
            'cashout_id' => 'nullable',
            'staff' => 'required',
            'paid' => 'required',
            'date' => 'required',
            'payment_due' => 'required',
            'discount' => 'nullable',
            'vat_base' => 'nullable',
            'cash_received' => 'nullable',
            'cash_change' => 'nullable',
            'pph23_amount' => 'nullable',
            'pph22_amount' => 'nullable',
            'pph4_2_amount' => 'nullable',
            'pph4_2_amount_v2' => 'nullable',
            'pph21_amount' => 'nullable',
            'id' => 'nullable',
            'remaind' => 'nullable',
            'product_id.*' => 'required',
            'selling_price.*' => 'required',
            'multi_unit.*'  => 'required',
            'qty_unit.*' => 'required',
            'selling_price_unit.*'  => 'required',
            'ppn_amount.*' => 'nullable',
            'qty.*'  => 'required',
            'total.*'  => 'required|numeric',
        ]);

        if (!empty($request->paid) || $request->paid > 0) {
            $request->validate([
                'cashin_id' => 'required',
            ]);
        }
        if (empty($request->cashin_id)) {
            if (empty($request->id)) {
                $request->cashin_id = Akun::where('iscash', true)->first()->id;
            } else {
                $request->cashin_id = Akun::where('name', '=', 'Hutang Pesanan Penjualan')->first()->id;
            }
        }

        $contact = Contact::where('id', $request->contact_id)->first();
        $sum = 0;

        foreach ($request->total as $key => $value) {
            $sum = $sum + $request->total[$key];
        }
        $paid = 0;
        if (!empty($request->id)) {
            $pending = Stocktransaction::find($request->id);
            $paid = $pending->paid;
        }
        $request->paid = $request->paid + $paid;
        $request->pph23_amount = $request->pph23_amount ?? 0;
        $request->pph22_amount = $request->pph22_amount ?? 0;
        $request->pph4_2_amount = $request->pph4_2_amount ?? 0;
        $request->pph4_2_amount_v2 = $request->pph4_2_amount_v2 ?? 0;
        $request->pph21_amount = $request->pph21_amount ?? 0;
        $hutang = round(($sum - $request->discount - $request->pph23_amount - $request->pph22_amount - $request->pph4_2_amount - $request->pph21_amount) - $request->paid, 2);
        $maxdebt = $contact->type()->first()->maxdebt ?? 0;
        if ($hutang > $maxdebt) {
            return response(['error' => 'Hutang melebihi batas'], 400);
        }
        $request->paid = $request->paid - $paid;

        $paydue = date("Y-m-d", strtotime($request->payment_due));
        $day = $contact->type()->first()->max_paydue;
        $max_patdue = date('Y-m-d', time() + (60 * 60 * 24 * $day));
        if ($paydue > $max_patdue && $contact->type()->first()->max_paydue != null) {
            return response(['error' => 'Jatuh tempo melebihi batas'], 400);
        }

        $is_pkp = TaxSettingMain::where('name', 'vat_registered ')->first()->vat_registered ?? false;

        $data = $request->product_id;
        // Pengecekan stok produk
        foreach ($data as $key => $value) {
            $dataQty = $request->qty[$key];
            $dataProduct = Product::find($request->product_id[$key]);

            if ($dataQty > $dataProduct->qty) {
                return response()->json([
                    'status' => 'error',
                    'error' => 'Stok tidak mencukupi untuk produk: ' . $dataProduct->name . '. Stok tersedia: ' . $dataProduct->qty
                ], 400);
            }
        }

        DB::beginTransaction();

        try {
            if (!empty($request->id)) {
                $this->pendingToOut($request);
            }

            $stock = new Stocktransaction;
            $stock->contact_id = $request->contact_id;
            $stock->sales_person = $request->sales_person;
            $stock->cashin_id = $request->cashin_id;
            $stock->description = $request->desc;
            $stock->staff = $request->staff;
            $stock->pending = null;
            $stock->date = date("Y-m-d", strtotime($request->date));
            $stock->paid = $request->paid;
            $stock->return_credit = 0;
            $stock->payment_due = date("Y-m-d", strtotime($request->payment_due));
            $stock->cash_received = $request->cash_received;
            $stock->cash_change = $request->cash_change;
            $stock->pph23_amount = $request->pph23_amount;
            $stock->pph22_amount = $request->pph22_amount;
            $stock->pph4_2_amount = $request->pph4_2_amount;
            $stock->pph4_2_amount_v2 = $request->pph4_2_amount_v2;
            $stock->pph21_amount = $request->pph21_amount;
            $stock->is_pkp = $is_pkp;
            $stock->vat_base = $request->vat_base ?? 0;
            // $stock->return_id = $request->id;
            $stock->save();

            $total = 0;
            $total_ppn = 0;
            $jasa = 0;
            $totalhpp = 0;
            $lasthb = 0;
            $qty = 0;
            $cashCreatedService = false;
            $cashCreatedProduct = false;
            $subcash_id = 0;
            $substocktransactions = [];

            foreach ($data as $key => $value) {
                $subtotal = !$is_pkp ? $request->total[$key] : $request->total[$key] - $request->ppn_amount[$key];

                $sub = new Substocktransaction;
                $sub->stocktransaction_id = $stock->id;
                $sub->product_id = $request->product_id[$key];
                $sub->selling_price = $request->selling_price[$key];
                $sub->qty = $request->qty[$key];
                $sub->total = $subtotal;
                $sub->multi_unit = $request->multi_unit[$key];
                $sub->qty_unit = $request->qty_unit[$key];
                $sub->selling_price_unit = $request->selling_price_unit[$key];
                $sub->ppn_amount = $request->ppn_amount[$key];
                $sub->save();

                $substocktransactions[] = $sub;

                $product = Product::find($sub->product_id);
                if ($product->category == 'service') {

                    $akun = Akun::where('name', '=', 'Pendapatan Jasa')->first();
                    $akun = Akun::find($akun->id);
                    $akun->total = $akun->total + $sub->total;
                    $akun->save();
                    $jasa = $jasa + $sub->total;
                    $total = $total + $sub->total;
                    $total_ppn = $total_ppn + $sub->ppn_amount;

                    if (!$cashCreatedService) {
                        $cash = new Cashtransaction;
                        $cash->staff = $request->staff;
                        $cash->date = date("Y-m-d", strtotime($request->date));
                        $cash->transaction_category = 'pendapatan_jasa';
                        $cash->stocktransaction_id = $stock->id;
                        $cash->cashout = 0;
                        $cash->cashin = 0;
                        $cash->transfer = 0;
                        $cash->save();

                        $cashCreatedService = true;

                        $stock = Stocktransaction::find($stock->id);
                        $stock->cashtransaction_id = $cash->id;
                        $stock->save();

                        $subcash = new Subcashtransaction;
                        $subcash->cashtransaction_id = $cash->id;
                        $subcash->akun_id = 39;
                        $subcash->total = 0;
                        $subcash->desc = $request->desc;
                        $subcash->save();

                        $subcash_id = $subcash->id;
                    }

                    $subtotal = $sub->selling_price * $sub->qty;

                    $subcash = Subcashtransaction::find($subcash_id);
                    $subcash->total = $subcash->total + $subtotal;
                    $subcash->save();
                    continue;
                }

                if ($product->category == 'product') {
                    if (!$cashCreatedProduct) {
                        $cash = new Cashtransaction;
                        $cash->staff = $request->staff;
                        $cash->date = date("Y-m-d", strtotime($request->date));
                        $cash->transaction_category = 'pendapatan_penjualan';
                        $cash->stocktransaction_id = $stock->id;
                        $cash->cashout = 0;
                        $cash->cashin = 0;
                        $cash->transfer = 0;
                        $cash->save();

                        $cashCreatedProduct = true;

                        $stock = Stocktransaction::find($stock->id);
                        $stock->cashtransaction_id = $cash->id;
                        $stock->save();

                        $subcash = new Subcashtransaction;
                        $subcash->cashtransaction_id = $cash->id;
                        $subcash->akun_id = 40;
                        $subcash->total = 0;
                        $subcash->desc = $request->desc;
                        $subcash->save();

                        $subcash_id = $subcash->id;
                    }

                    $subtotal = $sub->selling_price * $sub->qty;

                    $subcash = Subcashtransaction::find($subcash_id);
                    $subcash->total = $subcash->total + $subtotal;
                    $subcash->save();
                }
                $product->qty = $product->qty - $sub->qty;
                $product->save();

                $qty = $sub->qty;
                $subin = Substocktransaction::where('left', '>', 0)
                    ->whereHas('stocktransaction', function ($query) {
                        $query->whereNull('pending');
                    })->where('product_id', '=', $sub->product_id)->get();

                // temp array substock ids
                $substocktransactions_ids = [];

                foreach ($subin as $key => $value) {

                    // push id
                    array_push($substocktransactions_ids, $value->id);

                    if ($qty <= $value->left) {

                        $set = $value->left - $qty;

                        $sibin = Substocktransaction::find($value->id);
                        $sibin->left = $set;
                        $sibin->save();

                        $totalhpp = $totalhpp + ($value->purchase_price * $qty);
                        break;
                    } else {
                        $set = 0;
                        $qty = $qty - $value->left;
                        $totalhpp = $totalhpp + ($value->purchase_price * $value->left);

                        $sibin = Substocktransaction::find($value->id);
                        $sibin->left = $set;
                        $sibin->save();
                    }

                    $lasthb = $value->purchase_price;
                }

                $sibin = Substocktransaction::find($sub->id);
                $sibin->hpp = $totalhpp;
                $sibin->substocktransactions_ids = join(",", $substocktransactions_ids); // merge array with string ","
                $sibin->save();
                $totalhpp = 0;
                $total = $total + $sub->total;
                $total_ppn = $total_ppn + $sub->ppn_amount;
            }

            if ($stock->paid > 0) {
                $credit = new Credit;
                $credit->stocktransaction_id = $stock->id;
                $credit->cashin_id = $stock->cashin_id;
                $credit->total = $stock->paid;
                $credit->staff = $request->staff;
                $credit->date = date("Y-m-d", strtotime($request->date));
                $credit->save();
            }

            $paid = 0;
            if (!empty($request->id)) {
                $pending = Stocktransaction::find($request->id);
                $paid = $pending->paid - $request->remaind;

                $stock->order_id = $request->id;
                $stock->save();

                $total_um = $pending->paid - ($pending->paid - $request->remaind);
                $akun = Akun::where('name', '=', 'Hutang Pesanan Penjualan')->first();

                $credit = new Credit;
                $credit->stocktransaction_id = $stock->id;
                $credit->cashin_id = $akun->id;
                $credit->total = $total_um > 0 ? $total : $pending->paid;
                $credit->staff = $request->staff;
                $credit->date = date("Y-m-d", strtotime($request->date));
                $credit->save();

                if ($total_um > 0) {
                    $cash = new Cashtransaction;
                    $cash->from = $request->cashout_id;
                    $cash->staff = $request->staff;
                    $cash->date = date("Y-m-d", strtotime($request->date));
                    $cash->transaction_category = 'pengembalian_hutang_pesanan_penjualan';
                    $cash->stocktransaction_id = $stock->id;
                    $cash->cashout = $total_um;
                    $cash->cashin = 0;
                    $cash->transfer = 0;
                    $cash->save();

                    $stock->cashin_id = $akun->id; // Hutang Pesanan Penjualan
                    $stock->cashtransaction_id = $cash->id;
                    $stock->save();

                    $sub = new Subcashtransaction;
                    $sub->cashtransaction_id = $cash->id;
                    $sub->akun_id = $akun->id; // Hutang Pesanan Penjualan
                    $sub->total = $total_um;
                    $sub->desc = $request->desc;
                    $sub->save();
                } elseif ($paid < $total) {
                    $cash = new Cashtransaction;
                    $cash->staff = $request->staff;
                    $cash->date = date("Y-m-d", strtotime($request->date));
                    $cash->transaction_category = 'kekurangan_pesanan_penjualan';
                    $cash->stocktransaction_id = $stock->id;
                    $cash->cashin = $total - $paid;
                    $cash->cashout = 0;
                    $cash->transfer = 0;
                    $cash->save();

                    $stock->cashtransaction_id = $cash->id;
                    $stock->save();

                    $sub = new Subcashtransaction;
                    $sub->cashtransaction_id = $cash->id;
                    $sub->akun_id = $request->cashout_id;
                    $sub->total = $total - $paid;
                    $sub->desc = $request->desc;
                    $sub->save();
                } elseif ($paid == $total) {
                    $stock->cashin_id = $akun->id; // Hutang Pesanan Penjualan
                    $stock->save();
                }
            }

            if ($stock->pph23_amount > 0) {
                $akun = Akun::where('name', 'Piutang_PPh_Pasal_23')->first();
                $credit = new Credit;
                $credit->stocktransaction_id = $stock->id;
                $credit->cashin_id = $akun->id;
                $credit->total = $stock->pph23_amount;
                $credit->staff = $request->staff;
                $credit->date = date("Y-m-d", strtotime($request->date));
                $credit->save();
            }

            if ($stock->pph22_amount > 0) {
                $akun = Akun::where('name', 'Uang_Muka_PPh_22')->first();
                $credit = new Credit;
                $credit->stocktransaction_id = $stock->id;
                $credit->cashin_id = $akun->id;
                $credit->total = $stock->pph22_amount;
                $credit->staff = $request->staff;
                $credit->date = date("Y-m-d", strtotime($request->date));
                $credit->save();
            }

            if ($stock->pph4_2_amount > 0) {
                $akun = Akun::where('name', 'Biaya_PPh_4_2')->first();
                $credit = new Credit;
                $credit->stocktransaction_id = $stock->id;
                $credit->cashin_id = $akun->id;
                $credit->total = $stock->pph4_2_amount;
                $credit->staff = $request->staff;
                $credit->date = date("Y-m-d", strtotime($request->date));
                $credit->save();
            }

            if ($stock->pph4_2_amount_v2 > 0) {
                $stock = Stocktransaction::find($stock->id);
                $stock->total += $stock->pph4_2_amount_v2;
                $stock->save();

                $akunv1 = Akun::where('name', 'Biaya_PPh_4_2')->first();
                $akunv2 = Akun::where('name', 'Utang_PPh_Pasal_4_ayat_2')->first();

                $credit = new Credit;
                $credit->stocktransaction_id = $stock->id;
                $credit->cashin_id = $akunv1->id;
                $credit->total = $stock->pph4_2_amount_v2;
                $credit->staff = $request->staff;
                $credit->date = date("Y-m-d", strtotime($request->date));
                $credit->save();

                $credit = new Credit;
                $credit->stocktransaction_id = $stock->id;
                $credit->cashin_id = $akunv2->id;
                $credit->total = $stock->pph4_2_amount_v2;
                $credit->staff = $request->staff;
                $credit->date = date("Y-m-d", strtotime($request->date));
                $credit->save();
            }

            if ($stock->pph21_amount > 0) {
                $akun = Akun::where('name', 'Piutang_PPh_21')->first();
                $credit = new Credit;
                $credit->stocktransaction_id = $stock->id;
                $credit->cashin_id = $akun->id;
                $credit->total = $stock->pph21_amount;
                $credit->staff = $request->staff;
                $credit->date = date("Y-m-d", strtotime($request->date));
                $credit->save();
            }

            $stock = Stocktransaction::find($stock->id);
            $stock->discount = $stock->discount + $request->discount;
            $stock->total = $total;
            $stock->total_ppn = $total_ppn;
            $stock->paid = $stock->paid + $paid;
            $stock->save();

            $point = PointHelper::calculatePoint($stock->total);
            if ($point) {
                $pointtransaction = new PointTransaction;
                $pointtransaction->customer_id = $request->contact_id;
                $pointtransaction->type        = 'earn';
                $pointtransaction->point       = $point;
                $pointtransaction->reference   = 'PENJUALAN NO.' . $stock->id;
                $pointtransaction->date        = date("Y-m-d", strtotime($request->date));
                $pointtransaction->staff       = $request->staff;
                $pointtransaction->save();

                $contactPoint = ContactPoint::firstOrNew(['contact_id' => $request->contact_id]);
                $contactPoint->total_point = ($contactPoint->total_point ?? 0) + $point;
                $contactPoint->last_updated = now();
                $contactPoint->save();
            }

            DB::commit();

            $response = [
                'success' => true,
                'stockktransaction' => $stock,
                'substocktransaction' => $substocktransactions,
            ];

            return response($response, 200);
        } catch (\Exception $e) {
            DB::rollback();

            $response = [
                'success' => false,
                'message' => 'Terjadi kesalahan saat memproses stock out: ' . $e->getMessage(),
            ];

            return response($response, 500);
        }
    }

    public function pendingToIn(Request $request)
    {
        $stock = Stocktransaction::find($request->id);
        $stock->pending = 2;
        $stock->save();

        $akun = Akun::where('name', '=', 'Uang Muka Pesanan Pembelian')->first();
        $akun = Akun::find($akun->id);
        $akun->total = $akun->total -  $stock->paid;
        $akun->save();

        $akun = Akun::find($request->cashout_id);
        $akun->total = $akun->total + $stock->paid;
        $akun->save();
    }

    public function pendingToOut(Request $request)
    {
        $stock = Stocktransaction::find($request->id);
        $stock->pending = 2;
        $stock->save();

        $akun = Akun::where('name', '=', 'Hutang Pesanan Penjualan')->first();
        $akun = Akun::find($akun->id);
        $akun->total = $akun->total - $stock->paid;
        $akun->save();

        $akun = Akun::find($request->cashin_id);
        $akun->total = $akun->total - $stock->paid;
        $akun->save();
    }

    public function updateStockTransaction(Request $request)
    {
        $request->validate([
            'sales_person' => 'nullable',
        ]);

        $stock = Stocktransaction::find($request->id);
        $stock->sales_person = $request->sales_person;
        $stock->save();

        $response = [
            'success' => true,
            'stockktransaction' => $stock,
        ];
        return response($response, 200);
    }

    public function updateDescription(Request $request)
    {
        $request->validate([
            'desc' => 'nullable',
        ]);

        $stock = Stocktransaction::find($request->id);
        $stock->description = $request->desc;
        $stock->save();

        $response = [
            'success' => true,
            'stockktransaction' => $stock,
        ];
        return response($response, 200);
    }

    public function updateVatNumber(Request $request)
    {
        $request->validate([
            'vat_number' => 'nullable|string',
        ]);

        DB::beginTransaction();

        try {
            $stock = Stocktransaction::findOrFail($request->id);
            $stock->vat_number = $request->vat_number;
            $stock->save();

            DB::commit();

            return response([
                'success' => true,
                'stocktransaction' => $stock,
            ], 200);
        } catch (\Exception $e) {
            DB::rollBack();

            return response([
                'success' => false,
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function deleteStockTransaction(Request $request)
    {
        // data yang ingin di hapus
        $stock = Stocktransaction::with('substocktransaction')
            ->find($request->id);
        // return response($stock, 200);
        $sids = $stock->substocktransaction->map(function ($item) {
            return $item->id;
        });
        $hasReturn = Substocktransaction::whereIn('return_trans_id', $sids)
            ->with('stocktransaction')
            ->get()
            ->map(function ($item) {
                if ($item->stocktransaction->return === 'out') {
                    return 'RETUR PEMBELIAN no. ' . $item->stocktransaction->id;
                } else if ($item->stocktransaction->return === 'in') {
                    return 'RETUR PENJUALAN no. ' . $item->stocktransaction->id;
                }
            });

        if (count($hasReturn) > 0) {
            $response = [
                'success' => false,
                'message' => "Produk dalam transaksi ini telah diretur, " . $hasReturn[0] . ". Jika Anda ingin menghapus ini, silakan hapus transaksi tersebut terlebih dahulu.",
            ];

            return response($response, 400);
        }

        if ($stock) {
            // mengambil semua transaksi pembelian sebelumnya
            //  $out = Stocktransaction::where('id', $stock->id)
            //                ->with('substocktransaction')
            //                ->get()
            //                ->map(function ($item){
            //                  $substocktransaction = $item->substocktransaction;
            //                 //  return $substocktransaction->map(function ($item2) {
            //                     return $substocktransaction->flatMap(function ($item2) {
            //                      return Substocktransaction::where('substocktransactions_ids', 'LIKE', '%' . $item2->id . '%')->first();
            //                  });
            //                     // $substocktransaction = $item->substocktransaction;
            //                     // // Menggunakan flatMap untuk menyatukan hasil setiap item
            //                     // return $substocktransaction->flatMap(function ($item2) {
            //                     //     // Melakukan pencarian untuk setiap item2
            //                     //     return Substocktransaction::where('substocktransactions_ids', 'LIKE', '%' . $item2->id . '%')->get();
            //                     // });
            //                });
            //  $out = $out[0][0];
            $out = Stocktransaction::where('id', $stock->id)
                ->with('substocktransaction')
                ->get()
                ->map(function ($item) {
                    $substocktransaction = $item->substocktransaction;
                    // Menggunakan flatMap untuk menyatukan hasil setiap item
                    return $substocktransaction->flatMap(function ($item2) {
                        // Melakukan pencarian untuk setiap item2
                        return Substocktransaction::where(function ($query) use ($item2) {
                            $query->where('substocktransactions_ids', 'LIKE', $item2->id . ',%')
                                ->orWhere('substocktransactions_ids', 'LIKE', '%, ' . $item2->id . ',%')
                                ->orWhere('substocktransactions_ids', 'LIKE', '%, ' . $item2->id)
                                ->orWhere('substocktransactions_ids', '=', $item2->id);
                        })->get();
                    });
                })
                ->flatten(); // Menggabungkan semua hasil menjadi satu koleksi

            $out = $out->first();

            $dt_stock = [];
            $dt_stock2 = [];


            $dt_stock1 = Stocktransaction::where('id', $stock->id)
                ->with('substocktransaction')
                ->first();

            $sel_sub_stock = Substocktransaction::where('return_trans_id', $dt_stock1->substocktransaction->first()->return_trans_id)
                ->orderBy('created_at', 'asc')
                ->get();

            $dt_stock2 = optional($dt_stock1->substocktransaction->first())->return_trans_id
                ? Substocktransaction::where('id', $dt_stock1->substocktransaction->first()->return_trans_id)->first()
                : null;

            if ($dt_stock2 && $dt_stock2->stocktransaction_id) {
                $dt_stock = Stocktransaction::where('id', $dt_stock2->stocktransaction_id)
                    ->with('substocktransaction')
                    ->first();
            }

            if ($stock->cashin_id) {
                $akun = Akun::find($stock->cashin_id);
                $akun->total = $akun->total - $stock->paid;
                $akun->save();

                $akun = Akun::where('name', '=', 'Piutang Penjualan')->first();
                $akun = Akun::find($akun->id);
                $akun->total = $akun->total - ($stock->total - $stock->discount - $stock->paid);
                $akun->save();

                $sub = Substocktransaction::where('stocktransaction_id', '=', $stock->id)->get();
                $totalhpp = 0;
                $jasa = 0;
                foreach ($sub as $key => $value) {
                    $product = Product::find($value->product_id);
                    if ($product->category == 'service') {

                        $akun = Akun::where('name', '=', 'Pendapatan Jasa')->first();
                        $akun = Akun::find($akun->id);
                        $akun->total = $akun->total - $value->total;
                        $akun->save();
                        $jasa = $jasa + $value->total;
                        continue;
                    }
                    $product->qty = $product->qty + $value->qty;
                    $product->save();

                    if ($stock->return === 'out') {
                        $s_r = Substocktransaction::where('id', $value->return_trans_id)->where('product_id', $value->product_id)->first();
                        if ($s_r) {
                            $s_r->qty_retur = $s_r->qty_retur - $value->qty;
                            $s_r->save();
                        }
                    }

                    $totalhpp = $totalhpp + $value->hpp;
                    $qty = $value->qty;
                    $subin = explode(",", $value->substocktransactions_ids);
                    foreach ($subin as $key => $value) {
                        $sibin = Substocktransaction::find($value);

                        if ($qty <= $sibin->qty) {
                            $set = $sibin->left + $qty;
                            $sibin->left = $set;
                            $sibin->save();
                        } else {
                            $set = $sibin->qty;
                            $qty = $qty - $sibin->qty;
                            $sibin->left = $set;
                            $sibin->save();
                        }
                    }
                }

                $akun = Akun::where('name', '=', 'Persediaan Barang')->first();
                $akun = Akun::find($akun->id);
                $akun->total = $akun->total + $totalhpp;
                $akun->save();

                $akun = Akun::where('name', '=', 'Pendapatan Penjualan')->first();
                $akun = Akun::find($akun->id);
                $akun->total = $akun->total - ($stock->total - $jasa);
                $akun->save();

                $akun = Akun::where('name', '=', 'Harga Pokok Penjualan')->first();
                $akun = Akun::find($akun->id);
                $akun->total = $akun->total - $totalhpp;
                $akun->save();

                $akun = Akun::where('name', '=', 'Potongan Penjualan')->first();
                $akun = Akun::find($akun->id);
                $akun->total = $akun->total - $stock->discount;
                $akun->save();

                Substocktransaction::where('stocktransaction_id', '=', $stock->id)->delete();
                Credit::where('stocktransaction_id', '=', $stock->id)->delete();

                // menghapus cashtransaction
                if ($stock->cashtransaction_id) {
                    $data = Cashtransaction::where('stocktransaction_id', $stock->id)->get();
                    foreach ($data as $cashTransaction) {
                        if (in_array($cashTransaction->transaction_category, [
                            'biaya_retur_out',
                            'pendapatan_retur_out',
                            'pendapatan_jasa',
                            'pendapatan_penjualan',
                        ])) {
                            Subcashtransaction::where('cashtransaction_id', $cashTransaction->id)->delete();
                        }

                        $cashTransaction->delete();
                    }
                }

                // mengembalikan pending
                if ($stock->order_id) {
                    $data = Stocktransaction::find($stock->order_id);
                    $data->pending = 1;
                    $data->save();
                }

                // mengelola return_credit dalam stocktransactions
                if ($dt_stock && $dt_stock1->substocktransaction->first()->isdebt == 1) {
                    $dts = Stocktransaction::find($dt_stock->id);
                    if ($dts->return_credit > 0) {
                        $dts->return_credit -= $stock->return_credit_cash;
                        $dts->save();
                    }
                }

                $stock->delete();
                $stock->credit()->delete();

                $response = [
                    'success' => true,
                    'stocktransaction' => $stock,
                ];
                return response($response, 200);
            } elseif ($stock->cashout_id) {
                if (!$out) {
                    $akun = Akun::find($stock->cashout_id);
                    $akun->total = $akun->total + $stock->total;
                    $akun->save();

                    $totalhpp = 0;
                    $sub = Substocktransaction::where('stocktransaction_id', '=', $stock->id)->get();
                    foreach ($sub as $key => $value) {
                        $product = Product::find($value->product_id);
                        $product->qty = $product->qty - $value->qty;
                        $product->save();

                        $totalhpp = $totalhpp + ($value->left * $value->purchase_price);
                        //kembalikan qty jika return penjualan
                        if ($stock->return === 'in') {
                            $s_r = Substocktransaction::where('id', $value->return_trans_id)->where('product_id', $value->product_id)->first();
                            if ($s_r) {
                                $s_r->qty_retur = $s_r->qty_retur - $value->qty;
                                $s_r->save();
                            }
                        }
                    }

                    $akun = Akun::where('name', '=', 'Persediaan Barang')->first();
                    $akun = Akun::find($akun->id);
                    $akun->total = $akun->total - $stock->total;
                    $akun->save();

                    $akun = Akun::where('name', '=', 'Potongan Pembelian')->first();
                    $akun = Akun::find($akun->id);
                    $akun->total = $akun->total - $stock->discount;
                    $akun->save();

                    $akun = Akun::where('name', '=', 'Hutang Pembelian Non Tunai')->first();
                    $akun = Akun::find($akun->id);
                    $akun->total = $akun->total - (($totalhpp - $stock->discount) - $stock->paid);
                    $akun->save();

                    // menghapus cashtransaction
                    if ($stock->cashtransaction_id) {
                        $data = Cashtransaction::where('stocktransaction_id', $stock->id)->get();
                        foreach ($data as $cashTransaction) {
                            if (in_array($cashTransaction->transaction_category, [
                                'pendapatan_retur_in',
                                'potongan_pembelian',
                            ])) {
                                Subcashtransaction::where('cashtransaction_id', $cashTransaction->id)->delete();
                            }

                            $cashTransaction->delete();
                        }
                    }
                    // mengembalikan pending
                    if ($stock->order_id) {
                        $data = Stocktransaction::find($stock->order_id);
                        $data->pending = 1;
                        $data->save();
                    }
                    // mengelola return_credit dalam stocktransactions
                    if ($dt_stock && $dt_stock1->substocktransaction->first()->isdebt == 1) {
                        $dts = Stocktransaction::find($dt_stock->id);
                        if ($dts->return_credit > 0) {
                            $dts->return_credit -= $stock->return_credit_cash;
                            $dts->save();
                        }
                    }

                    Substocktransaction::where('stocktransaction_id', '=', $stock->id)->delete();
                    $stock->delete();
                    $stock->credit()->delete();

                    //  $response = [
                    //      'success'=>true,
                    //      'message'  => 'boleh',
                    //      'buy' => $total_buy,
                    //      'sell' => $total_sell
                    //  ];
                    //  return response($response,200);

                    $response = [
                        'success' => true,
                        'stocktransaction' => $stock,
                        'sel_sub_stock' => $sel_sub_stock,
                    ];
                    return response($response, 200);
                } else {
                    $response = [
                        'success' => false,
                        'message' => 'Produk dalam transaksi ini telah dikeluarkan dalam PENJUALAN / KOREKSI STOK - KURANGI STOK dengan nomor transaksi: ' . $out->stocktransaction_id . '. Jika Anda ingin menghapus transaksi ini, silakan hapus transaksi tersebut terlebih dahulu.',
                    ];
                    return response($response, 400);
                }
            }
        } else {
            $response = [
                'success' => false,
                'message' => 'not found'
            ];
            return response($response, 400);
        }
    }
}
