<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Auth;
use Carbon\Carbon;
use App\Models\DeleteLog;
use App\Models\Formula;
use App\Models\FormulaDetail;
use App\Models\Warehouse;
use App\Models\Company;
use App\Models\Item;
use App\Models\ItemDetail;
use App\Models\Department;
use App\Models\ProductionWorkOrder;
use App\Models\ProductionWorkOrderDetail;
use App\Models\ProductionWorkOrderMaterial;


class ProductionWorkOrderController extends Controller
{
    public function index($dateStart,$dateEnd): JsonResponse
    {
        try {
            $result = DB::table("production_work_order as x")
            ->join("production_work_order_details as y","x.id","=","y.production_work_order_id")
            ->join("items as i","i.id","=","y.item_id")
            ->join("item_units as iu","iu.id","=","y.unit_id")
            ->join("formulas as f","f.id","=","y.formula_id")
            ->join("warehouse as w","w.id","=","y.warehouse_id")
            ->select("x.id","x.production_work_order_number","x.document_date","x.status","i.item_code","i.item_name","iu.unit_name","y.qty","w.warehouse_name","f.formula_name")
            ->whereBetween("document_date",[$dateStart,$dateEnd])->get();
            return response()->json(["spk" => $result, "role" => $this->getRole()]);
        } catch (\Exception $e) {
            Log::error('Failed to fetch production plans', [
                'message' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
                'file' => $e->getFile(),
                'line' => $e->getLine(),
            ]);
            return response()->json(['error' => 'Failed to fetch production plans', 'details' => $e->getMessage()], 500);
        }
    }

    public function store(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'document_date' => 'required|date',
            'department_id' => 'required|exists:department,id',
            'details.*.item_id' => 'required|exists:items,id',
            'details.*.unit_id' => 'required|exists:item_units,id',
            'details.*.warehouse_id' => 'required|exists:warehouse,id',
            'details.*.formula_id' => 'required|exists:formulas,id',
            'details.*.qty' => 'required'
        ]);

        try {
            DB::beginTransaction();
            $company = Company::first();
            $department = Department::find($request->department_id);
            $date = Carbon::parse($request->document_date);
            $nobukti = Module::generateDocumentNumber($company->companyCode,$department->department_code,$date->month,$date->year,"SPK",1);
            $spk = ProductionWorkOrder::create([
                'production_work_order_number' => $nobukti,
                'status' => 'Pending',
                'document_date' => $request->document_date,
                'department_id' => $request->department_id,
                'created_by' => auth()->id(),
                'updated_by' => auth()->id(),
            ]);

            foreach ($request->details as $detail) {
                $itd = ItemDetail::where("item_id",$detail["item_id"])->where("unit_id",$detail["unit_id"])->first();
                $det = ProductionWorkOrderDetail::create([
                    'production_work_order_id' => $spk->id,
                    'item_id' => $detail["item_id"],
                    'unit_id' => $detail["unit_id"],
                    'qty' => $detail["qty"],
                    'qty_left' => $detail["qty"],
                    'base_qty' => $itd->conversion,
                    'formula_id' => $detail["formula_id"],
                    'warehouse_id' => $detail["warehouse_id"],
                ]);
                $mat = array_filter($request->materials, fn($m) => $m['detailId'] === $detail["tempId"]);
                foreach ($mat as $material) {
                    $itdMaterial = ItemDetail::where("item_id",$material["item_id"])->where("unit_id",$material["unit_id"])->first();
                    ProductionWorkOrderMaterial::create([
                        'production_work_order_id' => $spk->id,
                        'production_work_order_detail_id' => $det->id,
                        'item_id' => $material["item_id"],
                        'unit_id' => $material["unit_id"],
                        'formula_qty' => $material["formula_qty"],
                        'qty' => $material["qty"],
                        'qty_left' => $material["qty"],
                        'base_qty' => $itdMaterial->conversion,
                        'warehouse_id' => $detail["warehouse_id"],
                    ]);
                }
            }

            DB::commit();
            return response()->json(null, 201);
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json(['error' => 'Failed to create spk: ' . $e->getMessage()], 500);
        }
    }

    public function show($id)
    {
        try {
            $result = ProductionWorkOrder::with(['details','materials'])->findOrFail($id);
            return response()->json($result);
        } catch (\Exception $e) {
            Log::error('Failed to fetch spk', [
                'user' => Auth::user()->name,
                'production_work_order_id' => $id,
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);

            return response()->json([
                'error' => 'SPK not found',
                'message' => $e->getMessage()
            ], 404);
        }
    }
    public function update(Request $request, $plan_id): JsonResponse
    {
        $validated = $request->validate([
            'details.*.item_id' => 'required|exists:items,id',
            'details.*.unit_id' => 'required|exists:item_units,id',
            'details.*.warehouse_id' => 'required|exists:warehouse,id',
            'details.*.formula_id' => 'required|exists:formulas,id',
            'details.*.qty' => 'required'
        ]);

        try {
            DB::beginTransaction();
            $spk = ProductionWorkOrder::where('id', $plan_id)->firstOrFail();
            $spk->update([
                'updated_by' => auth()->id(),
            ]);
            
            ProductionWorkOrderMaterial::where('production_work_order_id', $plan_id)->delete();
            ProductionWorkOrderDetail::where('production_work_order_id', $plan_id)->delete();
            foreach ($request->details as $detail) {
                $itd = ItemDetail::where("item_id",$detail["item_id"])->where("unit_id",$detail["unit_id"])->first();
                $det = ProductionWorkOrderDetail::create([
                    'production_work_order_id' => $spk->id,
                    'item_id' => $detail["item_id"],
                    'unit_id' => $detail["unit_id"],
                    'qty' => $detail["qty"],
                    'qty_left' => $detail["qty"],
                    'base_qty' => $itd->conversion,
                    'formula_id' => $detail["formula_id"],
                    'warehouse_id' => $detail["warehouse_id"],
                ]);

                $mat = array_filter($request->materials, fn($m) => $m['detailId'] === $detail["tempId"]);
                foreach ($mat as $material) {
                    $itdMaterial = ItemDetail::where("item_id",$material["item_id"])->where("unit_id",$material["unit_id"])->first();
                    ProductionWorkOrderMaterial::create([
                        'production_work_order_id' => $spk->id,
                        'production_work_order_detail_id' => $det->id,
                        'item_id' => $material["item_id"],
                        'unit_id' => $material["unit_id"],
                        'formula_qty' => $material["formula_qty"],
                        'qty' => $material["qty"],
                        'qty_left' => $material["qty"],
                        'base_qty' => $itdMaterial->conversion,
                        'warehouse_id' => $detail["warehouse_id"],
                    ]);
                }
            }

            DB::commit();
            return response()->json(null);
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json(['error' => 'Failed to update spk: ' . $e->getMessage()], 500);
        }
    }

    public function destroy(Request $request,$plan_id): JsonResponse
    {
        try {
            DB::beginTransaction();
            $plan = ProductionWorkOrder::find($plan_id);            
            $plan->materials()->delete();
            $plan->details()->delete();
            $plan->delete();

            DeleteLog::create([
                'document_number' => $plan->production_work_order_number,
                'document_date' => now(),
                'delete_notes' => $request->delete_notes ?? 'No notes provided',
                'company_code' => null,
                'department_code' => null,
                'deleted_by' => Auth::check() ? Auth::user()->name : 'system',
                'type' => 'Production Plan',
            ]);
            DB::commit();
            return response()->json(null, 204);
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('Failed to delete production plans', [
                'message' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
                'file' => $e->getFile(),
                'line' => $e->getLine(),
            ]);
            return response()->json(['error' => 'Failed to delete production plan'], 500);
        }
    }

    public function getMasterData(): JsonResponse
    {
        try {
            $Listdepartment = $this->getDepartment();
            $company = Company::first();
            $date = Carbon::now();
            $nobukti = Module::generateDocumentNumber($company->companyCode, Department::first()->department_code, $date->month, $date->year, "SPK", 0);
            $data = [
                'items' => Item::with(['itemDetails.unit'])->orderBy('id')->get(),
                'formula' => Formula::with('formulaDetails')->get(),
                'warehouse' => Warehouse::get(),
                'departments' => Department::whereIn("id",$Listdepartment)->orderBy('id')->get(),
                'nobukti' => $nobukti,
                'role' => $this->getRole()
            ];
            return response()->json($data);
        } catch (\Exception $e) {
            Log::error('Master data fetch error: ' . $e->getMessage());
            return response()->json(['error' => 'Failed to fetch master data'], 500);
        }
    }

    public function getNomorBukti(Request $request)
    {
        $request->validate([
            'department_id' => 'required|exists:department,id',
            'document_date' => 'required|date',
        ]);

        try {
            $company = Company::select('companyCode')->first();
            $department = Department::findOrFail($request->department_id);
            $date = Carbon::parse($request->document_date);
            $nobukti = Module::generateDocumentNumber($company->companyCode, $department->department_code, $date->month, $date->year, "SPK", 0);
            return response()->json($nobukti, 200);
        } catch (\Exception $e) {
            Log::error('Error generating document number', [
                'error' => $e->getMessage(),
                'data' => $request->all(),
                'user' => Auth::user()->name ?? 'system',
                'trace' => $e->getTraceAsString()
            ]);
            return response()->json(['error' => $e->getMessage()], 500);
        }
    }
}
