<?php
namespace App\Http\Controllers\V1;

use App\Http\Controllers\Controller;

use App\Models\CustomerVendor;
use App\Models\EmployeeDetails;
use App\Models\Machines;
use App\Models\Process;
use App\Models\ProductType;
use App\Models\RouteCard;
use App\Models\RouteCardProcess;
use App\Models\SalesOrder;

use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;

class RouteCardController extends Controller
{
    /**
     * Display a listing of the resource.
     */
    public function index(Request $request)
    {

        $nextRouteNo  = nextNumber('UEPL/RC', 'route_cards', 'route_no');
        $saleOrders   = SalesOrder::with(['customer'])->get();
        $productTypes = ProductType::all();
        $routeCardId  = $request->input('route_card_id');
        $saleOrder    = null;
        if (isset($request->sale_order_id)) {
            $saleOrder = SalesOrder::find($request->sale_order_id);
            $routeCard = RouteCard::with(['processes', 'salesOrder'])->where([
                'order_no' => $saleOrder->sales_order_no,
            ])->first();
            if (! empty($routeCard)) {$routeCardId = $routeCard->id;}
        }

        $routeCardProcesses   = [];
        $routeCard            = null;
        $lastRouteCardProcess = null;
        if ($routeCardId) {
            if (empty($routeCard)) {
                $routeCard = RouteCard::with(['processes', 'salesOrder'])->find($routeCardId);
                request()->merge(['route_card' => $routeCard]);
            }
            $routeCardProcesses = RouteCardProcess::with([
                'previousProcess', 'attchedProcess',
                'attchedMachine', 'attchedOperator',
            ])
                ->where('route_card_id', $routeCardId)
                ->get();
            $lastRouteCardProcess = collect($routeCardProcesses->toArray())->last();
            if ($routeCard) {
                $customer = $routeCard->salesOrder ? $routeCard->salesOrder->customer : null;
                if ($customer) {
                    $routeCard->company_name = $customer->company;
                }
            }
        }

        $processesQuery = Process::with(['productType', 'machines']);
        if (! empty($routeCard)) {
            $productType = ProductType::where('name', $routeCard->product_type)->first();
            $processesQuery->where('product_type_id', $productType->id);
        }
        $processesQuery->has('machines', '>', 0);
        $processes = $processesQuery->get();

        $processIds = $processes->pluck('id');

        $machines = Machines::with(['operators', 'operators.routeCardProcesses', 'processes'])
            ->whereHas('operators') // Ensures machine has at least one operator
            ->whereIn('id', function ($query) use ($processIds) {
                $query->select('machine_id')
                    ->from('process_machine')
                    ->whereIn('process_id', $processIds);
            })
            ->get();

        return view('superadmin.routecard.routecardorder', compact(
            'processes', 'machines', 'nextRouteNo', 'saleOrders',
            'productTypes', 'routeCardId', 'routeCardProcesses',
            'routeCard', 'lastRouteCardProcess', 'saleOrder'
        ));
    }

    public function ganttChart(Request $request)
    {
        $companies = CustomerVendor::where('company_role', 'Customer')->get();
        $machines = Machines::all();
        $operators = EmployeeDetails::all();
        $routeCards = RouteCard::with(['processes', 'salesOrder'])->get();

        return view('v1.manufacturing.ganttchart', compact(
            'companies', 'machines', 'operators', 'routeCards'
        ));
    }

    /**
     * Store a newly created resource in storage.
     */
    public function store(Request $request)
    {
        $data = $request->validate([
            'route_no'           => 'required|string|max:255',
            'route_date'         => 'required|date',
            'order_no'           => 'required|exists:sales_orders,sales_order_no',
            'product_type'       => 'required|exists:product_types,name',
            'project_start_date' => 'required|date',
        ]);
        $routeCard = RouteCard::create($request->all());
        return redirect()->route('superadmin.routecard.index', ['route_card_id' => $routeCard->id])
            ->with('success', 'Route Card created successfully.');
    }

    public function processCreate(Request $request)
    {
        $request->validate([
            'route_card_id'       => 'required|exists:route_cards,id',
            'process'             => 'required|exists:processes,id',
            'machine'             => 'nullable|exists:machines,id',
            'operator'            => 'nullable|exists:employees,id',
            'previous_process_id' => 'nullable|exists:route_card_processes,id',
            'start_date'          => 'required|date',
            'end_date'            => 'required|date|after_or_equal:start_date',
            'cycle_hours'         => 'required|integer|min:0',
            'cycle_minutes'       => 'required|integer|min:0|max:59',
            'source'              => 'required|string|in:inhouse,outsourced',
            'description'         => 'nullable|string',
        ]);
        $data            = $request->except(["_token"]);
        $process         = Process::find($request->process);
        $data['process'] = $process->name;

        $routeCard = RouteCard::findOrFail($request->route_card_id);

        request()->merge(['route_card' => $routeCard]);

        $machine = null;
        if ($request->machine) {
            $machine = Machines::find($request->machine);
        }

        $operator = null;
        if ($request->operator) {
            $operator = EmployeeDetails::find($request->operator);
        }

        $ret = RouteCardProcess::create($data);

        $firstProcess = RouteCardProcess::where('route_card_id', $request->route_card_id)
            ->orderBy('start_date', 'asc')
            ->first();
        $firstProcessStart = Carbon::parse($firstProcess->start_date);

        $delayedStart = $firstProcessStart;

        if ($routeCard->project_start_date != $delayedStart) {
            $routeCard->project_start_date = $delayedStart;
            $routeCard->save();
        }

        return redirect()->route('superadmin.routecard.index', ['route_card_id' => $request->route_card_id])
            ->with('success', 'Route Card created successfully.');
    }

    public function processDelete(Request $request, $id)
    {
        $routeCard = RouteCardProcess::findOrFail($id);
        $routeCard->delete();
        return redirect()->route('superadmin.routecard.index', ['route_card_id' => $request->route_card_id])
            ->with('success', 'Route Card Process deleted successfully.');
    }

    /**
     * Update the specified resource in storage.
     */
    public function update(Request $request, $id)
    {
        $routeCard = RouteCard::findOrFail($id);
        $request->validate([
            'route_no'           => 'required|string|max:255',
            'route_date'         => 'required|date',
            'order_no'           => 'required|exists:sales_orders,sales_order_no',
            'product_type'       => 'required|exists:product_types,name',
            'project_start_date' => 'required|date',
        ]);
        $data = $request->except(['_token', '_method']);
        $routeCard->update($data);
        return redirect()->route('superadmin.routecard.index', ['route_card_id' => $id])
            ->with('success', 'Route Card updated successfully.');
    }

    /**
     * Display the specified resource.
     */
    public function show($id)
    {
        $routeCard = RouteCard::with(['processes', 'salesOrder'])
            ->findOrFail($id);
        $routeCardProcesses = RouteCardProcess::with([
                'previousProcess', 'attchedProcess',
                'attchedMachine', 'attchedOperator',
            ])
            ->where('route_card_id', $id)
            ->get();
        return view('superadmin.routecard.show', compact(
            'routeCard', 'routeCardProcesses'
        ));
    }
    /**
     * Show the form for editing the specified resource.
     */
    public function edit($id)
    {
        $card = RouteCard::with(['processes', 'salesOrder'])
            ->findOrFail($id);
        $routeCardProcesses = RouteCardProcess::with([
                'previousProcess', 'attchedProcess',
                'attchedMachine', 'attchedOperator',
            ])
            ->where('route_card_id', $id)
            ->get();

        $machines     = Machines::with(['operators'])->get();
        $employees    = EmployeeDetails::all();
        $companies    = CustomerVendor::all();
        $processes    = Process::with(['productType', 'machines'])->get();
        $saleOrders   = SalesOrder::with(['customer'])->get();
        $productTypes = ProductType::all();

        // Machine and Operator availability
        $now = Carbon::now();
        $machineAvailability = [];
        foreach ($machines as $machine) {
            $maxEndDate = \DB::table('route_card_processes')
                ->where('machine', $machine->machine_id)
                ->max('end_date');
            if ($maxEndDate && Carbon::parse($maxEndDate)->gt($now)) {
                $machineAvailability[$machine->machine_id] = 'Available from: ' . Carbon::parse($maxEndDate)->format('d-m-Y H:i');
            } else {
                $machineAvailability[$machine->machine_id] = 'Available now';
            }
        }

        $operatorAvailability = [];
        foreach ($employees as $emp) {
            $maxEndDate = \DB::table('route_card_processes')
                ->where('operator', $emp->id)
                ->max('end_date');
            if ($maxEndDate && Carbon::parse($maxEndDate)->gt($now)) {
                $operatorAvailability[$emp->id] = 'Available from: ' . Carbon::parse($maxEndDate)->format('d-m-Y H:i');
            } else {
                $operatorAvailability[$emp->id] = 'Available now';
            }
        }

        // Process assignments
        $processAssignments = [];
        $allProcesses = Process::with(['machines', 'operators'])->get();
        foreach ($allProcesses as $process) {
            $key = $process->product_type_id . '|' . $process->name;
            $processAssignments[$key] = [
                'operators' => $process->operators->pluck('id')->map(fn($id) => (string)$id)->toArray(),
                'machines' => $process->machines->pluck('machine_id')->map(fn($id) => (string)$id)->toArray(),
            ];
        }

        // Product type name to ID mapping
        $productTypeNameToId = $productTypes->pluck('id', 'name')->toArray();

        return view('superadmin.routecard.edit', compact(
            'card', 'routeCardProcesses', 'machines', 'employees', 'companies',
            'processes', 'saleOrders', 'productTypes', 'machineAvailability',
            'operatorAvailability', 'processAssignments', 'productTypeNameToId'
        ));
    }

    /**
     * Remove the specified resource from storage.
     */
    public function destroy($id)
    {
        try {
            $routeCard = RouteCard::with('processes')->find($id);

            if (! $routeCard) {
                return response()->json([
                    'success' => false,
                    'message' => 'Route card not found',
                ], 404);
            }

            DB::beginTransaction();

            // Only delete processes if they exist
            if ($routeCard->processes->isNotEmpty()) {
                $routeCard->processes()->delete();
            }

            $routeCard->delete();
            DB::commit();

            return response()->json([
                'success' => true,
                'message' => 'Route card deleted successfully',
            ]);

        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json([
                'success' => false,
                'message' => $e->getMessage(),
            ], 500);
        }
    }
    /**
     * Display the route card details list.
     */
    public function details(Request $request)
    {
        $cards = RouteCard::with('processes')->latest()->get();
        return view('superadmin.routecard.routecarddetails', compact('cards'));
    }

    /**
     * Approve a route card
     */
    public function approve($id)
    {
        $routeCard = RouteCard::findOrFail($id);

        $routeCard->update([
            'status'      => 'approved',
            'approved_by' => auth()->user()->name,
            'approved_at' => now(),
        ]);

        return response()->json([
            'success' => true,
            'message' => 'Route card approved successfully',
        ]);
    }

/**
 * Reject a route card
 */
    public function reject($id, Request $request)
    {
        $request->validate(['reason' => 'required|string']);

        $routeCard = RouteCard::findOrFail($id);

        $routeCard->update([
            'status'           => 'rejected',
            'rejected_by'      => auth()->user()->name,
            'rejected_at'      => now(),
            'rejection_reason' => $request->reason,
        ]);

        return response()->json([
            'success' => true,
            'message' => 'Route card rejected successfully',
        ]);
    }

    public function checkStatus($id)
    {
        $routeCard = RouteCard::findOrFail($id);

        return response()->json([
            'status'      => $routeCard->status,
            'approved_at' => $routeCard->approved_at,
            'approved_by' => $routeCard->approved_by,
        ]);
    }
}
