<?php

namespace App\Http\Controllers;

use App\Models\Production;
use App\Models\ProductionCost;
use App\Models\Product;
use App\Models\Unit;
use App\Models\Stocktransaction;
use App\Models\Substocktransaction;
use App\Models\Cashtransaction;
use App\Models\CreditCashTransaction;
use App\Models\Akun;
use App\Models\Subcashtransaction;
use App\Models\Language;
use App\Models\Licence;
use App\Models\MultiUnit;
use App\Models\ProductionRecipe;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Validation\Rule;

class ProductionController extends Controller
{
    public static function getActiveLanguage()
    {
        return Language::where('status', true)->first();
    }

    private function loadAkunMapping($langCode = 'id')
    {
        $jsonPath = config_path("lang/{$langCode}/akun.json");
        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)
    {
        if (isset($mappingData[$companyType][$accountName])) {
            return $mappingData[$companyType][$accountName];
        }
        if (isset($mappingData['akun_umum'][$accountName])) {
            return $mappingData['akun_umum'][$accountName];
        }
        return $accountName;
    }

    private function tambahNamaAkunSesuaiTipe(&$items, $companyType, $mappingData)
    {
        foreach ($items as $item) {
            $item->rename = $this->translateAccountName($item->name, $companyType, $mappingData);
            if ($item->children && $item->children->count() > 0) {
                $this->tambahNamaAkunSesuaiTipe($item->children, $companyType, $mappingData);
            }
        }
    }

    public function akuncostscharged(Request $request)
    {
        $relations = [];
        $relation = 'children';
        for ($i = 0; $i < 10; $i++) {
            $relations[] = $relation;
            $relation .= '.children';
        }

        $overhead = Akun::where('name', 'biaya_overhead_pabrik_dibebankan')->with($relations)->first();
        $children = $overhead ? $overhead->children : collect();

        $btlk = Akun::where('name', 'biaya_tenaga_kerja_langsung_dibebankan')->first();

        $result = $children ? $children->values() : collect();
        if ($btlk) {
            $result = $result->push($btlk);
        }

        $lang = self::getActiveLanguage();
        $langCode = $lang->code ?? 'id';
        $mappingData = $this->loadAkunMapping($langCode);
        $this->tambahNamaAkunSesuaiTipe($result, null, $mappingData);
        $result = $result->sortBy('rename', SORT_NATURAL | SORT_FLAG_CASE)->values();

        return response([
            'success' => true,
            'akun' => $result,
            'language' => $langCode
        ], 200);
    }

    public function akuncostsactual(Request $request)
    {
        $relations = [];
        $relation = 'children';
        for ($i = 0; $i < 10; $i++) {
            $relations[] = $relation;
            $relation .= '.children';
        }

        $overhead = Akun::where('name', 'biaya_overhead_pabrik_aktual')->with($relations)->first();
        $children = $overhead ? $overhead->children : collect();

        $btlk = Akun::where('name', 'biaya_tenaga_kerja_langsung_aktual')->with($relations)->first();
        if ($btlk && $btlk->children && $btlk->children->count() > 0) {
            $btlk->children = $btlk->children
                ->where('name', '!=', 'biaya_penyusutan_pabrik_aktual')
                ->values();
        }

        $result = $children ? $children->values() : collect();
        if ($btlk) {
            $result = $result->push($btlk);
        }

        $lang = self::getActiveLanguage();
        $langCode = $lang->code ?? 'id';
        $mappingData = $this->loadAkunMapping($langCode);
        $this->tambahNamaAkunSesuaiTipe($result, null, $mappingData);
        $result = $result->sortBy('rename', SORT_NATURAL | SORT_FLAG_CASE)->values();

        return response([
            'success' => true,
            'akun' => $result,
            'language' => $langCode
        ], 200);
    }

    public function akunAsetProduction(Request $request)
    {
        $akun = Akun::where('is_productionasset', true)->get();
        $lang = self::getActiveLanguage();
        $langCode = $lang->code ?? 'id';
        $mappingData = $this->loadAkunMapping($langCode);
        $this->tambahNamaAkunSesuaiTipe($akun, null, $mappingData);
        $akun = $akun->sortBy('rename', SORT_NATURAL | SORT_FLAG_CASE)->values();
        return response([
            'success' => true,
            'akun' => $akun,
            'language' => $langCode
        ], 200);
    }

    public function akuncostschargedassets(Request $request)
    {
        $relations = [];
        $relation = 'children';
        for ($i = 0; $i < 10; $i++) {
            $relations[] = $relation;
            $relation .= '.children';
        }

        $overhead = Akun::where('name', 'biaya_overhead_pabrik_dibebankan')->with($relations)->first();
        $children = $overhead ? $overhead->children : collect();

        $btlk = Akun::where('name', 'biaya_tenaga_kerja_langsung_dibebankan')->first();

        $charged = $children ? $children->values() : collect();
        if ($btlk) {
            $charged = $charged->push($btlk);
        }

        $assets = Akun::where('is_productionasset', true)->get();

        $result = $charged->concat($assets)->unique('id')->values();

        $lang = self::getActiveLanguage();
        $langCode = $lang->code ?? 'id';
        $mappingData = $this->loadAkunMapping($langCode);
        $this->tambahNamaAkunSesuaiTipe($result, null, $mappingData);
        $result = $result->sortBy('rename', SORT_NATURAL | SORT_FLAG_CASE)->values();

        return response([
            'success' => true,
            'akun' => $result,
            'language' => $langCode
        ], 200);
    }

    private function localizeProductionCosts($productions)
    {
        $lang = self::getActiveLanguage();
        $langCode = $lang->code ?? 'id';
        $mappingData = $this->loadAkunMapping($langCode);

        $licence = Licence::first();
        $companyType = $licence ? $licence->company_type : null;

        $items = ($productions instanceof \Illuminate\Support\Collection) ? $productions : collect([$productions]);

        foreach ($items as $production) {
            if ($production->costs) {
                foreach ($production->costs as $cost) {
                    if ($cost->cashtransaction && $cost->cashtransaction->subcashtransaction) {
                        foreach ($cost->cashtransaction->subcashtransaction as $sub) {
                            if ($sub->akun) {
                                $sub->akun->rename = $this->translateAccountName($sub->akun->name, $companyType, $mappingData);
                            }
                        }
                    }
                }
            }
        }
    }

    public function index(Request $request)
    {
        $query = Production::with([
            'product.unit',
            'multiunit.multi_unit',
            'stocktransactionOut.substocktransaction.product.unit',
            'stocktransactionOut.substocktransaction.multiunit.multi_unit',
            'costs',
            'costs.cashtransaction.from',
            'costs.cashtransaction.subcashtransaction.akun',
            'stocktransactions.substocktransaction.product.unit',
            'stocktransactions.substocktransaction.multiunit.multi_unit'
        ]);

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

        if (!empty($request->product_id)) {
            $query->where('product_id', $request->product_id);
        }

        $data = $query->orderBy('id', 'desc')->get();

        $akunNoOverhead = Akun::where('name', 'biaya_tenaga_kerja_langsung_dibebankan')->first();
        foreach ($data as $production) {
            foreach ($production->costs as $cost) {
                if ($cost->cashtransaction && $cost->cashtransaction->subcashtransaction) {
                    foreach ($cost->cashtransaction->subcashtransaction as $sub) {
                        if ($sub->akun) {
                            $sub->is_overhead = true;
                            if ($akunNoOverhead && $sub->akun->id === $akunNoOverhead->id) {
                                $sub->is_overhead = false;
                            }
                        }
                    }
                }
            }
        }

        $this->localizeProductionCosts($data);

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

    public function getProductions(Request $request)
    {
        $query = Production::with([
            'product.unit',
            'multiunit.multi_unit',
            'stocktransactionOut.substocktransaction.product.unit',
            'stocktransactionOut.substocktransaction.multiunit.multi_unit',
            'costs',
            'costs.cashtransaction.from',
            'costs.cashtransaction.subcashtransaction.akun',
            'stocktransactions.substocktransaction.product.unit',
            'stocktransactions.substocktransaction.multiunit.multi_unit'
        ]);

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

        if (!empty($request->status)) {
            $query->where('status', $request->status);
        }

        if (!empty($request->product_id)) {
            $query->where('product_id', $request->product_id);
        }

        $data = $query->orderBy('id', 'desc')->get();

        $akunNoOverhead = Akun::where('name', 'biaya_tenaga_kerja_langsung_dibebankan')->first();
        foreach ($data as $production) {
            foreach ($production->costs as $cost) {
                if ($cost->cashtransaction && $cost->cashtransaction->subcashtransaction) {
                    foreach ($cost->cashtransaction->subcashtransaction as $sub) {
                        if ($sub->akun) {
                            $sub->is_overhead = true;
                            if ($akunNoOverhead && $sub->akun->id === $akunNoOverhead->id) {
                                $sub->is_overhead = false;
                            }
                        }
                    }
                }
            }
        }

        $this->localizeProductionCosts($data);

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

    public function getMaterials(Request $request)
    {
        $productions = Production::with([
            'product.unit',
            'multiunit.multi_unit',
        ])->whereNotNull('stocktransaction_id_out');

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

        $productions = $productions->get();

        $productionIds = $productions->pluck('id');
        $productionOutIds = $productions->pluck('stocktransaction_id_out');

        $resultproduction = $productions->map(function ($item) {
            return [
                'product_finished_id' => $item->product_id,
                'multi_unit_finished' => $item->product_unit,
            ];
        });

        $recipe = ProductionRecipe::with([
            'productMaterial.unit',
            'multiunit.multi_unit',
        ])->where(function ($query) use ($resultproduction) {
            foreach ($resultproduction as $prod) {
                $query->orWhere(function ($q) use ($prod) {
                    $q->where('product_finished_id', $prod['product_finished_id'])
                        ->where('multi_unit_finished', $prod['multi_unit_finished']);
                });
            }
        })->get();

        $stocktransaction = Stocktransaction::with([
            'substocktransaction.product.unit',
            'substocktransaction.multiunit.multi_unit',
            'production'
        ])->whereIn('production_id', $productionIds)->whereNotIn('id', $productionOutIds)->get();

        $result = $productions->map(function ($item) use ($recipe, $stocktransaction) {
            $itemRecipe = $recipe->filter(function ($r) use ($item) {
                return $r->product_finished_id == $item->product_id &&
                    $r->multi_unit_finished == $item->product_unit;
            })->values();

            $itemMaterial = $stocktransaction->where('production_id', $item->id)->values();

            return [
                'id' => $item->id,
                'product_id' => $item->product_id,
                'multi_unit' => $item->product_unit,
                'qty' => $item->product_qty,
                'recipe' => $itemRecipe,
                'material' => $itemMaterial
            ];
        });

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

    public function show($id)
    {
        $data = Production::with([
            'product.unit',
            'multiunit.multi_unit',
            'stocktransactionOut.substocktransaction.product.unit',
            'stocktransactionOut.substocktransaction.multiunit.multi_unit',
            'costs',
            'costs.cashtransaction.from',
            'costs.cashtransaction.subcashtransaction.akun',
            'stocktransactions.substocktransaction.product.unit',
            'stocktransactions.substocktransaction.multiunit.multi_unit'
        ])->find($id);

        if (!$data) {
            return response([
                'success' => false,
                'message' => 'not found',
            ], 404);
        }

        $this->localizeProductionCosts($data);

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

    public function store(Request $request)
    {
        $request->validate([
            'product_id' => ['required', 'integer', 'exists:products,id'],
            'product_qty' => ['required', 'numeric'],
            'product_unit' => 'required',
            'date' => ['nullable', 'date'],
            'desc' => ['nullable', 'string'],
            'staff' => ['nullable', 'string'],
            'stock' => ['array'],
            'stock.*.product_id' => ['required', 'integer', 'exists:products,id'],
            'stock.*.qty' => ['required', 'numeric'],
            'status' => ['nullable', Rule::in(['draft', 'in_progress', 'completed', 'cancelled'])],
            'costs' => ['array'],
            'costs.*.cashtransaction_id' => ['nullable', 'integer', 'exists:cashtransactions,id'],
            'costs.*.akun_cost' => ['required', 'integer', 'exists:akuns,id'],
            // 'costs.*.cost_category' => ['required', Rule::in(['material', 'labor', 'overhead'])],
            // 'costs.*.cost_type' => ['required', Rule::in(['raw_material', 'production_wage', 'machine_electricity', 'machine_depreciation', 'other_cost'])],
            'costs.*.total' => ['required', 'numeric'],
        ]);

        DB::beginTransaction();
        try {
            $production = new Production;
            $production->product_id = $request->product_id;
            $production->product_qty = $request->product_qty;
            $production->product_unit = $request->product_unit != 'none' ? $request->product_unit : null;
            $production->date_in = $request->date ? date("Y-m-d", strtotime($request->date)) : null;
            if (!empty($request->status)) {
                $production->status = $request->status;
            }
            $production->save();

            // Jika request mengirim stock sebagai array, buat Stocktransaction + Substocktransaction
            if (is_array($request->stock) && count($request->stock) > 0) {
                // Pre-check stok cukup
                foreach ($request->stock as $item) {
                    $p = Product::find($item['product_id']);
                    if (!$p || $item['qty'] > ($p->qty ?? 0)) {
                        throw new \Exception('Stok tidak mencukupi untuk produk: ' . ($p->name ?? 'Unknown'));
                    }
                }

                $stock = new Stocktransaction;
                $stock->staff = $request->staff;
                $stock->description = $request->desc;
                $stock->date = date("Y-m-d", strtotime($request->date));
                $stock->total = 0;
                $stock->nonmoney = 'out';
                $stock->production_id = $production->id;
                $stock->save();

                $production->status = 'in_progress';
                $production->date_process = $request->date ? date("Y-m-d", strtotime($request->date)) : null;
                $production->save();

                foreach ($request->stock as $item) {
                    $totalhpp = 0;
                    $substocktransactions_ids = [];

                    $sub = new Substocktransaction;
                    $sub->stocktransaction_id = $stock->id;
                    $sub->product_id = $item['product_id'];
                    $sub->qty = $item['qty'];
                    $sub->multi_unit = $item['multi_unit'] == 'none' ? null : $item['multi_unit'];
                    $sub->qty_unit = $item['qty_unit'];
                    $sub->save();

                    $product = Product::find($sub->product_id);
                    $product->qty = ($product->qty ?? 0) - $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();

                    foreach ($subin as $value) {
                        $substocktransactions_ids[] = $value->id;
                        if ($qty <= $value->left) {
                            $set = $value->left - $qty;
                            $sibin = Substocktransaction::find($value->id);
                            $sibin->left = $set;
                            $sibin->save();
                            $totalhpp += ($value->purchase_price * $qty);
                            $qty = 0;
                            break;
                        } else {
                            $set = 0;
                            $qty -= $value->left;
                            $totalhpp += ($value->purchase_price * $value->left);
                            $sibin = Substocktransaction::find($value->id);
                            $sibin->left = $set;
                            $sibin->save();
                        }
                    }

                    $sibin = Substocktransaction::find($sub->id);
                    $sibin->hpp = $totalhpp;
                    $sibin->substocktransactions_ids = join(",", $substocktransactions_ids);
                    $sibin->save();
                }
            }

            $createdCosts = [];
            if (is_array($request->costs)) {
                foreach ($request->costs as $cost) {
                    $cost_category = $cost['cost_category'] ?? null;
                    if (!$cost_category && !empty($cost['akun_cost'])) {
                        $akunTenagaKerja = Akun::where('name', 'biaya_tenaga_kerja_langsung_dibebankan')->first();
                        $laborId = $akunTenagaKerja ? (int)$akunTenagaKerja->id : null;
                        $costAkunId = (int)$cost['akun_cost'];
                        $cost_category = ($laborId && $costAkunId === $laborId) ? 'labor' : 'overhead';
                    }

                    $pc = new ProductionCost;
                    $pc->production_id = $production->id;
                    $pc->cashtransaction_id = null;
                    $pc->cost_category = $cost_category;
                    $pc->total = $cost['total'];
                    $pc->save();

                    $cash = new Cashtransaction;
                    $cash->staff = $request->staff;
                    $cash->desc = $cost['desc'] ?? $request->desc;
                    $cash->date = date("Y-m-d", strtotime($request->date));
                    $cash->transaction_category = 'biaya_produksi_dibebankan';
                    $cash->save();

                    $sub = new Subcashtransaction;
                    $sub->cashtransaction_id = $cash->id;
                    $sub->akun_id = $cost['akun_cost'] ?? null;
                    $sub->total = $pc->total;
                    $sub->desc = $pc->cost_type;
                    $sub->save();

                    $cash = Cashtransaction::find($cash->id);
                    $cash->total = $pc->total;
                    $cash->save();

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

                    $createdCosts[] = $pc;
                }
            }

            if (is_array($request->costs) && count($request->costs) > 0) {
                $production->status = 'in_progress';
                $production->date_process = $request->date ? date("Y-m-d", strtotime($request->date)) : null;
                $production->save();
            }

            DB::commit();
            return response([
                'success' => true,
                'production' => $production->load(['product.unit', 'multiunit.multi_unit', 'stocktransactionOut']),
                'costs' => $createdCosts,
            ], 201);
        } catch (\Throwable $e) {
            DB::rollBack();
            return response([
                'success' => false,
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function addStock(Request $request, $id)
    {
        $request->validate([
            'staff' => ['nullable', 'string'],
            'desc' => ['nullable', 'string'],
            'date' => ['nullable', 'date'],
            'stock' => ['required', 'array', 'min:1'],
            'stock.*.product_id' => ['required', 'integer', 'exists:products,id'],
            'stock.*.qty' => ['required', 'numeric', 'min:0.01'],
        ]);

        DB::beginTransaction();
        try {
            // Cari production berdasarkan ID
            $production = Production::findOrFail($id);

            // Pre-check stok cukup
            foreach ($request->stock as $item) {
                $p = Product::find($item['product_id']);
                if (!$p || $item['qty'] > ($p->qty ?? 0)) {
                    throw new \Exception('Stok tidak mencukupi untuk produk: ' . ($p->name ?? 'Unknown'));
                }
            }

            // Buat Stocktransaction baru
            $stock = new Stocktransaction;
            $stock->staff = $request->staff;
            $stock->description = $request->desc;
            $stock->date = date("Y-m-d", strtotime($request->date));
            $stock->total = 0;
            $stock->nonmoney = 'out';
            $stock->production_id = $production->id;
            $stock->save();

            // Update status ke in_progress jika masih draft
            if ($production->status === 'draft') {
                $production->status = 'in_progress';
                $production->date_process = date("Y-m-d", strtotime($request->date));
            }
            $production->save();

            // Proses setiap item stock
            foreach ($request->stock as $item) {
                $totalhpp = 0;
                $substocktransactions_ids = [];

                // Buat Substocktransaction
                $sub = new Substocktransaction;
                $sub->stocktransaction_id = $stock->id;
                $sub->product_id = $item['product_id'];
                $sub->qty = $item['qty'];
                $sub->multi_unit = $item['multi_unit'] == 'none' ? null : $item['multi_unit'];
                $sub->qty_unit = $item['qty_unit'];
                $sub->save();

                // Kurangi qty produk
                $product = Product::find($sub->product_id);
                $product->qty = ($product->qty ?? 0) - $sub->qty;
                $product->save();

                // Hitung HPP menggunakan FIFO
                $qty = $sub->qty;
                $subin = Substocktransaction::where('left', '>', 0)
                    ->whereHas('stocktransaction', function ($query) {
                        $query->whereNull('pending');
                    })
                    ->where('product_id', '=', $sub->product_id)
                    ->orderBy('id', 'asc')
                    ->get();

                foreach ($subin as $value) {
                    $substocktransactions_ids[] = $value->id;
                    if ($qty <= $value->left) {
                        $set = $value->left - $qty;
                        $sibin = Substocktransaction::find($value->id);
                        $sibin->left = $set;
                        $sibin->save();
                        $totalhpp += ($value->purchase_price * $qty);
                        $qty = 0;
                        break;
                    } else {
                        $set = 0;
                        $qty -= $value->left;
                        $totalhpp += ($value->purchase_price * $value->left);
                        $sibin = Substocktransaction::find($value->id);
                        $sibin->left = $set;
                        $sibin->save();
                    }
                }

                // Update HPP dan substocktransactions_ids
                $sibin = Substocktransaction::find($sub->id);
                $sibin->hpp = $totalhpp;
                $sibin->substocktransactions_ids = join(",", $substocktransactions_ids);
                $sibin->save();
            }

            DB::commit();
            return response([
                'success' => true,
                'message' => 'Stock berhasil ditambahkan',
                'production' => $production->load(['product.unit', 'multiunit.multi_unit', 'stocktransactionOut']),
                'stocktransaction' => $stock->load('substocktransaction.product'),
            ], 200);
        } catch (\Throwable $e) {
            DB::rollBack();
            return response([
                'success' => false,
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function addCosts(Request $request, $id)
    {
        $request->validate([
            'staff' => ['nullable', 'string'],
            'desc' => ['nullable', 'string'],
            'date' => ['nullable', 'date'],
            'costs' => ['required', 'array', 'min:1'],
            'costs.*.akun_cost' => ['required', 'integer', 'exists:akuns,id'],
            'costs.*.total' => ['required', 'numeric'],
            'costs.*.desc' => ['nullable', 'string'],
        ]);

        DB::beginTransaction();
        try {
            $production = Production::findOrFail($id);

            // Update status ke in_progress jika masih draft
            if ($production->status === 'draft') {
                $production->status = 'in_progress';
                $production->date_process = $request->date ? date("Y-m-d", strtotime($request->date)) : null;
                $production->save();
            }

            $createdCosts = [];
            foreach ($request->costs as $cost) {
                $cost_category = $cost['cost_category'] ?? null;
                if (!$cost_category && !empty($cost['akun_cost'])) {
                    $akunTenagaKerja = Akun::where('name', 'biaya_tenaga_kerja_langsung_dibebankan')->first();
                    $laborId = $akunTenagaKerja ? (int)$akunTenagaKerja->id : null;
                    $costAkunId = (int)$cost['akun_cost'];
                    $cost_category = ($laborId && $costAkunId === $laborId) ? 'labor' : 'overhead';
                }

                $pc = new ProductionCost;
                $pc->production_id = $production->id;
                $pc->cashtransaction_id = null;
                $pc->cost_category = $cost_category;
                $pc->total = $cost['total'];
                $pc->save();

                $cash = new Cashtransaction;
                $cash->staff = $request->staff;
                $cash->desc = $cost['desc'] ?? $request->desc;
                $cash->date = date("Y-m-d", strtotime($request->date));
                $cash->transaction_category = 'biaya_produksi_dibebankan';
                $cash->save();

                $sub = new Subcashtransaction;
                $sub->cashtransaction_id = $cash->id;
                $sub->akun_id = $cost['akun_cost'] ?? null;
                $sub->total = $pc->total;
                $sub->desc = $pc->cost_type; // Note: cost_type might be null if not passed, assuming it might be handled or not needed based on existing store logic
                $sub->save();

                $cash = Cashtransaction::find($cash->id);
                $cash->total = $pc->total;
                $cash->save();

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

                $createdCosts[] = $pc;
            }

            DB::commit();
            return response([
                'success' => true,
                'message' => 'Biaya berhasil ditambahkan',
                'production' => $production->load(['product.unit', 'multiunit.multi_unit', 'costs.cashtransaction.from']),
                'costs' => $createdCosts,
            ], 200);
        } catch (\Throwable $e) {
            DB::rollBack();
            return response([
                'success' => false,
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function completedProduction(Request $request, $id)
    {
        $request->validate([
            'product_qty' => ['required', 'numeric'],
            'product_unit' => 'required',
            'date_out' => ['required', 'date'],
            'desc' => ['nullable', 'string'],
            'staff' => ['nullable', 'string']
        ]);

        $production = Production::find($id);
        if (!$production) {
            return response([
                'success' => false,
                'message' => 'not found',
            ], 404);
        }

        DB::beginTransaction();
        try {
            $productioncosts = ProductionCost::where('production_id', $production->id)->get();
            $multiunit = null;
            $qty = $request->product_qty;
            if ($request->product_unit != 'none') {
                $multiunit = MultiUnit::find($request->product_unit);
                $qty = $request->product_qty * $multiunit->multi_qty;
            }

            $stock = new Stocktransaction;
            $stock->staff = $request->staff;
            $stock->date = date("Y-m-d", strtotime($request->date_out));
            $stock->production_id = $production->id;
            $stock->description = $request->desc;
            $stock->nonmoney = 'in';
            $stock->save();

            $sub = new Substocktransaction;
            $sub->stocktransaction_id = $stock->id;
            $sub->product_id = $production->product_id;
            $sub->qty = $qty;
            $sub->left = $qty;
            $sub->multi_unit = $request->product_unit != 'none' ? $request->product_unit : null;
            $sub->qty_unit = $request->product_qty;
            $sub->save();

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

            $materials = Stocktransaction::where('production_id', $production->id)
                ->pluck('id');

            $subs = Substocktransaction::whereIn('stocktransaction_id', $materials)
                ->get()
                ->groupBy('stocktransaction_id');

            $total = $subs->flatten()->sum('hpp');

            $pc = new ProductionCost;
            $pc->production_id = $production->id;
            $pc->cashtransaction_id = null;
            $pc->total = $total;
            $pc->save();

            $total_production = $total + $productioncosts->sum('total');
            $purchase_price = $total_production / $qty;

            $stock = Stocktransaction::find($stock->id);
            $stock->total = $total_production;
            $stock->save();

            $sub->purchase_price = $purchase_price;
            $sub->total = $total_production;
            $sub->save();

            $production->stocktransaction_id_out = $stock->id;
            $production->product_qty = $request->product_qty;
            $production->product_unit = $request->product_unit != 'none' ? $request->product_unit : null;
            $production->status = 'completed';
            $production->date_out = $request->date_out ? date("Y-m-d", strtotime($request->date_out)) : null;
            $production->save();

            DB::commit();

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

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

            return response()->json([
                'status' => 'error',
                'message' => 'Terjadi kesalahan saat memproses data: ' . $e->getMessage()
            ], 500);
        }
    }

    public function deleteProduction($id)
    {
        DB::beginTransaction();
        try {
            $production = Production::find($id);
            if (!$production) {
                return response([
                    'success' => false,
                    'message' => 'not found',
                ], 404);
            }

            $stocks = Stocktransaction::where('production_id', $production->id)->get();

            foreach ($stocks as $stock) {
                $subs = Substocktransaction::where('stocktransaction_id', $stock->id)->get();

                foreach ($subs as $sub) {
                    $usedIn = Substocktransaction::where(function ($query) use ($sub) {
                        $query->where('substocktransactions_ids', 'LIKE', $sub->id . ',%')
                            ->orWhere('substocktransactions_ids', 'LIKE', '%,' . $sub->id . ',%')
                            ->orWhere('substocktransactions_ids', 'LIKE', '%,' . $sub->id)
                            ->orWhere('substocktransactions_ids', '=', $sub->id);
                    })->first();

                    if ($usedIn) {
                        $relatedStock = Stocktransaction::find($usedIn->stocktransaction_id);
                        throw new \Exception("Produk dalam transaksi ini telah dikeluarkan dalam PENJUALAN / KOREKSI STOK - KURANGI STOK dengan nomor transaksi: " . ($relatedStock ? $relatedStock->id : ''));
                    }
                }

                if ($stock->nonmoney === 'out') {
                    foreach ($subs as $sub) {
                        $product = Product::find($sub->product_id);
                        if ($product) {
                            $product->qty = ($product->qty ?? 0) + $sub->qty;
                            $product->save();
                        }

                        if (!empty($sub->substocktransactions_ids)) {
                            $qty = $sub->qty;
                            $subin = explode(",", $sub->substocktransactions_ids);
                            foreach ($subin as $subinId) {
                                $subinId = trim($subinId);
                                if ($subinId === '') {
                                    continue;
                                }
                                $sibin = Substocktransaction::find($subinId);
                                if (!$sibin) {
                                    continue;
                                }

                                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();
                                }
                            }
                        }
                    }
                } elseif ($stock->nonmoney === 'in') {
                    foreach ($subs as $sub) {
                        $product = Product::find($sub->product_id);
                        if ($product) {
                            $product->qty = ($product->qty ?? 0) - $sub->qty;
                            if ($product->qty < 0) {
                                $product->qty = 0;
                            }
                            $product->save();
                        }
                    }
                }

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

            $costs = ProductionCost::where('production_id', $production->id)->get();
            foreach ($costs as $cost) {
                if ($cost->cashtransaction_id) {
                    $cash = Cashtransaction::find($cost->cashtransaction_id);
                    if ($cash) {
                        Subcashtransaction::where('cashtransaction_id', $cash->id)->delete();
                        CreditCashTransaction::where('cashtransaction_id', $cash->id)->delete();
                        $cash->delete();
                    }
                }
                $cost->delete();
            }

            $production->delete();

            DB::commit();
            return response([
                'success' => true,
                'message' => 'production deleted',
            ], 200);
        } catch (\Throwable $e) {
            DB::rollBack();
            return response([
                'success' => false,
                'message' => $e->getMessage(),
            ], 500);
        }
    }
}
