<?php

namespace App\Http\Controllers\Modules\Sales;

use App\Http\Controllers\Controller;
use App\Http\Traits\HasRoleViews;
use App\Models\CustomerVendor;
use App\Models\Rfq;
use App\Models\RfqFile;
use App\Models\RfqType;
use App\Models\ProductType;
use App\Models\RawMaterial;
use App\Services\Sales\RfqService;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;

/**
 * Unified RFQ Controller
 *
 * Handles RFQ (Request for Quotation) management for all roles.
 * Views are automatically resolved based on the logged-in user's role.
 */
class RfqController extends Controller
{
    use HasRoleViews;

    protected RfqService $rfqService;

    public function __construct(RfqService $rfqService)
    {
        $this->rfqService = $rfqService;
    }

    /**
     * Display the RFQ creation form
     */
    public function create()
    {
        $customers = CustomerVendor::whereIn('company_role', ['Customer', 'Both'])->get();
        $rfqTypes = RfqType::all();
        $productTypes = ProductType::all();
        $rawmaterials = RawMaterial::all();

        return $this->roleView($this->getViewPath('rfq'), compact('customers', 'rfqTypes', 'productTypes', 'rawmaterials'));
    }

    /**
     * Alias for create() - backward compatibility with old routes
     */
    public function rfq()
    {
        return $this->create();
    }

    /**
     * Get role-specific view path for RFQ views
     * SuperAdmin uses nested path (salesbom.rfq.*), Admin/Manager use direct path (rfq.*)
     */
    protected function getViewPath(string $view): string
    {
        if ($this->isSuperAdmin()) {
            return "salesbom.rfq.{$view}";
        }
        return "rfq.{$view}";
    }

    /**
     * Get role-specific route name for RFQ routes
     * SuperAdmin uses nested path (salesbom.rfq.*), Admin/Manager use direct path (rfq.*)
     */
    protected function getRouteName(string $route): string
    {
        if ($this->isSuperAdmin()) {
            return "salesbom.rfq.{$route}";
        }
        return "rfq.{$route}";
    }

    /**
     * Generate a new RFQ ID (AJAX)
     */
    public function generateRfqId(): JsonResponse
    {
        $rfqId = $this->rfqService->generateRfqNumber();
        return response()->json(['rfqId' => $rfqId]);
    }

    /**
     * Store a newly created RFQ
     */
    public function store(Request $request)
    {
        try {
            Log::info('[RFQ STORE] Processing started');

            $validated = $request->validate($this->getValidationRules());

            Log::info('[RFQ STORE] Validation passed', $validated);

            // Replace 'other' values if needed
            if ($request->rfqType == 'other') {
                $validated['rfqType'] = $request->input('other_rfq_type');
            }
            if ($request->productType == 'other') {
                $validated['productType'] = $request->input('other_product_type');
            }

            $data = [
                'rfq_no' => $request->rfqNo,
                'rfq_date' => $request->rfqDate,
                'customer' => $request->customer,
                'cus_ref_no' => $request->cusRefNo,
                'rfq_type' => $validated['rfqType'],
                'product_type' => $validated['productType'],
                'part_no' => $request->partNo,
                'project_material_no' => $request->project_materialNo,
                'description' => $request->description,
                'drawing_no' => $request->drawingNo,
                'drawing_rev' => $request->drawingRev,
                'quantity' => $request->quantity,
                'uom' => $request->uom,
                'note' => $request->note,
                'raw_material' => json_encode($request->rawmaterials),
            ];

            Log::info('[RFQ STORE] Final data for insert:', $data);

            $rfq = Rfq::create($data);
            Log::info('[RFQ STORE] RFQ created successfully. ID: ' . $rfq->id);

            // Store files in separate table
            $this->storeFiles($request, $rfq);

            return $this->redirectToRoute($this->getRouteName('rfqdetails'))
                ->with('success', 'RFQ created successfully.');

        } catch (\Illuminate\Validation\ValidationException $ve) {
            Log::error('[RFQ STORE] Validation Error:', $ve->errors());
            return back()->withErrors($ve->errors())->withInput();
        } catch (\Exception $e) {
            Log::error('[RFQ STORE] General Error: ' . $e->getMessage(), ['trace' => $e->getTraceAsString()]);
            return back()->with('error', 'Something went wrong while creating RFQ.');
        }
    }

    /**
     * Display the RFQ list page
     */
    public function index()
    {
        $rfqs = Rfq::with('customerInfo')->latest()->get();
        return $this->roleView($this->getViewPath('rfqdetails'), compact('rfqs'));
    }

    /**
     * Alias for index() - backward compatibility with old routes
     */
    public function rfqDetails()
    {
        return $this->index();
    }

    /**
     * Display the specified RFQ
     */
    public function show(int $id)
    {
        $rfq = Rfq::with(['customerInfo', 'rfqFiles'])->findOrFail($id);
        $rawMaterialNames = $this->getRawMaterialNames($rfq);

        return $this->roleView($this->getViewPath('view'), compact('rfq', 'rawMaterialNames'));
    }

    /**
     * Alias for show() - backward compatibility with old routes
     */
    public function view(int $id)
    {
        return $this->show($id);
    }

    /**
     * Display the edit form
     */
    public function edit(int $id)
    {
        $rfq = Rfq::with('customerInfo', 'rfqFiles')->findOrFail($id);
        $customers = CustomerVendor::all();
        $rfqTypes = RfqType::all();
        $productTypes = ProductType::all();
        $rawmaterials = RawMaterial::all();

        return $this->roleView($this->getViewPath('edit'), compact('rfq', 'customers', 'rfqTypes', 'productTypes', 'rawmaterials'));
    }

    /**
     * Update the specified RFQ
     */
    public function update(Request $request, int $id)
    {
        try {
            $rfq = Rfq::findOrFail($id);

            $validated = $request->validate($this->getValidationRules());

            if ($request->rfqType == 'other') {
                $validated['rfqType'] = $request->input('other_rfq_type');
            }
            if ($request->productType == 'other') {
                $validated['productType'] = $request->input('other_product_type');
            }

            $data = [
                'rfq_no' => $request->rfqNo,
                'rfq_date' => $request->rfqDate,
                'customer' => $request->customer,
                'cus_ref_no' => $request->cusRefNo,
                'rfq_type' => $validated['rfqType'],
                'product_type' => $validated['productType'],
                'part_no' => $request->partNo,
                'project_material_no' => $request->project_materialNo,
                'description' => $request->description,
                'drawing_no' => $request->drawingNo,
                'drawing_rev' => $request->drawingRev,
                'quantity' => $request->quantity,
                'uom' => $request->uom,
                'note' => $request->note,
                'raw_material' => json_encode($request->rawmaterials),
            ];

            $rfq->update($data);
            $this->storeFiles($request, $rfq);

            return $this->redirectToRoute($this->getRouteName('rfqdetails'))
                ->with('success', 'RFQ updated successfully.');

        } catch (\Illuminate\Validation\ValidationException $ve) {
            Log::error('[RFQ UPDATE] Validation Error:', $ve->errors());
            return back()->withErrors($ve->errors())->withInput();
        } catch (\Exception $e) {
            Log::error('[RFQ UPDATE] General Error: ' . $e->getMessage());
            return back()->with('error', 'Something went wrong while updating RFQ.');
        }
    }

    /**
     * Remove the specified RFQ
     * Only SuperAdmin or Manager can delete RFQs
     */
    public function destroy(int $id): JsonResponse
    {
        // Authorization check - only SuperAdmin and Manager can delete
        if (!$this->isSuperAdmin() && !$this->isManager()) {
            return response()->json(['message' => 'Unauthorized. Only SuperAdmin or Manager can delete RFQs.'], 403);
        }

        try {
            $rfq = Rfq::with('rfqFiles')->findOrFail($id);

            // Prevent deletion of approved RFQs unless SuperAdmin
            if ($rfq->isApproved() && !$this->isSuperAdmin()) {
                return response()->json(['message' => 'Cannot delete approved RFQs.'], 403);
            }

            foreach ($rfq->rfqFiles as $file) {
                if (Storage::disk('public')->exists($file->file_path)) {
                    Storage::disk('public')->delete($file->file_path);
                }
                $file->delete();
            }

            // Delete legacy file fields (if any)
            $this->deleteLegacyFiles($rfq);

            $rfq->delete();

            Log::info('[RFQ DELETE] RFQ deleted', [
                'rfq_id' => $id,
                'deleted_by' => auth()->id(),
            ]);

            return response()->json(['message' => 'RFQ deleted successfully.']);
        } catch (\Exception $e) {
            Log::error('RFQ Delete Error: ' . $e->getMessage());
            return response()->json(['message' => 'Failed to delete RFQ.'], 500);
        }
    }

    /**
     * Approve an RFQ (SuperAdmin only)
     */
    public function approve(int $id): JsonResponse
    {
        if (!$this->isSuperAdmin()) {
            return response()->json(['message' => 'Unauthorized'], 403);
        }

        $rfq = Rfq::findOrFail($id);

        // Validate current state
        if (!$rfq->isPending()) {
            return response()->json([
                'message' => 'Only pending RFQs can be approved.',
                'current_status' => $rfq->status
            ], 422);
        }

        if ($rfq->approve(auth()->id())) {
            Log::info('[RFQ APPROVE] RFQ approved', [
                'rfq_id' => $id,
                'approved_by' => auth()->id(),
            ]);
            return response()->json(['message' => 'RFQ approved successfully!']);
        }

        return response()->json(['message' => 'Failed to approve RFQ.'], 500);
    }

    /**
     * Reject an RFQ (SuperAdmin only)
     */
    public function reject(Request $request, int $id): JsonResponse
    {
        if (!$this->isSuperAdmin()) {
            return response()->json(['message' => 'Unauthorized'], 403);
        }

        $rfq = Rfq::findOrFail($id);

        // Validate current state
        if (!$rfq->isPending()) {
            return response()->json([
                'message' => 'Only pending RFQs can be rejected.',
                'current_status' => $rfq->status
            ], 422);
        }

        $reason = $request->input('reason');

        if ($rfq->reject(auth()->id(), $reason)) {
            Log::info('[RFQ REJECT] RFQ rejected', [
                'rfq_id' => $id,
                'rejected_by' => auth()->id(),
                'reason' => $reason,
            ]);
            return response()->json(['message' => 'RFQ rejected successfully!']);
        }

        return response()->json(['message' => 'Failed to reject RFQ.'], 500);
    }

    /**
     * Print RFQ
     */
    public function print(int $id)
    {
        $rfq = Rfq::with('customerInfo')->findOrFail($id);
        $rawMaterialNames = $this->getRawMaterialNames($rfq);

        return $this->roleView($this->getViewPath('print'), compact('rfq', 'rawMaterialNames'));
    }

    /**
     * Alias for print() - backward compatibility with old routes
     */
    public function printRfq(int $id)
    {
        return $this->print($id);
    }

    /**
     * Delete a specific file
     */
    public function deleteFile(int $id): JsonResponse
    {
        $file = RfqFile::find($id);

        if (!$file) {
            return response()->json(['success' => false, 'message' => 'File not found.']);
        }

        if (Storage::disk('public')->exists($file->file_path)) {
            Storage::disk('public')->delete($file->file_path);
        }

        $file->delete();

        return response()->json(['success' => true, 'message' => 'File deleted successfully.']);
    }

    /**
     * Get all raw materials (AJAX)
     */
    public function getRawMaterials(): JsonResponse
    {
        return response()->json(RawMaterial::all());
    }

    /**
     * Store a new raw material (AJAX)
     * Fixed: Use only validated data to prevent mass assignment vulnerability
     */
    public function storeRawMaterial(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'name' => 'required|string|max:255',
            'iso_specification' => 'required|string|max:255',
            'density' => 'nullable|string|max:255',
            'mechanical_properties' => 'nullable|string|max:255',
        ]);

        // Only use validated data - prevents mass assignment vulnerability
        $material = RawMaterial::create([
            'rm_grade' => $validated['name'],
            'iso_specification' => $validated['iso_specification'],
            'density' => $validated['density'] ?? null,
            'raw_material_type' => $validated['mechanical_properties'] ?? null,
        ]);

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

    /**
     * Store files for RFQ
     */
    protected function storeFiles(Request $request, Rfq $rfq): void
    {
        $fileInputs = [
            'drawingFiles' => 'drawing',
            'materialSpecificationFiles' => 'material_spec',
            'rfqFormFiles' => 'rfq_form',
            'annexureFiles' => 'annexure',
        ];

        foreach ($fileInputs as $inputName => $type) {
            if ($request->hasFile($inputName)) {
                foreach ($request->file($inputName) as $file) {
                    $path = $file->store("rfq_files/{$type}", 'public');

                    RfqFile::create([
                        'rfq_id' => $rfq->id,
                        'file_path' => $path,
                        'file_name' => $file->getClientOriginalName(),
                        'file_type' => $type,
                    ]);

                    Log::info("[RFQ STORE] File saved for type {$type}: {$path}");
                }
            }
        }
    }

    /**
     * Get raw material names from RFQ
     * Uses display_name accessor which prefers name over rm_grade
     */
    protected function getRawMaterialNames(Rfq $rfq): array
    {
        $rawMaterialNames = [];

        if ($rfq->raw_material) {
            $rawMaterialIds = json_decode($rfq->raw_material, true);

            if (is_array($rawMaterialIds) && count($rawMaterialIds)) {
                $materials = RawMaterial::whereIn('id', $rawMaterialIds)->get();
                foreach ($materials as $material) {
                    // Use display_name accessor which handles null names
                    $rawMaterialNames[$material->id] = $material->display_name;
                }
            }
        }

        return $rawMaterialNames;
    }

    /**
     * Delete legacy file fields
     */
    protected function deleteLegacyFiles(Rfq $rfq): void
    {
        $legacyFields = ['drawing_file', 'material_specification_file', 'rfq_form_file', 'annexure_file'];

        foreach ($legacyFields as $field) {
            if ($rfq->$field) {
                Storage::disk('public')->delete($rfq->$field);
            }
        }
    }

    /**
     * Get validation rules
     * Added file size limits (5MB max per file) for security
     */
    protected function getValidationRules(): array
    {
        return [
            'rfqNo' => 'required|string|max:100',
            'rfqDate' => 'required|date',
            'customer' => 'required|integer|exists:customer_vendors,id',
            'cusRefNo' => 'nullable|string|max:100',
            'rfqType' => 'required|string|max:100',
            'productType' => 'required|string|max:100',
            'partNo' => 'nullable|string|max:100',
            'project_materialNo' => 'nullable|string|max:100',
            'description' => 'nullable|string|max:2000',
            'drawingNo' => 'nullable|string|max:100',
            'drawingRev' => 'nullable|string|max:50',
            'quantity' => 'required|numeric|min:0.01',
            'uom' => 'required|string|max:50',
            'note' => 'nullable|string|max:2000',
            'rawmaterials' => 'required|array|min:1',
            'rawmaterials.*' => 'required|string',
            // File validation with size limits (5MB = 5120KB)
            'drawingFiles.*' => 'nullable|file|mimes:pdf,jpg,jpeg,png|max:5120',
            'materialSpecificationFiles.*' => 'nullable|file|mimes:pdf,jpg,jpeg,png|max:5120',
            'rfqFormFiles.*' => 'nullable|file|mimes:pdf,jpg,jpeg,png|max:5120',
            'annexureFiles.*' => 'nullable|file|mimes:pdf,jpg,jpeg,png|max:5120',
        ];
    }
}
