<?php

namespace App\Http\Controllers\Modules\MasterData;

use App\Http\Controllers\Controller;
use App\Http\Traits\HasRoleViews;
use App\Models\Machines;
use App\Services\MasterData\MachineService;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator;
use PhpOffice\PhpSpreadsheet\IOFactory;

/**
 * Unified Machine Controller
 *
 * Handles machine management for all roles.
 * Views are automatically resolved based on the logged-in user's role.
 */

class MachineController extends Controller
{
    use HasRoleViews;

    protected MachineService $machineService;

    public function __construct(MachineService $machineService)
    {
        $this->machineService = $machineService;
    }

    /**
     * Display the add machine form
     */
    public function create()
    {
        return $this->roleView('machine.addmachine');
    }

    /**
     * Alias for create - backward compatibility
     */
    public function addMachine()
    {
        return $this->create();
    }

    /**
     * Display the machine list page
     */
    public function index()
    {
        $machines = $this->machineService->getAll();
        return $this->roleView('machine.machinedetails', compact('machines'));
    }

    /**
     * Alias for index - backward compatibility
     */
    public function machineDetails()
    {
        return $this->index();
    }

    /**
     * Store a newly created machine
     */
    public function storeMachine(Request $request)
    {
        $validated = $request->validate([
            'machine_id' => 'required|unique:machines,machine_id,NULL,id,deleted_at,NULL', 
            'machine_name' => 'nullable|string|max:255',
            'machine_sl_no' => 'nullable|string|max:255',
            'make' => 'nullable|string|max:255',
            'model_type' => 'nullable|string|max:255',
            'diameter' => 'nullable|numeric',
            'length' => 'nullable|numeric',
            'weight' => 'nullable|numeric',
            'remarks' => 'nullable|string',
        ]);
        $this->machineService->create($validated);

        return $this->redirectToRoute('machine.machinedetails')
            ->with('success', 'Machine added successfully.');
    }

    /**
     * Display the edit machine form
     */
    public function edit(int $id)
    {
        $machine = $this->machineService->findById($id);

        if (!$machine) {
            return $this->redirectToRoute('machine.machinedetails')
                ->with('error', 'Machine not found.');
        }

        return $this->roleView('machine.editmachine', compact('machine'));
    }

    /**
     * Alias for edit - backward compatibility
     */
    public function editMachine(int $id)
    {
        return $this->edit($id);
    }

    /**
     * Update the specified machine
     */
    public function updateMachine(Request $request, int $id)
    {
        $machine = $this->machineService->findById($id);

        if (!$machine) {
            return $this->redirectToRoute('machine.machinedetails')
                ->with('error', 'Machine not found.');
        }

        $validated = $request->validate([
            'machine_id' => 'required|unique:machines,machine_id,NULL,id,deleted_at,NULL',
            'machine_name' => 'nullable|string|max:255',
            'machine_sl_no' => 'nullable|string|max:255',
            'make' => 'nullable|string|max:255',
            'model_type' => 'nullable|string|max:255',
            'diameter' => 'nullable|numeric',
            'length' => 'nullable|numeric',
            'weight' => 'nullable|numeric',
            'remarks' => 'nullable|string',
        ]);

        $this->machineService->update($id, $validated);

        return $this->redirectToRoute('machine.machinedetails')
            ->with('success', 'Machine updated successfully.');
    }

    /**
     * Remove the specified machine
     */
    public function deleteMachine(int $id): JsonResponse
    {
        $machine = $this->machineService->findById($id);

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

        $this->machineService->delete($id);

        return response()->json(['success' => true, 'message' => 'Machine deleted successfully']);
    }
 
     
    public function import(Request $request)
    {
        $request->validate([
            'excel_file' => 'required|file|mimes:xlsx',
        ]);

        $file = $request->file('excel_file');
        Log::info('Bulk machine import started by user.', [
            'user_id' => auth()->id(),
            'filename' => $file->getClientOriginalName(),
            'timestamp' => now()->toDateTimeString(),
        ]);

        try {
            $spreadsheet = IOFactory::load($file->getRealPath());
            $worksheet = $spreadsheet->getActiveSheet();
            $rows = $worksheet->toArray(null, true, true, true);

            $headerRow = array_map('strtolower', array_map('trim', array_values($rows[1])));
            $expectedHeaders = [
                'machine_id',
                'machine_name',
                'machine_sl_no',
                'make',
                'model_type',
                'diameter',
                'length',
                'weight',
                'remarks',
            ];

            if ($headerRow !== $expectedHeaders) {
                Log::error('Invalid template format detected during bulk import.', [
                    'provided_header' => $headerRow,
                    'expected_header' => $expectedHeaders,
                ]);
                return back()->with('error', 'Invalid template format. Please use the provided sample template.');
            }

            $successCount = 0;
            $errorCount = 0;
            $errorRows = [];

            DB::beginTransaction();

            foreach (array_slice($rows, 1) as $index => $row) {
                if ($index == 0) continue;

                $rowData = array_combine($expectedHeaders, array_map('trim', array_values($row)));

                $validator = Validator::make($rowData, [
                    'machine_id' => 'required|unique:machines,machine_id',
                    'machine_sl_no' => 'nullable',
                    'diameter' => 'nullable',
                    'length' => 'nullable',
                    'weight' => 'nullable',
                ]);

                if ($validator->fails()) {
                    $errorCount++;
                    $errorRows[] = "Row " . ($index + 1) . ": " . implode('; ', $validator->errors()->all());
                    Log::warning('Validation failed for machine import row.', [
                        'row_number' => $index + 1,
                        'errors' => $validator->errors()->all(),
                        'row_data' => $rowData,
                    ]);
                    continue;
                }

                try {
                    // Use service for consistent transaction handling and logging
                    $this->machineService->create($rowData);
                    $successCount++;
                } catch (\Exception $e) {
                    $errorCount++;
                    $errorRows[] = "Row " . ($index + 1) . ": " . $e->getMessage();
                    Log::error('Exception while importing machine row.', [
                        'row_number' => $index + 1,
                        'row_data' => $rowData,
                        'exception' => $e->getMessage(),
                    ]);
                }
            }

            DB::commit();

            Log::info('Bulk machine import completed.', [
                'user_id' => auth()->id(),
                'imported_count' => $successCount,
                'error_count' => $errorCount,
            ]);

            $message = "{$successCount} machines imported.";
            if ($errorCount > 0) {
                $message .= " {$errorCount} errors. See below.";
                return back()->with('success', $message)->with('errorRows', $errorRows);
            }

            return back()->with('success', $message);
        } catch (\Exception $e) {
            Log::critical('Bulk machine import failed with exception.', [
                'exception' => $e->getMessage(),
                'file' => $file->getClientOriginalName(),
                'user_id' => auth()->id(),
            ]);
            return back()->with('error', 'Failed to import: ' . $e->getMessage());
        }
    }

    public function importMachines(Request $request)
    {
        $request->validate([
            'excel_file' => 'required|file|mimes:xlsx',
        ]);

        $file = $request->file('excel_file');
        Log::info('Bulk machine import started by user.', [
            'user_id' => auth()->id(), 
            'filename' => $file->getClientOriginalName(),
            'timestamp' => now()->toDateTimeString()
        ]);

        try {
            $spreadsheet = IOFactory::load($file->getRealPath());
            $worksheet = $spreadsheet->getActiveSheet();
            $rows = $worksheet->toArray(null, true, true, true);

            // Assume first row is headers
            // Get header row values (ignore keys 'A','B',...) and re-index as numeric
            $headerRow = array_map('strtolower', array_map('trim', array_values($rows[1])));
            $expectedHeaders = [
                'machine_id',
                'machine_name',
                'machine_sl_no',
                'make',
                'model_type',
                'diameter',
                'length',
                'weight',
                'remarks'
            ];

            // Validate headers (strict check, order matters)
            if ($headerRow !== $expectedHeaders) {
                Log::error('Invalid template format detected during bulk import.', [
                    'provided_header' => $headerRow,
                    'expected_header' => $expectedHeaders
                ]);
                return back()->with('error', 'Invalid template format. Please use the provided sample template.');
            }

            $successCount = 0;
            $errorCount = 0;
            $duplicateCount = 0;
            $errorRows = [];

            DB::beginTransaction();

            foreach (array_slice($rows, 1, null, false) as $index => $row) {
                // if ($index == 0) continue;

                $rowData = array_combine($expectedHeaders, array_map('trim', array_values($row)));

                $validator = Validator::make($rowData, [
                    'machine_id'     => 'required|unique:machines,machine_id,NULL,id,deleted_at,NULL',
                    'machine_sl_no'  => 'nullable',
                    'diameter'       => 'nullable',
                    'length'         => 'nullable',
                    'weight'         => 'nullable',
                ]);

                if ($validator->fails()) {

                    if ($validator->errors()->has('machine_id')) {
                        $duplicateCount++;
                    } else {
                        $errorCount++;
                    }

                    $errorMsg = "Row " . ($index + 1) . ": " . implode('; ', $validator->errors()->all());
                    $errorRows[] = $errorMsg;

                    Log::warning('Validation failed for machine import row.', [
                        'row_number' => $index + 1,
                        'errors' => $validator->errors()->all(),
                        'row_data' => $rowData
                    ]);

                    continue;
                }

                try {
                    Machines::create($rowData);
                    $successCount++;
                } catch (\Exception $e) {
                    $errorCount++;
                    $errorMsg = "Row " . ($index + 1) . ": " . $e->getMessage();
                    $errorRows[] = $errorMsg;
                    Log::error('Exception while importing machine row.', [
                        'row_number' => $index + 1,
                        'row_data' => $rowData,
                        'exception' => $e->getMessage()
                    ]);
                }
            }

            DB::commit();

            Log::info('Bulk machine import completed.', [
                'user_id' => auth()->id(),
                'imported_count' => $successCount,
                'error_count' => $errorCount
            ]);

            $message = "{$successCount} machines imported.";

            if ($duplicateCount > 0) {
                $message .= " {$duplicateCount} already exists.";
            }

            if ($errorCount > 0) {
                $message .= " {$errorCount} errors. See below.";

                Log::warning('Bulk import finished with errors.', [
                    'error_rows' => $errorRows
                ]);

                return back()
                    ->with('success', $message)
                    ->with('errorRows', $errorRows);
            }

            return back()->with('success', $message);

        } catch (\Exception $e) {
            Log::critical('Bulk machine import failed with exception.', [
                'exception' => $e->getMessage(),
                'file' => $file ? $file->getClientOriginalName() : null,
                'user_id' => auth()->id()
            ]);
            return back()->with('error', 'Failed to import: ' . $e->getMessage());
        }
    }

    /**
     * Start a machine
     */
    public function start(int $id): JsonResponse
    {
        try {
            $machine = $this->machineService->start($id);
            return response()->json([
                'success' => true,
                'message' => 'Machine started successfully',
                'machine' => $machine,
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Failed to start machine: ' . $e->getMessage(),
            ], 500);
        }
    }

    /**
     * Stop a machine
     */
    public function stop(int $id): JsonResponse
    {
        try {
            $machine = $this->machineService->stop($id);
            return response()->json([
                'success' => true,
                'message' => 'Machine stopped successfully',
                'machine' => $machine,
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Failed to stop machine: ' . $e->getMessage(),
            ], 500);
        }
    }
}
