<?php

namespace App\Http\Controllers\Modules\Sales;

use App\Http\Controllers\Controller;
use App\Http\Traits\HasRoleViews;
use App\Models\Quotation;
use App\Models\CustomerVendor;
use App\Models\Rfq;
use App\Models\ProductType;
use App\Models\ConversionProcess;
use App\Models\RawMaterial;
use App\Services\Sales\QuotationService;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;
use Illuminate\Validation\ValidationException;

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

    protected QuotationService $quotationService;

    public function __construct(QuotationService $quotationService)
    {
        $this->quotationService = $quotationService;
    }

    /**
     * Display the quotation creation form
     * Alias: quotationPage() for backward compatibility
     */
    public function quotationPage()
    {
        return $this->create();
    }

    /**
     * Display the quotation creation form
     */
    public function create()
    {
        $customers = CustomerVendor::customers()->get();
        $productTypes = ProductType::all();

        // Fetch only approved RFQs that are not yet assigned to quotations
        $unassignedRfqs = Rfq::where('status', 'approved')
            ->whereNotIn('id', function ($query) {
                $query->select('rfq_no')
                    ->from('quotations')
                    ->whereNotNull('rfq_no');
            })
            ->get();

        $conversionCosts = ConversionProcess::pluck('process_name')->toArray();
        $allRawMaterials = RawMaterial::all();

        return $this->roleView('salesbom.quotation.quotationorder', compact(
            'customers',
            'unassignedRfqs',
            'conversionCosts',
            'allRawMaterials',
            'productTypes'
        ));
    }

    /**
     * Get RFQ details for quotation form (AJAX)
     */
    public function getRfqDetails(int $id): JsonResponse
    {
        Log::info('getRfqDetails called with id:', ['id' => $id]);

        $rfq = Rfq::findOrFail($id);
        Log::info('RFQ retrieved:', $rfq->toArray());

        $customer = $rfq->customerInfo;

        // Parse raw_material IDs
        $rawMaterialIds = [];
        if ($rfq->raw_material) {
            $rawMaterialIds = is_array($rfq->raw_material)
                ? $rfq->raw_material
                : json_decode($rfq->raw_material, true);
        }

        $rawMaterials = [];
        if ($rawMaterialIds && count($rawMaterialIds)) {
            $rawMaterials = RawMaterial::whereIn('id', $rawMaterialIds)->get();
        }

        return response()->json([
            'success' => true,
            'rfq' => $rfq,
            'customer' => $customer,
            'raw_materials' => $rawMaterials,
        ]);
    }

    /**
     * Store a newly created quotation
     */
    public function store(Request $request)
    {
        try {
            $validated = $request->validate([
                'quotation_no' => 'required|unique:quotations,quotation_no',
                'quotation_date' => 'required|date',
                'customer_id' => 'required|exists:customer_vendors,id',
                'address' => 'nullable|string|max:500',
                'gst' => 'nullable|string|max:20',
                'email' => 'nullable|email|max:255',
                'phone' => 'nullable|string|max:20',
                'quantity' => 'nullable|numeric|min:0',
                'sub_total' => 'nullable|numeric|min:0',
                'grand_total' => 'nullable|numeric|min:0',
                'discount' => 'nullable|numeric|min:0',
                'round_up' => 'nullable|numeric',
            ]);

            $rawMaterials = $request->has('raw_material') ? array_values($request->raw_material) : [];
            $conversionCosts = $request->has('conversion_cost') ? array_values($request->conversion_cost) : [];
            $packingCharges = $request->has('packing') ? array_values($request->packing) : [];

            $quotation = Quotation::create([
                'quotation_no' => $request->quotation_no,
                'quotation_date' => $request->quotation_date,
                'customer_name' => $request->customer_id,
                'address' => $request->address,
                'gst' => $request->gst,
                'email' => $request->email,
                'phone' => $request->phone,
                'cust_ref_no' => $request->cust_ref_no,
                'rfq_no' => $request->rfq_no,
                'rfq_date' => $request->rfq_date,
                'part_no' => $request->part_no,
                'project_material_no' => $request->project_material_no,
                'drawing_no' => $request->drawing_no,
                'drawing_rev' => $request->drawing_rev,
                'quantity' => $request->quantity,
                'quantity_uom' => $request->quantity_uom,
                'description' => $request->description,
                'product_type' => $request->product_type,
                'note' => $request->note,
                'sub_total' => $request->sub_total,
                'discount' => $request->discount,
                'round_up' => $request->round_up,
                'grand_total' => $request->grand_total,
                'raw_materials' => $rawMaterials,
                'conversion_costs' => $conversionCosts,
                'packing_charges' => $packingCharges,
            ]);

            return $this->redirectToRoute('salesbom.quotation.quotationdetails')
                ->with('success', 'Quotation created successfully!');

        } catch (ValidationException $e) {
            throw $e;
        } catch (\Exception $e) {
            Log::error('Error in QuotationController@store', [
                'message' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
            ]);
            return redirect()->back()->with('error', 'Failed to create quotation: ' . $e->getMessage());
        }
    }

    /**
     * Display the quotation list
     * Alias: quotationDetails() for backward compatibility
     */
    public function quotationDetails()
    {
        return $this->index();
    }

    /**
     * Display the quotation list
     */
    public function index()
    {
        $quotations = Quotation::with('customer')->latest()->get();
        $assignedRfqIds = Quotation::whereNotNull('rfq_no')->pluck('rfq_no')->toArray();
        $unassignedRfqs = Rfq::whereNotIn('rfq_no', $assignedRfqIds)->get();

        return $this->roleView('salesbom.quotation.quotationdetails', compact('quotations', 'unassignedRfqs'));
    }

    /**
     * Display the specified quotation
     * Alias: view() for backward compatibility
     */
    public function view(int $id)
    {
        return $this->show($id);
    }

    /**
     * Display the specified quotation
     */
    public function show(int $id)
    {
        $quotation = Quotation::findOrFail($id);
        return $this->roleView('salesbom.quotation.view', compact('quotation'));
    }

    /**
     * Display the edit form
     */
    public function edit(int $id)
    {
        $quotation = Quotation::findOrFail($id);
        $customers = CustomerVendor::customers()->get();

        $customerId = $quotation->customer_id ?? $quotation->customer_name;
        $customer = CustomerVendor::find($customerId);

        $unassignedRfqs = Rfq::where('status', 'approved')
            ->whereNotIn('id', function ($query) use ($quotation) {
                $query->select('rfq_no')
                    ->from('quotations')
                    ->whereNotNull('rfq_no')
                    ->where('id', '!=', $quotation->id);
            })
            ->get();
        $conversionCosts = ConversionProcess::pluck('process_name')->toArray();
        $allRawMaterials = RawMaterial::all();
        $productTypes = ProductType::all();

        return $this->roleView('salesbom.quotation.edit', compact(
            'quotation',
            'customers',
            'unassignedRfqs',
            'customer',
            'conversionCosts',
            'allRawMaterials',
            'productTypes'
        ));
    }

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

            $rawMaterials = $request->has('raw_material') ? array_values($request->raw_material) : [];
            $conversionCosts = $request->has('conversion_cost') ? array_values($request->conversion_cost) : [];
            $packingCharges = $request->has('packing') ? array_values($request->packing) : [];

            $quotation->update([
                'quotation_no' => $request->quotation_no,
                'quotation_date' => $request->quotation_date,
                'customer_name' => $request->customer_id,
                'address' => $request->address,
                'gst' => $request->gst,
                'email' => $request->email,
                'phone' => $request->phone,
                'cust_ref_no' => $request->cust_ref_no,
                'rfq_no' => $request->rfq_no,
                'rfq_date' => $request->rfq_date,
                'part_no' => $request->part_no,
                'project_material_no' => $request->project_material_no,
                'drawing_no' => $request->drawing_no,
                'drawing_rev' => $request->drawing_rev,
                'quantity' => $request->quantity,
                'quantity_uom' => $request->quantity_uom,
                'description' => $request->description,
                'product_type' => $request->product_type,
                'note' => $request->note,
                'sub_total' => $request->sub_total,
                'discount' => $request->discount,
                'round_up' => $request->round_up,
                'grand_total' => $request->grand_total,
                'raw_materials' => $rawMaterials,
                'conversion_costs' => $conversionCosts,
                'packing_charges' => $packingCharges,
            ]);

            return $this->redirectToRoute('salesbom.quotation.quotationdetails')
                ->with('success', 'Quotation updated successfully!');

        } catch (ValidationException $e) {
            throw $e;
        } catch (\Exception $e) {
            Log::error('Quotation update error: ' . $e->getMessage());
            return redirect()->back()->with('error', 'Failed to update quotation: ' . $e->getMessage());
        }
    }

    /**
     * Remove the specified quotation
     */
    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 or Manager can delete quotations.',
            ], 403);
        }

        try {
            $quotation = Quotation::findOrFail($id);

            // Prevent deletion of approved quotations (except by SuperAdmin)
            if ($quotation->status === 'approved' && !$this->isSuperAdmin()) {
                return response()->json([
                    'success' => false,
                    'message' => 'Cannot delete approved quotations. Contact SuperAdmin.',
                ], 403);
            }

            $quotation->delete();

            return response()->json(['success' => true, 'message' => 'Quotation deleted successfully.']);
        } catch (\Exception $e) {
            return response()->json(['success' => false, 'message' => 'Failed to delete quotation.'], 500);
        }
    }

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

        $quotation = Quotation::findOrFail($id);
        $quotation->status = 'approved';
        $quotation->save();

        return response()->json(['success' => true, 'message' => 'Quotation approved!']);
    }

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

        $quotation = Quotation::findOrFail($id);
        $quotation->status = 'rejected';
        $quotation->save();

        return response()->json(['success' => true, 'message' => 'Quotation rejected!']);
    }

    /**
     * Print quotation
     */
    public function print(int $id)
    {
        $quotation = Quotation::findOrFail($id);

        // Ensure arrays (model cast handles decoding; guard against legacy double-encoded data)
        $quotation->raw_materials = is_array($quotation->raw_materials) ? $quotation->raw_materials : (json_decode($quotation->raw_materials, true) ?: []);
        $quotation->conversion_costs = is_array($quotation->conversion_costs) ? $quotation->conversion_costs : (json_decode($quotation->conversion_costs, true) ?: []);
        $quotation->packing_charges = is_array($quotation->packing_charges) ? $quotation->packing_charges : (json_decode($quotation->packing_charges, true) ?: []);

        return $this->roleView('salesbom.quotation.print', compact('quotation'));
    }
}
