<?php

namespace App\Http\Controllers;

use App\Models\Akun;
use App\Models\Cashtransaction;
use App\Models\Product;
use App\Models\StockTransactionSo;
use App\Models\Stocktransaction;
use App\Models\Subcashtransaction;
use App\Models\Substocktransaction;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class StockTransactionSoController extends Controller
{
    /**
     * Menampilkan semua data beserta relasi stocktransactions.
     */
    public function index(Request $request)
    {
        $data = StockTransactionSo::with('stocktransaction', 'signature');

        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->whereBetween('date', [$start_date, $end_date]);
        }
        $data = $data->get();

        $response = [
            'success' => true,
            'message' => 'Data retrieved successfully',
            'data' => $data,
        ];

        return response($response, 200);
    }

    /**
     * Menyimpan data baru menggunakan save().
     */
    public function store(Request $request)
    {
        $request->validate([
            'date' => 'required',
            'desc' => 'nullable|string',
            'staff' => 'required|string',
            'signature_id' => 'required',
            'product_id.*' => 'required',
            'qty.*'  => 'required',
            'actual_qty.*'  => 'required',
        ]);

        // Mulai database transaction
        DB::beginTransaction();

        try {
            $data = $request->product_id;

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

                if ($dataActualQty < $dataQty) {
                    if ($dataQty > $dataProduct->qty) {
                        // Rollback transaction jika ada masalah dengan stok
                        DB::rollback();
                        return response()->json([
                            'status' => 'error',
                            'message' => 'Mohon cek kembali untuk persediaan produk ini: ' . $dataProduct->name
                        ], 400);
                    }
                }
            }

            $so = new StockTransactionSo();
            $so->date = date("Y-m-d", strtotime($request->date));
            $so->desc = $request->desc;
            $so->staff = $request->staff;
            $so->signature_id = $request->signature_id;
            $so->save();

            $soout = [];
            $soin = [];
            foreach ($data as $key => $value) {
                $product = Product::findOrFail($value);
                if ($request->actual_qty[$key] > $request->qty[$key]) {
                    $soin[] = [
                        'product_id' => $value,
                        'actual_qty' => $request->actual_qty[$key],
                        'system_qty' => $request->qty[$key],
                        'qty' => $request->actual_qty[$key] - $request->qty[$key],
                        'price' => $product->purchase_price,
                        'type' => 'in'
                    ];
                } else if ($request->actual_qty[$key] < $request->qty[$key]) {
                    $soout[] = [
                        'product_id' => $value,
                        'actual_qty' => $request->actual_qty[$key],
                        'system_qty' => $request->qty[$key],
                        'qty' => $request->qty[$key] - $request->actual_qty[$key],
                        'price' => $product->selling_price,
                        'type' => 'out'
                    ];
                }
            }

            // Create stock transactions for stock in
            if (!empty($soin)) {
                $stockIn = new Stocktransaction;
                $stockIn->staff = $request->staff;
                $stockIn->date = date("Y-m-d", strtotime($request->date));
                $stockIn->description = $request->desc;
                $stockIn->nonmoney = 'in';
                $stockIn->is_so = true;
                $stockIn->so_id = $so->id;
                $stockIn->save();

                $cash = new Cashtransaction;
                $cash->staff = $request->staff;
                $cash->date = date("Y-m-d", strtotime($request->date));
                $cash->transaction_category = 'pendapatan_item_masuk';
                $cash->stocktransaction_id = $stockIn->id;
                $cash->cashout = 0;
                $cash->cashin = 0;
                $cash->transfer = 0;
                $cash->save();

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

                $total = 0;
                foreach ($soin as $item) {
                    $substockIn = new Substocktransaction;
                    $substockIn->stocktransaction_id = $stockIn->id;
                    $substockIn->product_id = $item['product_id'];
                    $substockIn->qty = $item['qty'];
                    $substockIn->purchase_price = $item['price'];
                    $substockIn->left = $item['qty'];
                    $substockIn->actual_qty = $item['actual_qty'];
                    $substockIn->system_qty = $item['system_qty'];
                    $substockIn->total = $item['qty'] * $item['price'];
                    $substockIn->save();

                    $product = Product::find($item['product_id']);
                    $product->qty = $product->qty + $substockIn->qty;
                    $product->save();

                    $total = $total + $item['qty'] * $item['price'];
                }

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

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

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

                $subCash = new Subcashtransaction;
                $subCash->cashtransaction_id = $cash->id;
                $subCash->akun_id = 43;
                $subCash->total = $total;
                $subCash->desc = $request->desc;
                $subCash->save();
            }

            // Create stock transactions for stock out
            if (!empty($soout)) {
                $stockOut = new Stocktransaction;
                $stockOut->staff = $request->staff;
                $stockOut->date = date("Y-m-d", strtotime($request->date));
                $stockOut->description = $request->desc;
                $stockOut->nonmoney = 'out';
                $stockOut->is_so = true;
                $stockOut->so_id = $so->id;
                $stockOut->save();

                $cash = new Cashtransaction;
                $cash->staff = $request->staff;
                $cash->date = date("Y-m-d", strtotime($request->date));
                $cash->transaction_category = 'biaya_item_keluar';
                $cash->stocktransaction_id = $stockOut->id;
                $cash->cashout = 0;
                $cash->cashin = 0;
                $cash->transfer = 0;
                $cash->save();

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

                $total = 0;
                $totalhpp = 0;
                $lasthb = 0;

                foreach ($soout as $item) {
                    $substockOut = new Substocktransaction();
                    $substockOut->stocktransaction_id = $stockOut->id;
                    $substockOut->product_id = $item['product_id'];
                    $substockOut->qty = $item['qty'];
                    $substockOut->actual_qty = $item['actual_qty'];
                    $substockOut->system_qty = $item['system_qty'];
                    $substockOut->save();

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

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

                    foreach ($subin as $key => $value) {
                        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($substockOut->id);
                    $sibin->hpp = $totalhpp;
                    $sibin->substocktransactions_ids = join(",", $substocktransactions_ids);
                    $sibin->save();
                    $totalhpp = 0;
                    $total = $total + $substockOut->total;
                }

                if ($qty > 0) {
                    $totalhpp = $totalhpp + ($lasthb * $qty);
                }

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

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

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

                $subCash = new Subcashtransaction;
                $subCash->cashtransaction_id = $cash->id;
                $subCash->akun_id = 31;
                $subCash->total = $sibin->hpp;
                $subCash->desc = $request->desc;
                $subCash->save();
            }

            // Commit transaction jika semua berhasil
            DB::commit();

            $response = [
                'success' => true,
                'message' => 'Data created successfully',
                'data' => $so,
            ];

            return response($response, 201);
        } catch (\Exception $e) {
            // Rollback transaction jika terjadi error
            DB::rollback();

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

    /**
     * Menampilkan satu data dengan relasi.
     */
    public function show($id)
    {
        $data = StockTransactionSo::with('stocktransaction', 'stocktransaction.substocktransaction', 'stocktransaction.substocktransaction.product', 'signature')->findOrFail($id);

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

    /**
     * Mengupdate data menggunakan save().
     */
    public function update(Request $request, $id)
    {
        // 
    }

    /**
     * Menghapus data.
     */
    public function destroy($id)
    {
        try {
            $response = DB::transaction(function () use ($id) {
                $so = StockTransactionSo::findOrFail($id);

                // Cek apakah produk terkait sudah dipakai di transaksi keluar lainnya
                $substockUsed = Stocktransaction::where('so_id', $so->id)
                    ->with('substocktransaction')
                    ->get()
                    ->flatMap(function ($stockTrans) {
                        return $stockTrans->substocktransaction->flatMap(function ($subTrans) {
                            return Substocktransaction::where('substocktransactions_ids', 'LIKE', '%' . $subTrans->id . '%')->get();
                        });
                    });

                $firstUsed = $substockUsed->first();
                if ($firstUsed) {
                    $usedTransaction = Stocktransaction::find($firstUsed->stocktransaction_id);
                    $usedSoId = $usedTransaction?->so_id;

                    return [
                        'success' => false,
                        'message' => $usedSoId
                            ? "Produk dalam transaksi ini telah digunakan dalam STOK OPNAME dengan nomor transaksi: {$usedSoId}. Silakan hapus transaksi tersebut terlebih dahulu."
                            : "Produk dalam transaksi ini telah digunakan dalam PENJUALAN / KOREKSI STOK - KURANGI STOK dengan nomor transaksi: {$firstUsed->stocktransaction_id}. Silakan hapus transaksi tersebut terlebih dahulu.",
                        'status' => 400,
                    ];
                }

                // Ambil seluruh transaksi stok yang berkaitan
                $stockTransactions = Stocktransaction::where('so_id', $so->id)->get();
                $stockTransactionIds = $stockTransactions->pluck('id');

                if ($stockTransactionIds->isNotEmpty()) {
                    $subTransactions = Substocktransaction::whereIn('stocktransaction_id', $stockTransactionIds)->get();

                    foreach ($subTransactions as $sub) {
                        $product = Product::find($sub->product_id);
                        if ($product) {
                            $stock = Stocktransaction::find($sub->stocktransaction_id);
                            if ($stock->nonmoney == "out") {
                                $product->qty += $sub->qty;
                                $product->save();
                            }
                            if ($stock->nonmoney == "in") {
                                $product->qty -= $sub->qty;
                                $product->save();
                            }
                        }

                        $sub->delete();
                    }

                    // Hapus semua transaksi kas dan subkas terkait
                    $cashTransactionIds = Cashtransaction::whereIn('stocktransaction_id', $stockTransactionIds)->pluck('id');
                    if ($cashTransactionIds->isNotEmpty()) {
                        Subcashtransaction::whereIn('cashtransaction_id', $cashTransactionIds)->delete();
                        Cashtransaction::whereIn('id', $cashTransactionIds)->delete();
                    }

                    // Hapus transaksi stok dan substok
                    Substocktransaction::whereIn('stocktransaction_id', $stockTransactionIds)->delete();
                    Stocktransaction::whereIn('id', $stockTransactionIds)->delete();
                }

                // Hapus header transaksi
                $so->delete();

                return [
                    'success' => true,
                    'message' => 'Data berhasil dihapus.',
                    'status' => 200,
                ];
            });

            return response($response, $response['status']);
        } catch (\Exception $e) {
            return response([
                'success' => false,
                'message' => 'Terjadi kesalahan saat menghapus data.',
            ], 500);
        }
    }
}
