<?php

namespace App\Http\Controllers;

use App\Mail\OrderConfirmed;
use App\Mail\Ordercopytransfer;
use App\Models\Area;
use App\Models\Cart;
use App\Models\Order;
use App\Models\Product;
use App\Models\Productcolor;
use App\Models\Shippingzone;
use App\Models\Systemlog;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Str;

use App\Traits\VerifiesPaymentTotal;

class CodController extends Controller
{
    use VerifiesPaymentTotal;




    public function order_confirmed_cod(Request $request)
    {

        try {
            // Save the order and get the new order IDs
            $newOrderIds = $this->savecodorder($request);

            if (!empty($newOrderIds['orderIds'])) {
                // Get specifically the newly created orders
                $newOrders = Order::whereIn('id', $newOrderIds['orderIds'])->get();

                // Flash a success message for the view
                session()->flash('new_order', true);

                return view('web.home.checkout.cod_success', [
                    'orders' => $newOrders,
                    'totalamount' => $request->amount,
                ]);
            } else {

                return redirect()->back()->with('error', 'Failed to place order');
            }
        } catch (\Exception $e) {
            // Log error
            DB::table('error_logs')->insert([
                'message' => $e->getMessage(),
                'file' => $e->getFile(),
                'line' => $e->getLine(),
                'trace' => $e->getTraceAsString(),
                'created_at' => now(),
            ]);

            return redirect()->back()->with('error', 'An error occurred while processing your order');
        }
    }
    public function savecodorder($request)
    {
        $newOrderIds = []; // Store new order IDs
        $orderItems = []; // For email content
        $productDetails = []; // For Koombiyo description
        $totalOrderAmount = 0;
        $totalServiceFee = 0;
        $totalTaxAmountSum = 0;


        // Get shipping zone data
        $city_name = $request->cus_city ?? null;
        $areaData = $city_name ? Area::where('area_name', $city_name)->first() : null;

        // If area not found, default to Zone A (serviceid 1)
        $serviceid = $areaData ? $areaData->serviceid : 1;

        $zonedata = Shippingzone::where('id', $serviceid)->first();

        try {
            // Security: Recalculate amount on server
            try {
                $verifiedAmount = $this->verifyTotalAmount($request->all());
                $request->merge(['amount' => $verifiedAmount]);
            } catch (\Exception $e) {
                throw new \Exception('Invalid order data: ' . $e->getMessage());
            }

            if (!$zonedata) {
                // Secondary fallback if specific zone or Zone A is missing from DB
                $zonedata = Shippingzone::where('id', 1)->first() ?: (object) ['id' => 1, 'price' => 425];
            }

            $user = Auth::user();
            $appliedPointsTotal = 0;
            if ($request->input('use_points') && $user) {
                $appliedPointsTotal = min($user->recycling_points, $verifiedAmount);
                $verifiedAmount -= $appliedPointsTotal;
                $request->merge(['amount' => $verifiedAmount]);
            }

            // Process request data
            $productIds = !empty($request->productid) ? explode(',', $request->productid) : [];
            $colors = !empty($request->order_color) ? explode(',', $request->order_color) : [];
            $quantities = !empty($request->order_qty) ? explode(',', $request->order_qty) : [];

            if (count($productIds) === 0 || count($productIds) !== count($colors) || count($productIds) !== count($quantities)) {
                throw new \Exception('Invalid product data');
            }

            // Calculate shipping total using server-side data directly
            $totalWeightForShipping = 0;
            foreach ($productIds as $index => $productId) {
                $qty = (int) ($quantities[$index] ?? 1);
                $pData = DB::table('product')->select('weight')->where('id', $productId)->first();
                if ($pData) {
                    $totalWeightForShipping += ($pData->weight * $qty);
                }
            }

            $productweightcostAll = $totalWeightForShipping > 1000 ? ceil(($totalWeightForShipping - 1000) / 1000) * 100 : 0;
            $serverShippingPrice = ($zonedata->price ?? 0) + $productweightcostAll;

            $itemCount = count($productIds);
            $baseShippingPerItem = $itemCount > 0 ? ($serverShippingPrice / $itemCount) : 0;

            // Process each product
            foreach ($productIds as $index => $productId) {
                $color = $colors[$index] ?? null;
                $quantity = (int) ($quantities[$index] ?? 1);

                if ($quantity <= 0)
                    continue;

                // Check for duplicate orders
                $existingOrder = Order::where('product_id', $productId)
                    ->where('color', $color)
                    ->where('userid', $user->id ?? 'Guest')
                    ->where('created_at', '>=', Carbon::now()->subMinutes(1))
                    ->first();

                if ($existingOrder)
                    continue;

                // Get product data with lock
                $productdata = DB::table('product')
                    ->join('product_color', 'product.id', '=', 'product_color.product_id')
                    ->select(
                        'product.id',
                        'product.product_name',
                        'product.product_price',
                        'product.cutted_price',
                        'product.qty',
                        'product.order',
                        'product.weight',
                        'product.product_image',
                        'product_color.product_color',
                        'product_color.price'
                    )
                    ->where('product.id', $productId)
                    ->where('product_color.product_color', $color)
                    ->lockForUpdate()
                    ->first();

                if (!$productdata)
                    continue;

                // Validate stock
                if ($productdata->qty < $quantity) {
                    throw new \Exception("Insufficient stock for product ID: {$productId}");
                }

                // Calculate prices
                $productPrice = ($productdata->price ?? $productdata->product_price) * $quantity;
                $productWeight = $productdata->weight * $quantity;
                // Weight cost is now handled via $baseShippingPerItem
                $service_fee = $baseShippingPerItem;
                $finalamount = $productPrice + $service_fee;

                // Create order
                $orderId = 'COD-' . $request->order_id . '-' . substr(Str::uuid(), 0, 5);

                $order = new Order();
                $order->userid = $user->id ?? "Guest";
                $order->zone_id = $zonedata->id;
                $order->order_id = $orderId;
                $order->product_id = $productId;
                $order->first_name = $request->cus_firstname;
                $order->last_name = $request->cus_lastname;
                $order->color = $color;
                $order->quantity = $quantity;
                $order->telephone = $request->cus_phone;
                $order->company = $request->cus_company;
                $order->email = $request->cus_email;
                $order->address_1 = $request->cus_address_one;
                $order->address_2 = $request->cus_address_two;
                $order->city = $request->cus_city;
                $order->district = $request->cus_district;
                $order->postcode = $request->cus_postcode;
                $order->ordernote = $request->order_note;
                $order->processing = 1;
                $order->payment_method = $request->input('payment_method') ?: 'cod';
                $order->service_fee = $service_fee;
                $order->total = $productPrice;
                $order->totalweight = $productWeight;

                // Calculate tax for this line item if corporate
                $lineTaxPercentage = 0;
                $lineTaxAmount = 0;
                if ($user && $user->is_corporate) {
                    $lineTaxPercentage = (float) \App\Models\SystemSetting::get('corporate_tax_percentage', 18.00);
                    $taxBaseSetting = \App\Models\SystemSetting::get('tax_calculation_base', 'selling_price');
                    $taxBasePrice = ($taxBaseSetting === 'cutted_price' && isset($productdata->cutted_price))
                        ? $productdata->cutted_price
                        : ($productdata->price ?? $productdata->product_price);

                    $lineTaxAmount = round(($taxBasePrice * $quantity * $lineTaxPercentage) / 100, 2);
                }
                $order->tax_amount = $lineTaxAmount;
                $order->tax_percentage = $lineTaxPercentage;
                $totalTaxAmountSum += $lineTaxAmount;

                $order->voucher_code = $request->voucher_code ?? null;
                // Distribute discount across items if needed, or just store it.
                // Since this loop processes each item as a separate order (row), we might want to store the full discount on the first item
                // or distribute it. For simplicity, let's store it on the first item or all if needed.
                // However, the DB schema has discount_amount on the order table.
                // If the user buys multiple items, they are separate rows in `order` table.
                // Let's attach the voucher code to all items in this batch, but we must be careful not to sum up discount amount when calculating totals later if not intended.
                // Better approach: if it's a percentage discount, apply to each specific item price.
                // If fixed, we need to split it or assign to one.
                // Given the Livewire component calculates total discount, let's assume specific logic.
                // But wait, the frontend sends `discount_amount` as a total value.
                // If we save it to every row, summing it up would be wrong.
                // Let's just save the code and maybe 0 discount for now, or handle it properly.
                // Actually, let's simplify: save the code on all, but maybe share the discount?
                // Or maybe just save it and let the Invoice/Reporting handle the "per order batch" logic.
                // Let's store the passed discount amount on the first order of the batch.
                if ($index === 0) {
                    $order->discount_amount = $request->discount_amount ?? 0;
                    $order->points_applied = $appliedPointsTotal;
                    $order->points_used_flag = $appliedPointsTotal > 0 ? 1 : 0;
                } else {
                    $order->discount_amount = 0;
                    $order->points_applied = 0;
                    $order->points_used_flag = 0;
                }
                $order->status = 1;

                DB::transaction(function () use ($order, $productdata, $quantity, $user, $productId, $color, $request, $index, $appliedPointsTotal) {
                    $order->save();
                    $this->updateqty($productdata, $quantity);
                    $this->updateorder_qty($productdata, $quantity);
                    $this->updatecolorstock($productId, $color, $quantity);
                    if ($user) {
                        $product = Product::find($productId);
                        $this->remove_fromCart($product, $user->id, $color);
                    }
                    if ($index === 0 && $appliedPointsTotal > 0 && $user) {
                        $user->recycling_points -= $appliedPointsTotal;
                        $user->save();
                    }
                    if (!empty($request->voucher_code)) {
                        $voucher = \App\Models\Voucher::where('code', $request->voucher_code)->first();
                        if ($voucher && $voucher->isValid()) {
                            $voucher->update([
                                'redeemed_by' => $user ? $user->id : null,
                                'redeemed_at' => now()
                            ]);
                        }
                    }
                });

                // Store data for Koombiyo and emails
                $newOrderIds[] = $order->id;
                $newOrderIdsNO[] = $order->order_id;
                $totalOrderAmount += $productPrice;
                $totalServiceFee += $service_fee;

                $productDetails[] = [
                    'name' => $productdata->product_name,
                    'color' => $color,
                    'quantity' => $quantity,
                    'price' => $productdata->price ?? $productdata->product_price
                ];

                $orderItems[] = [
                    'product_id' => $productId,
                    'product_name' => $productdata->product_name,
                    'color' => $color,
                    'quantity' => $quantity,
                    'unit_price' => $productdata->price ?? $productdata->product_price,
                    'total_price' => $productPrice,
                    'service_fee' => $service_fee,
                    'final_amount' => $finalamount,
                    'settextcolor' => $this->setcolor($color),
                    'cutted_price' => $productdata->cutted_price
                ];
            }

            $taxPercentage = ($user && $user->is_corporate) ? (float) \App\Models\SystemSetting::get('corporate_tax_percentage', 18.00) : 0;
            $taxAmount = $totalTaxAmountSum;
            if (count($orderItems) > 0) {
                $orderdate = Carbon::today();
                $discountAmount = !empty($request->voucher_code) ? ($request->discount_amount ?? 0) : 0;

                // Generate Invoice for COD order
                $todayDate = date('Ymd');
                $todayCount = \App\Models\Invoice::withoutGlobalScopes()->whereDate('invoice_date', date('Y-m-d'))->count() + 1;
                do {
                    $invoiceNumber = 'INV-' . $todayDate . '-' . str_pad($todayCount, 4, '0', STR_PAD_LEFT);
                    $todayCount++;
                } while (\App\Models\Invoice::withoutGlobalScopes()->where('invoice_number', $invoiceNumber)->exists());

                $invoiceSubtotal = $totalOrderAmount;
                $invoiceTotal = max(0, $invoiceSubtotal + $totalServiceFee + $taxAmount - $discountAmount - $appliedPointsTotal);

                $invoice = \App\Models\Invoice::create([
                    'invoice_number' => $invoiceNumber,
                    'order_id' => 'ORDER-' . implode('-', $newOrderIds),
                    'customer_name' => $request->cus_firstname . ' ' . $request->cus_lastname,
                    'customer_email' => $request->cus_email,
                    'billing_address' => $request->cus_address_one . ', ' . $request->cus_city,
                    'invoice_date' => now(),
                    'subtotal' => $invoiceSubtotal,
                    'tax_percentage' => $taxPercentage,
                    'tax_amount' => $taxAmount,
                    'shipping_cost' => $totalServiceFee,
                    'discount_amount' => $discountAmount,
                    'total_amount' => $invoiceTotal,
                    'status' => 'pending',
                    'points_applied' => $appliedPointsTotal,
                    'points_used_flag' => $appliedPointsTotal > 0 ? 1 : 0,
                ]);

                try {
                    $this->mailtoCustomer(
                        $request->cus_email,
                        $request->cus_firstname,
                        $newOrderIdsNO,
                        $orderItems,
                        $totalOrderAmount,
                        $totalServiceFee,
                        $request->cus_phone,
                        $request->cus_address_one,
                        $request->cus_address_two,
                        $orderdate,
                        $taxAmount ?? 0,
                        $taxPercentage ?? 0,
                        $discountAmount ?? 0,
                        $invoice,
                        $appliedPointsTotal
                    );

                    $this->copyTransfer(
                        $request->cus_email,
                        $request->cus_firstname,
                        $newOrderIds,
                        $orderItems,
                        $totalOrderAmount,
                        $totalServiceFee,
                        $request->cus_phone,
                        $request->cus_address_one,
                        $request->cus_address_two,
                        $orderdate,
                        $taxAmount ?? 0,
                        $taxPercentage ?? 0,
                        $discountAmount ?? 0,
                        $appliedPointsTotal
                    );
                } catch (\Exception $e) {
                    Log::error('Email sending failed: ' . $e->getMessage());
                }

                // // Send to Koombiyo using the first order for customer details
                $this->sendToKoombiyo(
                    $request->cus_firstname,
                    $request->cus_phone,
                    trim($request->cus_address_one . ' ' . $request->cus_address_two),
                    $request->cus_city,
                    $request->cus_district,
                    $request->cus_postcode,
                    $request->order_note ?? 'Order from website',
                    $productDetails,
                    max(0, $totalOrderAmount + $totalServiceFee + $taxAmount - $discountAmount - $appliedPointsTotal),
                    $newOrderIds
                );

                // Update the invoice status to paid after successful processing
                $invoice->update(['status' => 'paid']);
            }

            return [
                'success' => true,
                'orderIds' => $newOrderIds
            ];
        } catch (\Throwable $th) {
            DB::table('error_logs')->insert([
                'message' => $th->getMessage(),
                'file' => $th->getFile(),
                'line' => $th->getLine(),
                'trace' => $th->getTraceAsString(),
                'created_at' => now(),
            ]);

            throw $th;
        }
    }

    private function sendToKoombiyo(
        $customerName,
        $phone,
        $address,
        $city,
        $district,
        $postcode,
        $notes,
        $productDetails,
        $codValue,
        $orderIds
    ) {
        try {
            $waybillId = $this->getWaybillId();
            if (!$waybillId) {
                throw new \Exception('Failed to get waybill ID from Koombiyo');
            }

            // Build product description
            $description = "Order Details:\n";
            foreach ($productDetails as $product) {
                $description .= sprintf(
                    "%s (Color: %s) x %d - Rs.%.2f\n",
                    $product['name'],
                    $this->getsetcolor($product['color']),
                    $product['quantity'],
                    $product['price']
                );
            }

            $apiData = [
                'apikey' => 'ORkohpssTIlGBjSqDYyb',
                'orderWaybillid' => $waybillId,
                'orderNo' => 'ORDER-' . implode('-', $orderIds),
                'receiverName' => $customerName,
                'receiverStreet' => $address,
                'receiverDistrict' => $this->getDistrictId($district),
                'receiverCity' => $this->getCityId($city, $district),
                'receiverPhone' => $phone,
                'description' => 'Plastic Products',
                'spclNote' => $notes,
                'getCod' => $codValue
            ];

            $response = Http::asForm()
                ->post('https://application.koombiyodelivery.lk/api/Addorders/users', $apiData);


            if ($response->successful()) {
                // Update all orders with tracking info
                Order::whereIn('id', $orderIds)->update([

                    'tracking' => 'WAYBILL-' . $waybillId
                ]);

                return true;
            } else {
                throw new \Exception('Koombiyo API error: ' . $response->body());
            }
        } catch (\Exception $th) {
            DB::table('error_logs')->insert([
                'message' => $th->getMessage(),
                'file' => $th->getFile(),
                'line' => $th->getLine(),
                'trace' => $th->getTraceAsString(),
                'created_at' => now(),
            ]);
            return false;
        }
    }

    public function getWaybillId()
    {
        try {
            $response = Http::asForm()->post('https://application.koombiyodelivery.lk/api/Waybils/users', [
                'apikey' => 'ORkohpssTIlGBjSqDYyb',
                'limit' => 1
            ]);

            if ($response->successful()) {
                $data = $response->json();

                Log::info('Waybill API Response', ['response' => $data]);

                // Check multiple possible response structures
                if (isset($data['data']) && is_array($data['data']) && count($data['data']) > 0) {
                    return $data['data'][0]['waybill_id'] ?? $data['data'][0]['barcode'] ?? $data['data'][0]['id'];
                } elseif (isset($data['waybill_id'])) {
                    return $data['waybill_id'];
                } elseif (isset($data['barcode'])) {
                    return $data['barcode'];
                } elseif (isset($data['waybills']) && is_array($data['waybills']) && count($data['waybills']) > 0) {
                    return $data['waybills'][0]['waybill_id'] ?? null;
                }

                Log::error('No waybill ID found in API response', ['response' => $data]);
                return null;
            } else {
                Log::error('Failed to get waybill ID - API error', [
                    'status' => $response->status(),
                    'response' => $response->body()
                ]);
                return null;
            }
        } catch (\Exception $e) {
            Log::error('Exception while getting waybill ID from Koombiyo API', [
                'error' => $e->getMessage()
            ]);
            return null;
        }
    }

    /**
     * Get district ID for Koombiyo API
     */
    private function getDistrictId($districtName)
    {
        // You may want to create a mapping table or cache this data
        $districtMapping = [
            'Colombo' => 1,
            'Gampaha' => 2,
            'Kalutara' => 3,
            'Kandy' => 4,
            'Matale' => 5,
            'Nuwara Eliya' => 6,
            'Galle' => 7,
            'Matara' => 8,
            'Hambantota' => 9,
            'Jaffna' => 10,
            'Kilinochchi' => 11,
            'Mannar' => 12,
            'Vavuniya' => 13,
            'Mullativu' => 14,
            'Batticaloa' => 15,
            'Ampara' => 16,
            'Trincomalee' => 17,
            'Kurunegala' => 18,
            'Puttalam' => 19,
            'Anuradhapura' => 20,
            'Polonnaruwa' => 21,
            'Badulla' => 22,
            'Moneragala' => 23,
            'Ratnapura' => 24,
            'Kegalle' => 25
        ];

        return $districtMapping[$districtName] ?? 1; // Default to Colombo
    }

    /**
     * Get city ID for Koombiyo API
     */
    private function getCityId($cityName, $districtName)
    {
        // This is a simplified version. You should ideally call the Cities API
        // or maintain a mapping table for accurate city IDs
        try {
            $districtId = $this->getDistrictId($districtName);
            $response = Http::asForm()->post('https://application.koombiyodelivery.lk/api/Cities/users', [
                'apikey' => 'ORkohpssTIlGBjSqDYyb',
                'district_id' => $districtId
            ]);

            if ($response->successful()) {
                $cities = $response->json();
                // Find matching city (adjust based on actual API response structure)
                foreach ($cities as $city) {
                    if (stripos($city['name'], $cityName) !== false) {
                        return $city['id'];
                    }
                }
            }
        } catch (\Exception $e) {
            Log::error('Failed to get city ID from Koombiyo API', ['error' => $e->getMessage()]);
        }

        return 1; // Default city ID
    }

    /**
     * Generate order description from order data
     */

    public function getsetcolor($color)
    {

        if ($color == '#A78B8D') {
            $colorName = 'Marblepink';
        } else if ($color == '#61A8F8') {
            $colorName = 'Babyblue';
        } else if ($color == '#C55C82') {
            $colorName = 'Pink';
        } else if ($color == '#FF0000') {
            $colorName = 'Red';
        } else if ($color == '#CAD3D0') {
            $colorName = 'Clear';
        } else if ($color == '#BA9978') {
            $colorName = 'Beige';
        } else if ($color == '#88DB86') {
            $colorName = 'Applegreen';
        } else if ($color == '#DEE4EE') {
            $colorName = 'Marblewhite';
        } else if ($color == '#BDB8EE') {
            $colorName = 'Marbleviolet';
        } else if ($color == '#E9CBB9') {
            $colorName = 'Marbleorange';
        } else if ($color == '#FEF250') {
            $colorName = 'Lemonyellow';
        } else if ($color == '#f4c2c2') {
            $colorName = 'Babypink';
        } else if ($color == '#D2C77D') {
            $colorName = 'Metallicgold';
        } else if ($color == '#DAD9C6') {
            $colorName = 'Buttermilk';
        } else if ($color == '#E9C500') {
            $colorName = 'Yellow';
        } else if ($color == '#D3CBC4') {
            $colorName = 'Graybeige';
        } else if ($color == '#0F2D8D') {
            $colorName = 'Blue';
        } else if ($color == '#005E3A') {
            $colorName = 'Green';
        } else if ($color == '#D6F2E6') {
            $colorName = 'Marblegreen';
        } else if ($color == '#BF8BFF') {
            $colorName = 'Violet';
        } else if ($color == '#6B4B36') {
            $colorName = 'Brown';
        } else if ($color == '#C0C0C0') {
            $colorName = 'Silver';
        } else if ($color == '#808080') {
            $colorName = 'Grey';
        } else if ($color == '#6CD2FA') {
            $colorName = 'Skyblue';
        } else if ($color == '#D09305') {
            $colorName = 'Orange';
        } else if ($color == '#13598B') {
            $colorName = 'Metallicblue';
        } else if ($color == '#9582BB') {
            $colorName = 'Metalicviolet';
        } else if ($color == '#A286F4') {
            $colorName = 'Purple';
        } else if ($color == '#62ADE6') {
            $colorName = 'Marbleblue';
        } else if ($color == '#80355C') {
            $colorName = 'Marblered';
        } else if ($color == '#2FCBD4') {
            $colorName = 'Avocadogreen';
        } else if ($color == '#FFA07A') {
            $colorName = 'Lightorange';
        } else if ($color == '#DDD3D1') {
            $colorName = 'Marblebeige';
        } else if ($color == '#F4C430') {
            $colorName = 'Saffron';
        } else if ($color == '#000000') {
            $colorName = 'Black';
        } else if ($color == '#D4AF37') {
            $colorName = 'Marblegold';
        } else if ($color == '#FFFFFF') {
            $colorName = 'Purewhite';
        } else if ($color == '#B4B4B8') {
            $colorName = 'Metallicsilver';
        } else if ($color == '#58C3C2') {
            $colorName = 'Marblegreen';
        } else if ($color == '#006A4E') {
            $colorName = 'Bottlegreen';
        } else if ($color == '#6F4E37') {
            $colorName = 'Coffee';
        } else if ($color == '#FFFDD0') {
            $colorName = 'Cream';
        } else if ($color == '#A9A9A9') {
            $colorName = 'Darkgrey';
        } else if ($color == '#C40233') {
            $colorName = 'Metalicred';
        } else if ($color == '#3D7764') {
            $colorName = 'Metalicgreen';
        } else if ($color == '#F8B700') {
            $colorName = 'Metalicyellow';
        }
        return $colorName;
    }

    public function copyTransfer($email, $name, $orderIds, $orderItems, $totalOrderAmount, $totalServiceFee, $cusphone, $addressone, $addresstwo, $orderdate, $taxAmount = 0, $taxPercentage = 0, $discountAmount = 0, $pointsApplied = 0)
    {
        try {
            $recipients = ['sales@americanplastic.lk', 'info@americanplastic.lk', 'ashan.r@americanplastic.lk'];
            // $recipients = ['madusankakalpa65@gmail.com'];
            Mail::to($recipients)->send(new Ordercopytransfer(
                $name,
                $orderIds,
                $orderItems,
                $totalOrderAmount,
                $totalServiceFee,
                $cusphone,
                $addressone,
                $addresstwo,
                $orderdate,
                $taxAmount,
                $taxPercentage,
                $discountAmount,
                $pointsApplied
            ));
        } catch (\Throwable $th) {
            DB::table('error_logs')->insert([
                'message' => $th->getMessage(),
                'file' => $th->getFile(),
                'line' => $th->getLine(),
                'trace' => $th->getTraceAsString(),
                'created_at' => now(),
            ]);
        }
    }

    public function mailtoCustomer($email, $name, $orderIds, $orderItems, $totalOrderAmount, $totalServiceFee, $cusphone, $addressone, $addresstwo, $orderdate, $taxAmount = 0, $taxPercentage = 0, $discountAmount = 0, $invoice = null, $pointsApplied = 0)
    {

        try {
            Mail::to($email)->send(new OrderConfirmed(
                $name,
                $orderIds[0], // Use first order ID as reference
                $orderItems,
                $totalOrderAmount,
                $totalServiceFee,
                $cusphone,
                $addressone,
                $addresstwo,
                $orderdate,
                $taxAmount,
                $taxPercentage,
                $discountAmount,
                $invoice,
                $pointsApplied
            ));
        } catch (\Throwable $th) {
            DB::table('error_logs')->insert([
                'message' => $th->getMessage(),
                'file' => $th->getFile(),
                'line' => $th->getLine(),
                'trace' => $th->getTraceAsString(),
                'created_at' => now(),
            ]);
        }
    }
    public function setcolor($colorchecked)
    {
        try {
            if ($colorchecked == '#A78B8D') {
                $cartcolor = 'Marblepink';
            } elseif ($colorchecked == '#61A8F8') {
                $cartcolor = 'Babyblue';
            } elseif ($colorchecked == '#C55C82') {
                $cartcolor = 'Pink';
            } elseif ($colorchecked == '#FF0000') {
                $cartcolor = 'Red';
            } elseif ($colorchecked == '#CAD3D0') {
                $cartcolor = 'Clear';
            } elseif ($colorchecked == '#BA9978') {
                $cartcolor = 'Beige';
            } elseif ($colorchecked == '#88DB86') {
                $cartcolor = 'Applegreen';
            } elseif ($colorchecked == '#DEE4EE') {
                $cartcolor = 'Marblewhite';
            } elseif ($colorchecked == '#BDB8EE') {
                $cartcolor = 'Marbleviolet';
            } elseif ($colorchecked == '#E9CBB9') {
                $cartcolor = 'Marbleorange';
            } elseif ($colorchecked == '#FEF250') {
                $cartcolor = 'Lemonyellow';
            } elseif ($colorchecked == '#f4c2c2') {
                $cartcolor = 'Babypink';
            } elseif ($colorchecked == '#D2C77D') {
                $cartcolor = 'Metallicgold';
            } elseif ($colorchecked == '#DAD9C6') {
                $cartcolor = 'Buttermilk';
            } elseif ($colorchecked == '#E9C500') {
                $cartcolor = 'Yellow';
            } elseif ($colorchecked == '#D3CBC4') {
                $cartcolor = 'Graybeige';
            } elseif ($colorchecked == '#0F2D8D') {
                $cartcolor = 'Blue';
            } elseif ($colorchecked == '#005E3A') {
                $cartcolor = 'Green';
            } elseif ($colorchecked == '#D6F2E6') {
                $cartcolor = 'Marblegreen';
            } elseif ($colorchecked == '#BF8BFF') {
                $cartcolor = 'Violet';
            } elseif ($colorchecked == '#6B4B36') {
                $cartcolor = 'Brown';
            } elseif ($colorchecked == '#C0C0C0') {
                $cartcolor = 'Silver';
            } elseif ($colorchecked == '#808080') {
                $cartcolor = 'Grey';
            } elseif ($colorchecked == '#6CD2FA') {
                $cartcolor = 'Skyblue';
            } elseif ($colorchecked == '#D09305') {
                $cartcolor = 'Orange';
            } elseif ($colorchecked == '#13598B') {
                $cartcolor = 'Metallicblue';
            } elseif ($colorchecked == '#9582BB') {
                $cartcolor = 'Metallicviolet';
            } elseif ($colorchecked == '#A286F4') {
                $cartcolor = 'Purple';
            } elseif ($colorchecked == '#62ADE6') {
                $cartcolor = 'Marbleblue';
            } elseif ($colorchecked == '#80355C') {
                $cartcolor = 'Marblered';
            } elseif ($colorchecked == '#2FCBD4') {
                $cartcolor = 'Avocadogreen';
            } elseif ($colorchecked == '#FFA07A') {
                $cartcolor = 'Lightorange';
            } elseif ($colorchecked == '#DDD3D1') {
                $cartcolor = 'Marblebeige';
            } elseif ($colorchecked == '#F4C430') {
                $cartcolor = 'Saffron';
            } elseif ($colorchecked == '#000000') {
                $cartcolor = 'Black';
            } elseif ($colorchecked == '#D4AF37') {
                $cartcolor = 'Marblegold';
            } elseif ($colorchecked == '#FFFFFF') {
                $cartcolor = 'Purewhite';
            } elseif ($colorchecked == '#B4B4B8') {
                $cartcolor = 'Metallicsilver';
            } elseif ($colorchecked == '#58C3C2') {
                $cartcolor = 'Marblegreen';
            } elseif ($colorchecked == '#006A4E') {
                $cartcolor = 'Bottlegreen';
            } elseif ($colorchecked == '#6F4E37') {
                $cartcolor = 'Coffee';
            } elseif ($colorchecked == '#FFFDD0') {
                $cartcolor = 'Cream';
            } elseif ($colorchecked == '#A9A9A9') {
                $cartcolor = 'Darkgrey';
            } elseif ($colorchecked == '#C40233') {
                $cartcolor = 'Metalicred';
            } elseif ($colorchecked == '#9582BB') {
                $cartcolor = 'Metalicviolet';
            } elseif ($colorchecked == '#3D7764') {
                $cartcolor = 'Metalicgreen';
            } elseif ($colorchecked == '#F8B700') {
                $cartcolor = 'Metalicyellow';
            }

            return $cartcolor;
        } catch (\Throwable $th) {
        }
    }

    public function updatecolorstock($productid, $color, $qty)
    {
        try {
            $productcolor = Productcolor::where('product_id', $productid)->where('product_color', $color)->first();


            $productcolor->pc_qty = $productcolor->pc_qty - $qty;
            $productcolor->update();

        } catch (\Throwable $th) {
            DB::table('error_logs')->insert([
                'message' => $th->getMessage(),
                'file' => $th->getFile(),
                'line' => $th->getLine(),
                'trace' => $th->getTraceAsString(),
                'created_at' => now(),
            ]);
        }
    }
    private function updateqty($productdata, $orderqty)
    {

        if ($productdata) {
            $productNew = Product::find($productdata->id);

            $productNew->qty -= $orderqty;
            // Save the updated product data
            $productNew->save();

            return response()->json([
                'success' => true,
                'message' => 'Product quantity updated successfully.',
                'product' => $productNew
            ]);
        } else {
            return response()->json([
                'success' => false,
                'message' => 'Product not found.'
            ], 404);
        }
    }
    private function updateorder_qty($productdata, $orderqty)
    {

        if ($productdata) {
            $productNew = Product::find($productdata->id);
            $productNew->order += $orderqty;
            // Save the updated product data
            $productNew->save();

            return response()->json([
                'success' => true,
                'message' => 'Product order quantity updated successfully.',
                'product' => $productNew
            ]);
        } else {
            return response()->json([
                'success' => false,
                'message' => 'Product not found.'
            ], 404);
        }
    }

    private function remove_fromCart($productdata, $userid, $ordercolor)
    {
        try {
            $cart = Cart::where('productid', $productdata->id)->where('userid', $userid)->where('color', $ordercolor)->first();
            if ($cart) {
                $cart->delete();
                return response()->json([
                    'success' => true,
                    'message' => 'Product removed from cart successfully.',
                    'cart' => $cart
                ]);
            } else {
                return response()->json([
                    'success' => false,
                    'message' => 'Product not found in cart.'
                ], 404);
            }
        } catch (\Throwable $th) {
            //throw $th;
        }
    }

    public function order_confirmed_points(Request $request)
    {
        try {
            // Save the order and get the new order IDs
            $newOrderIds = $this->savepointsorder($request);

            if (!empty($newOrderIds['orderIds'])) {
                // Get specifically the newly created orders
                $newOrders = Order::whereIn('id', $newOrderIds['orderIds'])->get();

                // Flash a success message for the view
                session()->flash('new_order', true);

                return view('web.home.checkout.points_success', [
                    'orders' => $newOrders,
                    'totalamount' => $request->amount,
                ]);
            } else {
                return redirect()->back()->with('error', 'Failed to place order.');
            }
        } catch (\Exception $e) {
            // Log error
            DB::table('error_logs')->insert([
                'message' => $e->getMessage(),
                'file' => $e->getFile(),
                'line' => $e->getLine(),
                'trace' => $e->getTraceAsString(),
                'created_at' => now(),
            ]);

            return redirect()->back()->with('error', $e->getMessage());
        }
    }

    public function savepointsorder($request)
    {
        $newOrderIds = []; // Store new order IDs
        $orderItems = []; // For email content
        $productDetails = []; // For Koombiyo description
        $totalOrderAmount = 0;
        $totalServiceFee = 0;
        $totalTaxAmountSum = 0;

        try {
            // Security: Recalculate amount on server
            try {
                $verifiedAmount = $this->verifyTotalAmount($request->all());
                $request->merge(['amount' => $verifiedAmount]);
            } catch (\Exception $e) {
                throw new \Exception('Invalid order data: ' . $e->getMessage());
            }

            $user = Auth::user();
            if (!$user) {
                throw new \Exception('You must be logged in to pay with points.');
            }

            if ($user->recycling_points < $verifiedAmount) {
                throw new \Exception('Insufficient points to complete this order. Required: ' . $verifiedAmount . ', Available: ' . $user->recycling_points);
            }

            // Get shipping zone data
            $city_name = $request->cus_city ?? null;
            $areaData = $city_name ? Area::where('area_name', $city_name)->first() : null;

            // If area not found, default to Zone A (serviceid 1)
            $serviceid = $areaData ? $areaData->serviceid : 1;

            $zonedata = Shippingzone::where('id', $serviceid)->first();
            if (!$zonedata) {
                // Secondary fallback if specific zone or Zone A is missing from DB
                $zonedata = Shippingzone::where('id', 1)->first() ?: (object) ['id' => 1, 'price' => 425];
            }

            // Re-assign serviceid from zonedata for later use if needed
            $serviceid = $zonedata->id;

            // Process request data
            $productIds = !empty($request->productid) ? explode(',', $request->productid) : [];
            $colors = !empty($request->order_color) ? explode(',', $request->order_color) : [];
            $quantities = !empty($request->order_qty) ? explode(',', $request->order_qty) : [];

            if (count($productIds) === 0 || count($productIds) !== count($colors) || count($productIds) !== count($quantities)) {
                throw new \Exception('Invalid product data');
            }

            // Calculate shipping total using server-side data directly
            $totalWeightForShipping = 0;
            foreach ($productIds as $index => $productId) {
                $qty = (int) ($quantities[$index] ?? 1);
                $pData = DB::table('product')->select('weight')->where('id', $productId)->first();
                if ($pData) {
                    $totalWeightForShipping += ($pData->weight * $qty);
                }
            }

            $productweightcostAll = $totalWeightForShipping > 1000 ? floor(($totalWeightForShipping - 1000) / 1000) * 80 : 0;
            $serverShippingPrice = ($zonedata->price ?? 0) + $productweightcostAll;

            $itemCount = count($productIds);
            $baseShippingPerItem = $itemCount > 0 ? ($serverShippingPrice / $itemCount) : 0;

            // Process each product
            foreach ($productIds as $index => $productId) {
                $color = $colors[$index] ?? null;
                $quantity = (int) ($quantities[$index] ?? 1);

                if ($quantity <= 0)
                    continue;

                // Check for duplicate orders
                $existingOrder = Order::where('product_id', $productId)
                    ->where('color', $color)
                    ->where('userid', $user->id)
                    ->where('created_at', '>=', Carbon::now()->subMinutes(1))
                    ->first();

                if ($existingOrder)
                    continue;

                // Get product data with lock
                $productdata = DB::table('product')
                    ->join('product_color', 'product.id', '=', 'product_color.product_id')
                    ->select(
                        'product.id',
                        'product.product_name',
                        'product.product_price',
                        'product.cutted_price',
                        'product.qty',
                        'product.order',
                        'product.weight',
                        'product.product_image',
                        'product_color.product_color',
                        'product_color.price'
                    )
                    ->where('product.id', $productId)
                    ->where('product_color.product_color', $color)
                    ->lockForUpdate()
                    ->first();

                if (!$productdata)
                    continue;

                // Validate stock
                if ($productdata->qty < $quantity) {
                    throw new \Exception("Insufficient stock for product ID: {$productId}");
                }

                // Calculate prices
                $productPrice = ($productdata->price ?? $productdata->product_price) * $quantity;
                $productWeight = $productdata->weight * $quantity;
                // Weight cost is now handled via $baseShippingPerItem
                $service_fee = $baseShippingPerItem;
                $finalamount = $productPrice + $service_fee;


                // Create order
                $orderId = 'PTS-' . $request->order_id . '-' . substr(Str::uuid(), 0, 5);

                $order = new Order();
                $order->userid = $user->id;
                $order->zone_id = $zonedata->id;
                $order->order_id = $orderId;
                $order->product_id = $productId;
                $order->first_name = $request->cus_firstname;
                $order->last_name = $request->cus_lastname;
                $order->color = $color;
                $order->quantity = $quantity;
                $order->telephone = $request->cus_phone;
                $order->company = $request->cus_company;
                $order->email = $request->cus_email;
                $order->address_1 = $request->cus_address_one;
                $order->address_2 = $request->cus_address_two;
                $order->city = $request->cus_city;
                $order->district = $request->cus_district;
                $order->postcode = $request->cus_postcode;
                $order->ordernote = $request->order_note;
                $order->processing = 1;
                $order->payment_method = 'points';
                $order->service_fee = $service_fee;
                $order->total = $productPrice;
                $order->totalweight = $productWeight;

                // Calculate tax for this line item if corporate
                $lineTaxPercentage = 0;
                $lineTaxAmount = 0;
                if ($user && $user->is_corporate) {
                    $lineTaxPercentage = (float) \App\Models\SystemSetting::get('corporate_tax_percentage', 18.00);
                    $taxBaseSetting = \App\Models\SystemSetting::get('tax_calculation_base', 'selling_price');
                    $taxBasePrice = ($taxBaseSetting === 'cutted_price' && isset($productdata->cutted_price))
                        ? $productdata->cutted_price
                        : ($productdata->price ?? $productdata->product_price);

                    $lineTaxAmount = round(($taxBasePrice * $quantity * $lineTaxPercentage) / 100, 2);
                }
                $order->tax_amount = $lineTaxAmount;
                $order->tax_percentage = $lineTaxPercentage;
                $totalTaxAmountSum += $lineTaxAmount;

                $order->voucher_code = $request->voucher_code ?? null;

                if ($index === 0) {
                    $order->discount_amount = $request->discount_amount ?? 0;
                    $order->points_applied = $verifiedAmount;
                    $order->points_used_flag = 1;
                } else {
                    $order->discount_amount = 0;
                    $order->points_applied = 0;
                    $order->points_used_flag = 0;
                }
                $order->status = 1;

                DB::transaction(function () use ($order, $productdata, $quantity, $user, $productId, $color, $request, $index) {
                    $order->save();
                    $this->updateqty($productdata, $quantity);
                    $this->updateorder_qty($productdata, $quantity);
                    $this->updatecolorstock($productId, $color, $quantity);
                    $product = Product::find($productId);
                    if ($product) {
                        $this->remove_fromCart($product, $user->id, $color);
                    }
                    if ($index === 0 && !empty($request->voucher_code)) {
                        $voucher = \App\Models\Voucher::where('code', $request->voucher_code)->first();
                        if ($voucher && $voucher->isValid()) {
                            $voucher->update([
                                'redeemed_by' => $user->id,
                                'redeemed_at' => now()
                            ]);
                        }
                    }
                });

                // Store data for Koombiyo and emails
                $newOrderIds[] = $order->id;
                $newOrderIdsNO[] = $order->order_id;
                $totalOrderAmount += $productPrice;
                $totalServiceFee += $service_fee;

                $productDetails[] = [
                    'name' => $productdata->product_name,
                    'color' => $color,
                    'quantity' => $quantity,
                    'price' => $productdata->price ?? $productdata->product_price
                ];

                $orderItems[] = [
                    'product_id' => $productId,
                    'product_name' => $productdata->product_name,
                    'color' => $color,
                    'quantity' => $quantity,
                    'unit_price' => $productdata->price ?? $productdata->product_price,
                    'total_price' => $productPrice,
                    'service_fee' => $service_fee,
                    'final_amount' => $finalamount,
                    'settextcolor' => $this->setcolor($color),
                    'cutted_price' => $productdata->cutted_price
                ];
            }

            $taxPercentage = ($user && $user->is_corporate) ? (float) \App\Models\SystemSetting::get('corporate_tax_percentage', 18.00) : 0;
            $taxAmount = $totalTaxAmountSum;

            // Send emails if orders were created
            if (count($orderItems) > 0) {
                // Deduct points
                $user->recycling_points -= $verifiedAmount;
                $user->save();

                $discountAmount = !empty($request->voucher_code) ? ($request->discount_amount ?? 0) : 0;
                $orderdate = Carbon::today();

                // Generate Invoice
                $todayDate = date('Ymd');
                $todayCount = \App\Models\Invoice::withoutGlobalScopes()->whereDate('invoice_date', date('Y-m-d'))->count() + 1;
                do {
                    $invoiceNumber = 'INV-' . $todayDate . '-' . str_pad($todayCount, 4, '0', STR_PAD_LEFT);
                    $todayCount++;
                } while (\App\Models\Invoice::withoutGlobalScopes()->where('invoice_number', $invoiceNumber)->exists());

                $invoiceSubtotal = $totalOrderAmount;
                $invoiceTotal = $invoiceSubtotal + $totalServiceFee + $taxAmount - $discountAmount;

                $invoice = \App\Models\Invoice::create([
                    'invoice_number' => $invoiceNumber,
                    'order_id' => 'ORDER-' . implode('-', $newOrderIds),
                    'customer_name' => $request->cus_firstname . ' ' . $request->cus_lastname,
                    'customer_email' => $request->cus_email,
                    'billing_address' => $request->cus_address_one . ', ' . $request->cus_city,
                    'invoice_date' => now(),
                    'subtotal' => $invoiceSubtotal,
                    'tax_percentage' => $taxPercentage,
                    'tax_amount' => $taxAmount,
                    'shipping_cost' => $totalServiceFee,
                    'discount_amount' => $discountAmount,
                    'total_amount' => $invoiceTotal,
                    'status' => 'paid',
                    'points_applied' => $verifiedAmount,
                    'points_used_flag' => 1,
                ]);

                try {
                    $this->mailtoCustomer(
                        $request->cus_email,
                        $request->cus_firstname,
                        $newOrderIdsNO,
                        $orderItems,
                        $totalOrderAmount,
                        $totalServiceFee,
                        $request->cus_phone,
                        $request->cus_address_one,
                        $request->cus_address_two,
                        $orderdate,
                        $taxAmount,
                        $taxPercentage,
                        $discountAmount,
                        $invoice,
                        $verifiedAmount
                    );

                    $this->copyTransfer(
                        $request->cus_email,
                        $request->cus_firstname,
                        $newOrderIds,
                        $orderItems,
                        $totalOrderAmount,
                        $totalServiceFee,
                        $request->cus_phone,
                        $request->cus_address_one,
                        $request->cus_address_two,
                        $orderdate,
                        $taxAmount,
                        $taxPercentage,
                        $discountAmount,
                        $verifiedAmount
                    );
                } catch (\Exception $e) {
                    Log::error('Email sending failed: ' . $e->getMessage());
                }

                $this->sendToKoombiyo(
                    $request->cus_firstname,
                    $request->cus_phone,
                    trim($request->cus_address_one . ' ' . $request->cus_address_two),
                    $request->cus_city,
                    $request->cus_district,
                    $request->cus_postcode,
                    $request->order_note ?? 'Order from website',
                    $productDetails,
                    0, // Points cover full amount, COD collection is 0 LKR.
                    $newOrderIds
                );

            }

            return [
                'success' => true,
                'orderIds' => $newOrderIds
            ];
        } catch (\Throwable $th) {
            DB::table('error_logs')->insert([
                'message' => $th->getMessage(),
                'file' => $th->getFile(),
                'line' => $th->getLine(),
                'trace' => $th->getTraceAsString(),
                'created_at' => now(),
            ]);

            throw $th;
        }
    }
}
