<?php

namespace App\Http\Controllers\Modules\Manufacturing;

use App\Http\Controllers\Controller;
use App\Http\Traits\HasRoleViews;
use App\Models\ManufacturingPlan;
use App\Models\RouteCard;
use App\Models\RouteCardProcess;
use App\Models\EmployeeDetails;
use App\Models\Machines;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;

/**
 * Unified Manufacturing Planning Controller
 *
 * Handles manufacturing planning and Gantt chart functionality for all roles.
 * Reference: SuperAdminManufacturingPlanningController
 */
class ManufacturingPlanningController extends Controller
{
    use HasRoleViews;

    /**
     * Display the manufacturing planning list view
     */
    public function index()
    {
        return $this->roleView('manufacturing.planning');
    }

    /**
     * Get all manufacturing plans for DataTable (AJAX)
     */
    public function list(): JsonResponse
    {
        $plans = ManufacturingPlan::with(['routeCard.salesOrder', 'createdBy'])
            ->orderBy('created_at', 'desc')
            ->get();

        return datatables($plans)->make(true);
    }

    /**
     * Show the form for creating a new manufacturing plan
     */
    public function create()
    {
        $routeCards = RouteCard::with('salesOrder')
            ->where('status', 'approved')
            ->get();
        $operators = EmployeeDetails::pluck('name', 'id')->toArray();
        $machines = Machines::all();

        return $this->roleView('manufacturing.create', compact('routeCards', 'operators', 'machines'));
    }

    /**
     * Display a single manufacturing plan
     */
    public function show(int $id)
    {
        $plan = ManufacturingPlan::with(['routeCard.salesOrder', 'processes'])
            ->findOrFail($id);

        return $this->roleView('manufacturing.show', compact('plan'));
    }

    /**
     * Show the form for editing a manufacturing plan
     */
    public function edit(int $id)
    {
        $plan = ManufacturingPlan::with(['routeCard', 'processes'])->findOrFail($id);
        $routeCards = RouteCard::with('salesOrder')->get();
        $operators = EmployeeDetails::pluck('name', 'id')->toArray();
        $machines = Machines::all();

        return $this->roleView('manufacturing.edit', compact('plan', 'routeCards', 'operators', 'machines'));
    }

    /**
     * Display the planning page
     */
    public function planPage()
    {
        $operators = EmployeeDetails::pluck('name', 'id')->toArray();
        return $this->roleView('manufacturing.plan', compact('operators'));
    }

    /**
     * Display the planning page with route card details
     */
    public function planPageWithId(int $id)
    {
        $operators = EmployeeDetails::pluck('name', 'id')->toArray();
        $routeCard = RouteCard::with('processes')->findOrFail($id);

        // Machine & Operator Availability Logic
        $now = Carbon::now();
        $machines = Machines::all();
        $employees = EmployeeDetails::all();

        $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)) {
                $availDate = 'Available from: ' . Carbon::parse($maxEndDate)->format('d-m-Y H:i');
            } else {
                $availDate = 'Available now';
            }
            $machineAvailability[$machine->machine_id] = $availDate;
        }

        $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)) {
                $availDate = 'Available from: ' . Carbon::parse($maxEndDate)->format('d-m-Y H:i');
            } else {
                $availDate = 'Available now';
            }
            $operatorAvailability[$emp->id] = $availDate;
        }

        return $this->roleView('manufacturing.plan', compact(
            'operators',
            'routeCard',
            'id',
            'machineAvailability',
            'operatorAvailability'
        ));
    }

    /**
     * Get route card processes (AJAX)
     */
    public function rcProcesses(int $id): JsonResponse
    {
        $rc = RouteCard::with('processes')->findOrFail($id);
        return response()->json($rc);
    }

    /**
     * Store a new manufacturing plan
     */
    public function store(Request $request): JsonResponse
    {
        $data = $request->validate([
            'rc_id' => 'required|string',
            'company_name' => 'required|string',
            'status' => 'nullable|string',
            'rc_date' => 'nullable|date',
            'approved_by' => 'nullable|string',
            'plan_by' => 'nullable|string',
            'plan_date' => 'nullable|date',
            'machine' => 'nullable|string',
            'process' => 'nullable|string',
            'operator' => 'nullable|string',
            'ct_hours' => 'nullable|string',
            'ct_minutes' => 'nullable|string',
            'start_date' => 'nullable|date',
            'end_date' => 'nullable|date',
        ]);

        $plan = ManufacturingPlan::create($data);
        return response()->json($plan, 201);
    }

    /**
     * Update a route card process
     */
    public function updateProcess(Request $request, int $id): JsonResponse
    {
        $process = RouteCardProcess::findOrFail($id);

        $data = $request->validate([
            'description' => 'nullable|string',
            'start_date' => 'nullable|date',
            'end_date' => 'nullable|date',
            'operator' => 'nullable|string',
            'machine' => 'nullable|string',
            'process' => 'nullable|string',
            'cycle_hours' => 'nullable|integer',
            'cycle_minutes' => 'nullable|integer',
            'source' => 'nullable|string',
            'previous_process' => 'nullable|string',
        ]);

        $process->update($data);
        return response()->json(['success' => true, 'process' => $process]);
    }

    /**
     * Delete a manufacturing plan
     */
    public function destroy(int $id): JsonResponse
    {
        // Authorization check - only SuperAdmin and Manager can delete
        if (!$this->isSuperAdmin() && !$this->isManager()) {
            return response()->json([
                'success' => false,
                'message' => 'Unauthorized. Only SuperAdmin and Manager can delete manufacturing plans.'
            ], 403);
        }

        $plan = ManufacturingPlan::findOrFail($id);
        $plan->delete();
        return response()->json(['success' => true, 'message' => 'Manufacturing plan deleted successfully.']);
    }

    /**
     * Display the Gantt chart page
     */
    public function ganttPage()
    {
        return $this->roleView('manufacturing.gantt');
    }

    /**
     * Get Gantt chart data (AJAX)
     */
    public function ganttData(Request $request): JsonResponse
    {
        $query = RouteCard::with(['processes' => function ($q) {
            $q->orderBy('start_date');
        }]);

        if ($request->has('status') && $request->status != 'all') {
            $query->where('status', $request->status);
        }

        $cards = $query->orderBy('project_start_date')->get();

        $tasks = [];
        foreach ($cards as $rc) {
            // Calculate Project End
            $projectEnd = $rc->route_date;
            if ($rc->processes->count() > 0) {
                $maxEnd = $rc->processes->max('end_date');
                if ($maxEnd > $projectEnd) {
                    $projectEnd = $maxEnd;
                }
            }

            // Project Task
            $tasks[] = [
                'id' => 'rc-' . $rc->id,
                'name' => $rc->route_no,
                '_full_name' => $rc->route_no . ' - ' . $rc->company_name,
                'start' => $rc->project_start_date ?? date('Y-m-d'),
                'end' => $projectEnd ?? date('Y-m-d', strtotime('+1 day')),
                'progress' => 0,
                'custom_class' => 'gantt-project',
                'dependencies' => '',
            ];

            foreach ($rc->processes as $proc) {
                $dependencies = 'rc-' . $rc->id;
                if ($proc->previous_process_id) {
                    $dependencies .= ', p-' . $proc->previous_process_id;
                }

                // Ensure valid dates
                $start = $proc->start_date ? date('Y-m-d', strtotime($proc->start_date)) : date('Y-m-d');
                $end = $proc->end_date ? date('Y-m-d', strtotime($proc->end_date)) : $start;
                if ($end < $start) {
                    $end = $start;
                }

                $tasks[] = [
                    'id' => 'p-' . $proc->id,
                    'name' => $proc->process,
                    'description' => "Machine: {$proc->machine}, Operator: " . ($proc->operator ?? 'N/A'),
                    'start' => $start,
                    'end' => $end,
                    'progress' => ($proc->status == 'approved' || $proc->status == 'completed' ? 100 : ($proc->status == 'in_progress' ? 50 : 0)),
                    'dependencies' => $dependencies,
                    'custom_class' => 'gantt-process ' . ($proc->status == 'completed' || $proc->status == 'approved' ? 'is-completed' : ($proc->status == 'in_progress' ? 'is-running' : 'is-pending')),
                ];
            }
        }

        return response()->json($tasks);
    }
}
