<?php

namespace App\Http\Controllers\Modules\Purchase;

use App\Http\Controllers\Controller;
use App\Http\Traits\HasRoleViews;
use App\Models\PurchaseQuotation;
use App\Models\PurchaseRFQ;
use App\Models\CustomerVendor;
use App\Models\ProductType;
use App\Models\ConversionProcess;
use App\Models\RawMaterial;
use App\Services\Purchase\PurchaseQuotationService;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;
use Illuminate\Validation\Rule;

/**
 * Unified Purchase Quotation Controller
 *
 * Handles purchase quotation management for all roles.
 * Reference: SuperAdminPurchaseQuotationController
 */
class PurchaseQuotationController extends Controller
{
    use HasRoleViews;

    protected PurchaseQuotationService $purchaseQuotationService;

    public function __construct(PurchaseQuotationService $purchaseQuotationService)
    {
        $this->purchaseQuotationService = $purchaseQuotationService;
    }

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

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

    /**
     * Display the purchase quotation creation form
     */
    public function create()
    {
        $vendors = CustomerVendor::where('company_role', 'Vendor')
            ->orWhere('company_role', 'Both')
            ->get();
        $productTypes = ProductType::all();

        $assignedRfqIds = PurchaseQuotation::whereNotNull('rfq_no')->pluck('rfq_no')->toArray();
        $unassignedRfqs = PurchaseRFQ::whereNotIn('rfq_no', $assignedRfqIds)
            ->where('status', 'approved')
            ->get();

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

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

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

        $rfq = PurchaseRFQ::with(['items', 'vendor'])->findOrFail($id);
        $vendor = $rfq->vendor;

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

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

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

    /**
     * Store a newly created purchase quotation
     */
    public function store(Request $request)
    {
        Log::info('Purchase Quotation store processing started');

        try {
            $validated = $request->validate([
                'quotation_no' => 'required|unique:purchase_quotations,quotation_no',
                'quotation_date' => 'required|date',
                'vendor_id' => 'required|exists:customer_vendors,id',
                'address' => 'nullable|string',
                'gst' => 'nullable|string',
                'email' => 'nullable|email',
                'phone' => 'nullable|string|max:15',
            ]);

            $quotation = PurchaseQuotation::create([
                'quotation_no' => $request->quotation_no,
                'quotation_date' => $request->quotation_date,
                'vendor_id' => $request->vendor_id,
                'vendor_name' => $request->vendor_name,
                'address' => $request->address,
                'gst' => $request->gst,
                'email' => $request->email,
                'phone' => $request->phone,
                'rfq_no' => $request->rfq_no,
                'rfq_date' => $request->rfq_date,
                'vendor_reference_no' => $request->vendor_reference_no,
                'delivery_terms' => $request->delivery_terms,
                '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,
                'note' => $request->note,
                'sub_total' => $request->sub_total,
                'discount' => $request->discount,
                'round_up' => $request->round_up,
                'grand_total' => $request->grand_total,
                'inr_in_words' => $request->inr_in_words,
                'additional_charges' => $request->additional_charges,
                'status' => 'pending',
            ]);

            Log::info('Purchase Quotation created', ['quotation_id' => $quotation->id]);

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

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

    /**
     * Display the specified purchase quotation
     */
    public function show(int $id)
    {
        $quotation = PurchaseQuotation::with(['vendor', 'items'])->findOrFail($id);
        return $this->roleView('purchasebom.quotation.view', compact('quotation'));
    }

    /**
     * Display the edit form
     */
    public function edit(int $id)
    {
        $quotation = PurchaseQuotation::with(['vendor', 'items'])->findOrFail($id);
        $vendors = CustomerVendor::where('company_role', 'Vendor')
            ->orWhere('company_role', 'Both')
            ->get();

        $vendor = $quotation->vendor;

        $assignedRfqIds = PurchaseQuotation::whereNotNull('rfq_no')
            ->where('id', '!=', $id)
            ->pluck('rfq_no')
            ->toArray();
        $unassignedRfqs = PurchaseRFQ::whereNotIn('rfq_no', $assignedRfqIds)
            ->where('status', 'approved')
            ->get();

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

        return $this->roleView('purchasebom.quotation.edit', compact(
            'quotation',
            'vendors',
            'unassignedRfqs',
            'vendor',
            'conversionprocesses',
            'allRawMaterials'
        ));
    }

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

        $validated = $request->validate([
            'quotation_no' => ['required', 'string', 'max:30', Rule::unique('purchase_quotations', 'quotation_no')->ignore($id)],
            'quotation_date' => ['required', 'date'],
            'vendor_id' => ['required', 'exists:customer_vendors,id'],
            'grand_total' => ['required', 'numeric', 'min:0'],
        ]);

        $quotation->update([
            'quotation_no' => $request->quotation_no,
            'quotation_date' => $request->quotation_date,
            'vendor_id' => $request->vendor_id,
            'vendor_name' => $request->vendor_name,
            'address' => $request->address,
            'gst' => $request->gst,
            'email' => $request->email,
            'phone' => $request->phone,
            'rfq_no' => $request->rfq_no,
            'rfq_date' => $request->rfq_date,
            'vendor_reference_no' => $request->vendor_reference_no,
            'delivery_terms' => $request->delivery_terms,
            '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,
            'note' => $request->note,
            'sub_total' => $request->sub_total,
            'discount' => $request->discount,
            'round_up' => $request->round_up,
            'grand_total' => $request->grand_total,
            'inr_in_words' => $request->inr_in_words,
            'additional_charges' => $request->additional_charges,
        ]);

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

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

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

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

            // Check if quotation has a related purchase order
            if ($quotation->purchaseOrder) {
                return response()->json([
                    'success' => false,
                    'message' => 'Cannot delete quotation with existing purchase order.',
                ], 403);
            }

            $quotation->items()->delete();
            $quotation->delete();

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

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

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

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

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

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

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

    /**
     * Print purchase quotation
     */
    public function print(int $id)
    {
        $quotation = PurchaseQuotation::with(['vendor', 'items'])->findOrFail($id);
        return $this->roleView('purchasebom.quotation.print', compact('quotation'));
    }
}
