<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Customer;
use App\Models\Invoice;
use App\Models\InvoiceDay;
use App\Models\InvoiceDayService;
use App\Models\InvoiceDayHotel;
use App\Models\InvoiceDayExtraService; // <-- fixed import case
use App\Models\DayDescription;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator;

class InvoiceController extends Controller
{
    /**
     * Get all invoices for a customer with details.
     */
    public function getCustomerInvoices($customerId)
    {
        $invoices = Invoice::where('customer_id', $customerId)
            ->with([
                'days' => function($query) {
                    $query->select('id', 'invoice_id', 'day_number', 'day_date', 
                                  'seasonal_hike_percentage', 'seasonal_sessions');
                },
                'days.services.service',
                'days.hotels.hotel',
                'days.extraServices.extraService',
                'days.dayDescriptions', // FIXED: Added comma here
                'user' // Include user relationship if needed
            ])
            ->get();

        return response()->json($invoices, 200);
    }

    /**
     * Get a detailed invoice.
     */
    public function details($invoiceId)
    {
        $invoice = Invoice::with([
            'customer',
            'user', // Include user who created/updated
            'days' => function($query) {
                $query->select('id', 'invoice_id', 'day_number', 'day_date', 
                              'seasonal_hike_percentage', 'seasonal_sessions');
            },
            'days.services.service',
            'days.hotels.hotel',
            'days.extraServices.extraService',
            'days.dayDescriptions'
        ])->find($invoiceId);

        if (!$invoice) {
            return response()->json(['message' => 'Invoice not found'], 404);
        }

        return response()->json($invoice, 200);
    }

    /**
     * Create a full invoice with days, services, hotels, and extra services.
     */
    public function createFullInvoice(Request $request)
    {
        $request->validate([
            'customer_id' => 'required|integer|exists:customers,id',
            'package_name' => 'required|string',
            'no_of_pax' => 'required|integer|min:1',
            'trip_days' => 'required|array|min:1',
            'trip_days.*.day_date' => 'required|date',
            'trip_days.*.services' => 'array',
            'trip_days.*.hotels' => 'array',
            'trip_days.*.extra_services' => 'array',
            'trip_days.*.day_descriptions' => 'array',
            // NEW: Seasonal data validation
            'trip_days.*.seasonal_hike_percentage' => 'nullable|numeric|min:0',
            'trip_days.*.seasonal_sessions' => 'nullable|array',
            'trip_days.*.seasonal_multiplier' => 'nullable|numeric|min:1',
            // Existing validations
            'tax_percentage' => 'nullable|numeric|min:0',
            'margin_percentage' => 'nullable|numeric|min:0',
            'discount_amount' => 'nullable|numeric|min:0',
            'billed_amount' => 'nullable|numeric|min:0',
            'margin_amount' => 'nullable|numeric|min:0',
            'tax_amount' => 'nullable|numeric|min:0',
            'final_price' => 'required|numeric|min:0',
            'type' => 'required|in:quotation,billing,Quotation,Billing',
        ]);

        DB::beginTransaction();
        try {
            // determine travel agent (fallback to 1 if none)
            $travelAgentId = auth()->user()->travel_agent_id ?? 1;
            $userId = auth()->id(); // Get the current user ID

            // normalize type to capitalized form used in model ('Quotation' / 'Billing')
            $type = ucfirst(strtolower($request->type));

            // Get travel agent name
            $travelAgent = \App\Models\TravelAgent::find($travelAgentId);
            $agentName = $travelAgent ? $travelAgent->name : 'Trip Cup Agent';

            // Create main invoice WITHOUT trip_code first (we need the ID)
            $invoice = Invoice::create([
                'travel_agent_id' => $travelAgentId,
                'user_id' => $userId, // Add user_id
                'customer_id' => $request->customer_id,
                'package_name' => $request->package_name,
                'duration_days' => count($request->trip_days),
                'no_of_pax' => $request->no_of_pax,
                'tour_start_day' => $request->trip_days[0]['day_date'],
                'tax_percentage' => $request->tax_percentage ?? 0,
                'margin_percentage' => $request->margin_percentage ?? 0,
                'discount_amount' => $request->discount_amount ?? 0,
                'billed_amount' => $request->billed_amount ?? 0,
                'margin_amount' => $request->margin_amount ?? 0,
                'tax_amount' => $request->tax_amount ?? 0,
                'final_price' => $request->final_price,
                'type' => $type,
                // default status for new invoice - can adjust if needed
                'status' => $type === 'Quotation' ? 'Pending' : 'Finalized',
                // trip_code will be set after we have the ID
            ]);

            // Now generate and set the actual trip_code with travel agent name
            $tripCode = Invoice::generateTripCode($invoice->id, $invoice->created_at, $agentName);
            $invoice->update(['trip_code' => $tripCode]);

            // Log seasonal data for debugging
            Log::info('Creating invoice with seasonal data', [
                'invoice_id' => $invoice->id,
                'travel_agent_id' => $travelAgentId,
                'days_count' => count($request->trip_days),
                'seasonal_data_present' => array_filter($request->trip_days, function($day) {
                    return isset($day['seasonal_hike_percentage']) && $day['seasonal_hike_percentage'] > 0;
                })
            ]);

            // Add trip days with seasonal data
            foreach ($request->trip_days as $index => $dayData) {
                $day = InvoiceDay::create([
                    'invoice_id' => $invoice->id,
                    'day_number' => $index + 1,
                    'day_date' => $dayData['day_date'],
                    // NEW: Store seasonal data
                    'seasonal_hike_percentage' => $dayData['seasonal_hike_percentage'] ?? 0,
                    'seasonal_sessions' => $dayData['seasonal_sessions'] ?? [],
                ]);

                // Log each day's seasonal data
                if (isset($dayData['seasonal_hike_percentage']) && $dayData['seasonal_hike_percentage'] > 0) {
                    Log::info('Day seasonal data stored', [
                        'invoice_day_id' => $day->id,
                        'day_number' => $index + 1,
                        'seasonal_hike_percentage' => $dayData['seasonal_hike_percentage'],
                        'seasonal_sessions_count' => count($dayData['seasonal_sessions'] ?? [])
                    ]);
                }

                // Add services
                foreach ($dayData['services'] ?? [] as $service) {
                    InvoiceDayService::create([
                        'invoice_day_id' => $day->id,
                        'service_id' => $service['service_id'],
                        'variation' => $service['variation'] ?? null,
                        'qty' => $service['qty'] ?? 1,
                        'unit_price' => $service['unit_price'] ?? 0,
                    ]);
                }

                // Add hotels
                foreach ($dayData['hotels'] ?? [] as $hotel) {
                    InvoiceDayHotel::create([
                        'invoice_day_id' => $day->id,
                        'hotel_id' => $hotel['hotel_id'],
                        'room_type' => $hotel['room_type'] ?? null,
                        'extra_bed' => $hotel['extra_bed'] ?? 0,
                        'price' => $hotel['price'] ?? 0,
                        'qty' => $hotel['rooms'] ?? 1,
                    ]);
                }

                // Add extra services
                foreach ($dayData['extra_services'] ?? [] as $extra) {
                    InvoiceDayExtraService::create([
                        'invoice_day_id' => $day->id,
                        'extra_service_id' => $extra['extra_service_id'],
                        'description' => $extra['description'] ?? null,
                        'price' => $extra['price'] ?? 0,
                        'quantity' => $extra['quantity'] ?? 1,
                    ]);
                }

                // Add day descriptions (many-to-many)
                foreach ($dayData['day_descriptions'] ?? [] as $descriptionId) {
                    $description = DayDescription::where('id', $descriptionId)
                        ->where('travel_agent_id', $travelAgentId)
                        ->first();

                    if ($description) {
                        // attach only if not already attached
                        if (! $day->dayDescriptions()->where('day_description_id', $descriptionId)->exists()) {
                            $day->dayDescriptions()->attach($descriptionId);
                        }
                    }
                }
            }

            DB::commit();

            // Load the complete invoice with seasonal data for response
            $invoiceWithSeasonal = $invoice->fresh()->load([
                'customer',
                'user',
                'days' => function($query) {
                    $query->select('id', 'invoice_id', 'day_number', 'day_date', 
                                  'seasonal_hike_percentage', 'seasonal_sessions');
                },
                'days.services.service',
                'days.hotels.hotel',
                'days.extraServices.extraService',
                'days.dayDescriptions'
            ]);

            // Log successful creation with seasonal summary
            $daysWithSeasonal = $invoiceWithSeasonal->days->filter(function($day) {
                return $day->seasonal_hike_percentage > 0;
            });

            Log::info('Invoice created successfully with seasonal pricing', [
                'invoice_id' => $invoice->id,
                'trip_code' => $tripCode,
                'total_days' => $invoiceWithSeasonal->days->count(),
                'days_with_seasonal' => $daysWithSeasonal->count(),
                'total_seasonal_impact' => $daysWithSeasonal->sum('seasonal_hike_percentage')
            ]);

            return response()->json([
                'message' => 'Invoice created successfully',
                'invoice' => $invoiceWithSeasonal,
                'seasonal_summary' => [
                    'total_days' => $invoiceWithSeasonal->days->count(),
                    'days_with_seasonal' => $daysWithSeasonal->count(),
                    'total_seasonal_impact' => $daysWithSeasonal->sum('seasonal_hike_percentage')
                ]
            ], 201);

        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('createFullInvoice error: ' . $e->getMessage());
            return response()->json(['error' => $e->getMessage()], 500);
        }
    }

    /**
     * Update existing invoice and its nested data.
     */
    public function update(Request $request, $id)
    {
        $request->validate([
            'customer_id' => 'required|integer|exists:customers,id',
            'package_name' => 'required|string',
            'no_of_pax' => 'required|integer|min:1',
            'trip_days' => 'required|array|min:1',
            'trip_days.*.day_date' => 'required|date',
            'trip_days.*.services' => 'array',
            'trip_days.*.hotels' => 'array',
            'trip_days.*.extra_services' => 'array',
            'trip_days.*.day_descriptions' => 'array',
            // NEW: Seasonal data validation
            'trip_days.*.seasonal_hike_percentage' => 'nullable|numeric|min:0',
            'trip_days.*.seasonal_sessions' => 'nullable|array',
            'trip_days.*.seasonal_multiplier' => 'nullable|numeric|min:1',
            // Existing validations
            'tax_percentage' => 'nullable|numeric|min:0',
            'margin_percentage' => 'nullable|numeric|min:0',
            'discount_amount' => 'nullable|numeric|min:0',
            'billed_amount' => 'nullable|numeric|min:0',
            'margin_amount' => 'nullable|numeric|min:0',
            'tax_amount' => 'nullable|numeric|min:0',
            'final_price' => 'required|numeric|min:0',
            'type' => 'required|in:quotation,billing,Quotation,Billing',
        ]);

        DB::beginTransaction();
        try {
            $invoice = Invoice::findOrFail($id);

            // normalize type
            $type = ucfirst(strtolower($request->type));

            $invoice->update([
                'customer_id' => $request->customer_id,
                'user_id' => auth()->id(), // Track who updated the invoice
                'package_name' => $request->package_name,
                'duration_days' => count($request->trip_days),
                'no_of_pax' => $request->no_of_pax,
                'tour_start_day' => $request->trip_days[0]['day_date'],
                'tax_percentage' => $request->tax_percentage ?? 0,
                'margin_percentage' => $request->margin_percentage ?? 0,
                'discount_amount' => $request->discount_amount ?? 0,
                'billed_amount' => $request->billed_amount ?? 0,
                'margin_amount' => $request->margin_amount ?? 0,
                'tax_amount' => $request->tax_amount ?? 0,
                'final_price' => $request->final_price,
                'type' => $type,
            ]);

            // Log update with seasonal data
            Log::info('Updating invoice with seasonal data', [
                'invoice_id' => $invoice->id,
                'days_count' => count($request->trip_days),
                'seasonal_data_present' => array_filter($request->trip_days, function($day) {
                    return isset($day['seasonal_hike_percentage']) && $day['seasonal_hike_percentage'] > 0;
                })
            ]);

            // Delete old nested data (children)
            foreach ($invoice->days as $day) {
                $day->services()->delete();
                $day->hotels()->delete();
                $day->extraServices()->delete();
                $day->dayDescriptions()->detach();
            }
            // delete invoice days
            $invoice->days()->delete();

            // Recreate nested data with seasonal information
            foreach ($request->trip_days as $index => $dayData) {
                $day = InvoiceDay::create([
                    'invoice_id' => $invoice->id,
                    'day_number' => $index + 1,
                    'day_date' => $dayData['day_date'],
                    // NEW: Store seasonal data
                    'seasonal_hike_percentage' => $dayData['seasonal_hike_percentage'] ?? 0,
                    'seasonal_sessions' => $dayData['seasonal_sessions'] ?? [],
                ]);

                // Log each day's seasonal data during update
                if (isset($dayData['seasonal_hike_percentage']) && $dayData['seasonal_hike_percentage'] > 0) {
                    Log::info('Day seasonal data updated', [
                        'invoice_day_id' => $day->id,
                        'day_number' => $index + 1,
                        'seasonal_hike_percentage' => $dayData['seasonal_hike_percentage'],
                        'seasonal_sessions_count' => count($dayData['seasonal_sessions'] ?? [])
                    ]);
                }

                foreach ($dayData['services'] ?? [] as $service) {
                    InvoiceDayService::create([
                        'invoice_day_id' => $day->id,
                        'service_id' => $service['service_id'],
                        'variation' => $service['variation'] ?? null,
                        'qty' => $service['qty'] ?? 1,
                        'unit_price' => $service['unit_price'] ?? 0,
                    ]);
                }

                foreach ($dayData['hotels'] ?? [] as $hotel) {
                    InvoiceDayHotel::create([
                        'invoice_day_id' => $day->id,
                        'hotel_id' => $hotel['hotel_id'],
                        'room_type' => $hotel['room_type'] ?? null,
                        'extra_bed' => $hotel['extra_bed'] ?? 0,
                        'price' => $hotel['price'] ?? 0,
                        'qty' => $hotel['rooms'] ?? 1,
                    ]);
                }

                foreach ($dayData['extra_services'] ?? [] as $extra) {
                    InvoiceDayExtraService::create([
                        'invoice_day_id' => $day->id,
                        'extra_service_id' => $extra['extra_service_id'],
                        'description' => $extra['description'] ?? null,
                        'price' => $extra['price'] ?? 0,
                        'quantity' => $extra['quantity'] ?? 1,
                    ]);
                }

                // Reattach day descriptions
                foreach ($dayData['day_descriptions'] ?? [] as $descriptionId) {
                    $description = DayDescription::where('id', $descriptionId)
                        ->where('travel_agent_id', $invoice->travel_agent_id)
                        ->first();

                    if ($description) {
                        if (! $day->dayDescriptions()->where('day_description_id', $descriptionId)->exists()) {
                            $day->dayDescriptions()->attach($descriptionId);
                        }
                    }
                }
            }

            DB::commit();

            // Load the updated invoice with seasonal data
            $invoiceWithSeasonal = $invoice->load([
                'customer',
                'user',
                'days' => function($query) {
                    $query->select('id', 'invoice_id', 'day_number', 'day_date', 
                                  'seasonal_hike_percentage', 'seasonal_sessions');
                },
                'days.services.service',
                'days.hotels.hotel',
                'days.extraServices.extraService',
                'days.dayDescriptions'
            ]);

            // Log successful update with seasonal summary
            $daysWithSeasonal = $invoiceWithSeasonal->days->filter(function($day) {
                return $day->seasonal_hike_percentage > 0;
            });

            Log::info('Invoice updated successfully with seasonal pricing', [
                'invoice_id' => $invoice->id,
                'total_days' => $invoiceWithSeasonal->days->count(),
                'days_with_seasonal' => $daysWithSeasonal->count(),
                'total_seasonal_impact' => $daysWithSeasonal->sum('seasonal_hike_percentage')
            ]);

            return response()->json([
                'message' => 'Invoice updated successfully',
                'invoice' => $invoiceWithSeasonal,
                'seasonal_summary' => [
                    'total_days' => $invoiceWithSeasonal->days->count(),
                    'days_with_seasonal' => $daysWithSeasonal->count(),
                    'total_seasonal_impact' => $daysWithSeasonal->sum('seasonal_hike_percentage')
                ]
            ], 200);

        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('Invoice update failed: ' . $e->getMessage());
            return response()->json(['error' => $e->getMessage()], 500);
        }
    }

    /**
     * Convert a quotation invoice to billing.
     */
    public function convertToBilling(Invoice $invoice)
    {
        if (!$invoice->canConvertToBilling()) {
            return response()->json([
                'success' => false,
                'message' => 'This quotation cannot be converted to billing.'
            ], 400);
        }

        try {
            $invoice->update([
                'type' => 'Billing',
                'status' => 'Finalized',
                'user_id' => auth()->id(), // Track who converted it
            ]);

            return response()->json([
                'success' => true,
                'message' => 'Quotation converted to billing successfully.',
                'invoice' => $invoice->fresh()
            ]);

        } catch (\Exception $e) {
            Log::error('Convert to billing failed: ' . $e->getMessage());

            return response()->json([
                'success' => false,
                'message' => 'Failed to convert quotation: ' . $e->getMessage()
            ], 500);
        }
    }

    /**
     * Remove the specified invoice from storage.
     */
    public function destroy($id)
    {
        DB::beginTransaction();
        try {
            $invoice = Invoice::findOrFail($id);

            // Delete all related records first
            foreach ($invoice->days as $day) {
                $day->services()->delete();
                $day->hotels()->delete();
                $day->extraServices()->delete();
                $day->dayDescriptions()->detach();
            }

            // Delete the invoice days
            $invoice->days()->delete();

            // Finally delete the invoice itself
            $invoice->delete();

            DB::commit();

            return response()->json([
                'message' => 'Invoice deleted successfully',
                'success' => true
            ], 200);

        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('Invoice delete failed: ' . $e->getMessage());
            return response()->json([
                'message' => 'Failed to delete invoice: ' . $e->getMessage(),
                'success' => false
            ], 500);
        }
    }

    /**
     * Cancel an invoice (trip)
     */
    public function cancelInvoice(Invoice $invoice, Request $request)
    {
        $request->validate([
            'cancellation_reason' => 'required|string|max:1000',
            'accept_refund_terms' => 'required|accepted'
        ]);

        // Check if invoice can be cancelled
        if ($invoice->isCancelled()) {
            return response()->json([
                'success' => false,
                'message' => 'This trip is already cancelled.'
            ], 400);
        }

        if (!$invoice->canBeCancelled()) {
            return response()->json([
                'success' => false,
                'message' => 'Cannot cancel a trip that has already started or completed.'
            ], 400);
        }

        try {
            DB::beginTransaction();

            // Calculate refund based on ACTUAL trip payments received
            $refundAmount = $invoice->calculateRefundAmount();
            $totalPaid = $invoice->calculateTotalPaid();
            $refundPolicy = $invoice->getRefundPolicyDescription();

            // Update invoice with cancellation details
            $invoice->update([
                'status' => 'Cancelled',
                'cancellation_reason' => $request->cancellation_reason,
                'cancelled_at' => now(),
                'refund_amount' => $refundAmount,
                'refundable_amount' => $refundAmount,
                'refund_status' => $refundAmount > 0 ? 'Pending' : 'Rejected',
                'refund_notes' => $refundPolicy,
                'user_id' => auth()->id(), // Track who cancelled it
            ]);

            DB::commit();

            return response()->json([
                'success' => true,
                'message' => 'Trip cancelled successfully.',
                'refund_amount' => $refundAmount,
                'total_paid' => $totalPaid,
                'refund_policy' => $refundPolicy,
                'payment_summary' => $invoice->getPaymentSummary(),
                'invoice' => $invoice->fresh()
            ]);

        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('Invoice cancellation failed: ' . $e->getMessage());

            return response()->json([
                'success' => false,
                'message' => 'Failed to cancel invoice: ' . $e->getMessage()
            ], 500);
        }
    }

    /**
     * Get comprehensive invoice details by trip code with seasonal data
     */
    public function getByTripCode($tripCode)
    {
        try {
            // Validate trip code format
            if (empty($tripCode) || strlen($tripCode) < 5) {
                return response()->json([
                    'success' => false,
                    'message' => 'Invalid trip code format'
                ], 400);
            }

            $invoice = Invoice::with([
                'customer',
                'user',
                'travelAgent',
                'days' => function($query) {
                    $query->select('id', 'invoice_id', 'day_number', 'day_date', 
                                  'seasonal_hike_percentage', 'seasonal_sessions')
                          ->orderBy('day_number', 'asc');
                },
                'days.services.service',
                'days.hotels.hotel',
                'days.extraServices.extraService',
                'days.dayDescriptions',
                'tripPayments' => function($query) {
                    $query->orderBy('payment_date', 'desc')
                          ->orderBy('created_at', 'desc');
                }
            ])->where('trip_code', $tripCode)->first();

            if (!$invoice) {
                return response()->json([
                    'success' => false,
                    'message' => 'Invoice not found with trip code: ' . $tripCode
                ], 404);
            }

            // Calculate all summaries
            $paymentSummary = $invoice->getPaymentSummary();
            $seasonalBreakdown = $invoice->getSeasonalBreakdown();
            $detailedSeasonalAnalysis = $this->getDetailedSeasonalAnalysis($invoice);
            
            // Calculate amounts using EXACT same logic as Flutter
            $calculatedAmounts = $this->calculateAmountsUsingFlutterLogic($invoice);

            // Log the access for analytics
            Log::info('Invoice accessed by trip code', [
                'trip_code' => $tripCode,
                'invoice_id' => $invoice->id,
                'user_id' => auth()->id(),
                'has_seasonal_pricing' => $invoice->hasSeasonalPricing()
            ]);

            return response()->json([
                'success' => true,
                'invoice' => $invoice,
                'payment_summary' => $paymentSummary,
                'seasonal_analysis' => $detailedSeasonalAnalysis,
                'calculated_amounts' => $calculatedAmounts,
                'seasonal_breakdown' => $seasonalBreakdown,
                'refund_policy' => $invoice->getRefundPolicyDescription(),
                'analytics' => [
                    'accessed_at' => now()->toISOString(),
                    'has_seasonal_pricing' => $invoice->hasSeasonalPricing(),
                    'seasonal_revenue_impact' => $invoice->calculateSeasonalRevenueImpact()
                ]
            ], 200);

        } catch (\Exception $e) {
            Log::error('Error fetching invoice by trip code: ' . $e->getMessage(), [
                'trip_code' => $tripCode,
                'user_id' => auth()->id(),
                'trace' => $e->getTraceAsString()
            ]);

            return response()->json([
                'success' => false,
                'message' => 'Failed to fetch invoice: ' . $e->getMessage()
            ], 500);
        }
    }

    /**
     * Search invoices by trip code (partial match)
     */
    public function searchByTripCode(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'trip_code' => 'required|string|min:3'
        ]);

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'errors' => $validator->errors()
            ], 422);
        }

        try {
            $invoices = Invoice::with(['customer', 'user'])
                ->where('trip_code', 'like', '%' . $request->trip_code . '%')
                ->orderBy('created_at', 'desc')
                ->limit(10)
                ->get(['id', 'trip_code', 'package_name', 'customer_id', 'final_price', 'status', 'type', 'created_at']);

            return response()->json([
                'success' => true,
                'data' => $invoices
            ], 200);

        } catch (\Exception $e) {
            Log::error('Error searching invoices by trip code: ' . $e->getMessage());
            return response()->json([
                'success' => false,
                'message' => 'Search failed'
            ], 500);
        }
    }

    /**
     * Calculate amounts using EXACT same logic as Flutter frontend
     */
    private function calculateAmountsUsingFlutterLogic(Invoice $invoice): array
    {
        $billedAmount = 0;
        $dailyBreakdown = [];

        foreach ($invoice->days as $day) {
            $dayDate = $day->day_date;
            $dayMultiplier = $day->seasonal_hike_percentage > 0 
                ? (1 + ($day->seasonal_hike_percentage / 100))
                : 1.0;

            $daySubtotal = 0;
            $dayBaseAmount = 0;

            // Services - EXACT same logic as Flutter
            foreach ($day->services as $service) {
                $price = $service->unit_price ?? 0;
                $quantity = $service->qty ?? 0;
                $daySubtotal += $price * $quantity;
                $dayBaseAmount += $price * $quantity;
            }

            // Hotels - EXACT same logic as Flutter
            foreach ($day->hotels as $hotel) {
                $price = $hotel->price ?? 0;
                $rooms = $hotel->qty ?? 0;
                $daySubtotal += $price * $rooms;
                $dayBaseAmount += $price * $rooms;
            }

            // Extra Services - EXACT same logic as Flutter
            foreach ($day->extraServices as $extra) {
                $price = $extra->price ?? 0;
                $quantity = $extra->quantity ?? 0;
                $daySubtotal += $price * $quantity;
                $dayBaseAmount += $price * $quantity;
            }

            // Apply seasonal multiplier to day subtotal - EXACT same as Flutter
            $dayTotalWithSeasonal = $daySubtotal * $dayMultiplier;
            $billedAmount += $dayTotalWithSeasonal;

            $dailyBreakdown[] = [
                'day_number' => $day->day_number,
                'date' => $dayDate,
                'base_amount' => round($dayBaseAmount, 2),
                'day_subtotal' => round($daySubtotal, 2),
                'seasonal_hike_percentage' => $day->seasonal_hike_percentage,
                'seasonal_multiplier' => $dayMultiplier,
                'day_total_with_seasonal' => round($dayTotalWithSeasonal, 2),
                'seasonal_impact' => round($dayTotalWithSeasonal - $daySubtotal, 2)
            ];
        }

        // Calculate other amounts using the same formulas as Flutter
        $marginPercentage = $invoice->margin_percentage ?? 0;
        $taxPercentage = $invoice->tax_percentage ?? 18;
        $discountAmount = $invoice->discount_amount ?? 0;

        $marginAmount = ($billedAmount * $marginPercentage / 100);
        $subtotalWithMargin = $billedAmount + $marginAmount;
        $taxAmount = ($subtotalWithMargin * $taxPercentage / 100);
        $finalPrice = $billedAmount + $marginAmount + $taxAmount - $discountAmount;

        return [
            'billed_amount' => round($billedAmount, 2),
            'margin_amount' => round($marginAmount, 2),
            'tax_amount' => round($taxAmount, 2),
            'discount_amount' => round($discountAmount, 2),
            'final_price' => round($finalPrice, 2),
            'daily_breakdown' => $dailyBreakdown,
            'calculation_method' => 'flutter_consistent',
            'formulas' => [
                'billed_amount' => 'sum(day_base_amount * (1 + seasonal_hike_percentage/100))',
                'margin_amount' => 'billed_amount * margin_percentage / 100',
                'tax_amount' => '(billed_amount + margin_amount) * tax_percentage / 100',
                'final_price' => 'billed_amount + margin_amount + tax_amount - discount_amount'
            ]
        ];
    }

    /**
     * Get detailed seasonal analysis for the invoice
     */
    private function getDetailedSeasonalAnalysis(Invoice $invoice): array
    {
        $daysWithSeasonal = $invoice->days->filter(function($day) {
            return $day->seasonal_hike_percentage > 0;
        });

        $dailyBreakdown = [];
        $totalBaseAmount = 0;
        $totalSeasonalAmount = 0;
        $sessionSummary = [];

        foreach ($invoice->days as $day) {
            $dayBaseAmount = $this->calculateDayBaseAmount($day);
            $seasonalMultiplier = $day->seasonal_hike_percentage > 0 
                ? (1 + ($day->seasonal_hike_percentage / 100))
                : 1.0;
            
            $seasonalAmount = $dayBaseAmount * ($day->seasonal_hike_percentage / 100);
            $dayTotalWithSeasonal = $dayBaseAmount * $seasonalMultiplier;
            
            $dailyBreakdown[] = [
                'day_number' => $day->day_number,
                'day_date' => $day->day_date,
                'base_amount' => round($dayBaseAmount, 2),
                'seasonal_hike_percentage' => $day->seasonal_hike_percentage,
                'seasonal_multiplier' => $seasonalMultiplier,
                'seasonal_amount' => round($seasonalAmount, 2),
                'total_day_amount' => round($dayTotalWithSeasonal, 2),
                'has_seasonal_pricing' => $day->seasonal_hike_percentage > 0,
                'seasonal_sessions' => $day->seasonal_sessions ?? [],
                'session_count' => count($day->seasonal_sessions ?? [])
            ];

            $totalBaseAmount += $dayBaseAmount;
            $totalSeasonalAmount += $seasonalAmount;

            // Process session summary
            $this->processSessionSummary($sessionSummary, $day, $seasonalAmount);
        }

        // Calculate percentages for session summary
        foreach ($sessionSummary as $sessionName => &$session) {
            $session['average_percentage'] = $session['total_percentage'] / $session['day_count'];
            $session['revenue_impact'] = round($session['revenue_impact'], 2);
            $session['percentage_of_total_seasonal'] = $totalSeasonalAmount > 0 ? 
                round(($session['revenue_impact'] / $totalSeasonalAmount) * 100, 2) : 0;
        }

        return [
            'summary' => [
                'total_days' => $invoice->days->count(),
                'days_with_seasonal' => $daysWithSeasonal->count(),
                'total_base_amount' => round($totalBaseAmount, 2),
                'total_seasonal_revenue' => round($totalSeasonalAmount, 2),
                'final_amount_with_seasonal' => round($totalBaseAmount + $totalSeasonalAmount, 2),
                'seasonal_impact_percentage' => $totalBaseAmount > 0 ? 
                    round(($totalSeasonalAmount / $totalBaseAmount) * 100, 2) : 0,
                'average_daily_hike' => $daysWithSeasonal->count() > 0 ? 
                    round($daysWithSeasonal->avg('seasonal_hike_percentage'), 2) : 0
            ],
            'daily_breakdown' => $dailyBreakdown,
            'session_analysis' => $sessionSummary,
            'seasonal_impact_on_final_price' => [
                'base_price_without_seasonal' => round($totalBaseAmount, 2),
                'total_seasonal_surcharge' => round($totalSeasonalAmount, 2),
                'percentage_of_final_price' => ($totalBaseAmount + $totalSeasonalAmount) > 0 ? 
                    round(($totalSeasonalAmount / ($totalBaseAmount + $totalSeasonalAmount)) * 100, 2) : 0
            ]
        ];
    }

    /**
     * Calculate day base amount (EXACT same as Flutter logic)
     */
    private function calculateDayBaseAmount(InvoiceDay $day): float
    {
        $total = 0;
        
        // Services - same logic as Flutter
        foreach ($day->services as $service) {
            $total += ($service->unit_price ?? 0) * ($service->qty ?? 1);
        }
        
        // Hotels - same logic as Flutter
        foreach ($day->hotels as $hotel) {
            $total += ($hotel->price ?? 0) * ($hotel->qty ?? 1);
        }
        
        // Extra services - same logic as Flutter
        foreach ($day->extraServices as $extra) {
            $total += ($extra->price ?? 0) * ($extra->quantity ?? 1);
        }
        
        return $total;
    }

    /**
     * Process session summary for seasonal analysis
     */
    private function processSessionSummary(array &$sessionSummary, InvoiceDay $day, float $seasonalAmount): void
    {
        foreach ($day->seasonal_sessions ?? [] as $session) {
            $sessionName = $session['name'] ?? 'Unknown';
            $sessionType = $session['type'] ?? 'regular';
            $sessionPercentage = $session['percentage'] ?? 0;
            
            if (!isset($sessionSummary[$sessionName])) {
                $sessionSummary[$sessionName] = [
                    'type' => $sessionType,
                    'total_percentage' => 0,
                    'day_count' => 0,
                    'affected_days' => [],
                    'revenue_impact' => 0,
                    'description' => $session['description'] ?? null
                ];
            }
            
            $sessionSummary[$sessionName]['total_percentage'] += $sessionPercentage;
            $sessionSummary[$sessionName]['day_count']++;
            $sessionSummary[$sessionName]['affected_days'][] = $day->day_number;
            
            // Calculate revenue impact proportionally based on session percentage
            if ($day->seasonal_hike_percentage > 0) {
                $sessionRevenueImpact = $seasonalAmount * ($sessionPercentage / $day->seasonal_hike_percentage);
                $sessionSummary[$sessionName]['revenue_impact'] += $sessionRevenueImpact;
            }
        }
    }

    /**
     * Get seasonal analytics for invoices
     */
    public function getSeasonalAnalytics(Request $request)
    {
        try {
            $validator = Validator::make($request->all(), [
                'travel_agent_id' => 'nullable|integer|exists:travel_agents,id',
                'start_date' => 'nullable|date',
                'end_date' => 'nullable|date|after_or_equal:start_date',
                'min_seasonal_impact' => 'nullable|numeric|min:0'
            ]);

            if ($validator->fails()) {
                return response()->json([
                    'success' => false,
                    'errors' => $validator->errors()
                ], 422);
            }

            $query = Invoice::with(['customer', 'travelAgent', 'days'])
                ->withSeasonalPricing();

            if ($request->travel_agent_id) {
                $query->where('travel_agent_id', $request->travel_agent_id);
            }

            if ($request->start_date) {
                $query->whereDate('created_at', '>=', $request->start_date);
            }

            if ($request->end_date) {
                $query->whereDate('created_at', '<=', $request->end_date);
            }

            $invoices = $query->get()->map(function($invoice) {
                $seasonalBreakdown = $invoice->getSeasonalBreakdown();
                
                return [
                    'id' => $invoice->id,
                    'trip_code' => $invoice->trip_code,
                    'package_name' => $invoice->package_name,
                    'final_price' => $invoice->final_price,
                    'customer_name' => $invoice->customer->name ?? 'N/A',
                    'travel_agent_name' => $invoice->travelAgent->name ?? 'N/A',
                    'seasonal_breakdown' => $seasonalBreakdown,
                    'days_with_seasonal' => $invoice->days->filter(fn($day) => $day->seasonal_hike_percentage > 0)->count(),
                    'total_seasonal_impact' => $invoice->days->sum('seasonal_hike_percentage'),
                    'seasonal_revenue_impact' => $invoice->calculateSeasonalRevenueImpact(),
                    'created_at' => $invoice->created_at
                ];
            });

            // Filter by minimum seasonal impact if provided
            if ($request->min_seasonal_impact) {
                $invoices = $invoices->filter(function($invoice) use ($request) {
                    return $invoice['seasonal_revenue_impact'] >= $request->min_seasonal_impact;
                })->values();
            }

            $totalSeasonalRevenue = $invoices->sum('seasonal_revenue_impact');

            return response()->json([
                'success' => true,
                'analytics' => [
                    'total_invoices' => $invoices->count(),
                    'total_seasonal_revenue' => $totalSeasonalRevenue,
                    'average_seasonal_impact' => $invoices->avg('total_seasonal_impact'),
                    'invoices_with_seasonal' => $invoices->count(),
                    'top_seasonal_sessions' => $this->getTopSeasonalSessions($invoices)
                ],
                'invoices' => $invoices
            ], 200);

        } catch (\Exception $e) {
            Log::error('Seasonal analytics error: ' . $e->getMessage());
            return response()->json([
                'success' => false,
                'message' => 'Failed to generate seasonal analytics'
            ], 500);
        }
    }

    /**
     * Get top seasonal sessions from invoices
     */
    private function getTopSeasonalSessions($invoices): array
    {
        $sessionUsage = [];
        
        foreach ($invoices as $invoiceData) {
            $invoice = Invoice::find($invoiceData['id']);
            $breakdown = $invoice->getSeasonalBreakdown();
            
            foreach ($breakdown['session_breakdown'] ?? [] as $sessionName => $sessionData) {
                if (!isset($sessionUsage[$sessionName])) {
                    $sessionUsage[$sessionName] = [
                        'count' => 0,
                        'total_revenue_impact' => 0,
                        'invoices' => []
                    ];
                }
                
                $sessionUsage[$sessionName]['count']++;
                $sessionUsage[$sessionName]['total_revenue_impact'] += $sessionData['revenue_impact'] ?? 0;
                $sessionUsage[$sessionName]['invoices'][] = $invoice->trip_code;
            }
        }
        
        // Sort by revenue impact
        uasort($sessionUsage, function($a, $b) {
            return $b['total_revenue_impact'] <=> $a['total_revenue_impact'];
        });
        
        return array_slice($sessionUsage, 0, 5);
    }

    /**
     * Verify calculation consistency between frontend and backend
     */
    public function verifyCalculationConsistency($tripCode)
    {
        try {
            $invoice = Invoice::with([
                'days.services',
                'days.hotels', 
                'days.extraServices'
            ])->where('trip_code', $tripCode)->first();

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

            // Backend stored values
            $storedAmounts = [
                'billed_amount' => $invoice->billed_amount,
                'margin_amount' => $invoice->margin_amount,
                'tax_amount' => $invoice->tax_amount,
                'final_price' => $invoice->final_price
            ];

            // Recalculated using Flutter logic
            $recalculatedAmounts = $this->calculateAmountsUsingFlutterLogic($invoice);

            $consistencyCheck = [
                'stored_values' => $storedAmounts,
                'recalculated_values' => $recalculatedAmounts,
                'differences' => [
                    'billed_amount' => abs($storedAmounts['billed_amount'] - $recalculatedAmounts['billed_amount']),
                    'margin_amount' => abs($storedAmounts['margin_amount'] - $recalculatedAmounts['margin_amount']),
                    'tax_amount' => abs($storedAmounts['tax_amount'] - $recalculatedAmounts['tax_amount']),
                    'final_price' => abs($storedAmounts['final_price'] - $recalculatedAmounts['final_price'])
                ],
                'is_consistent' => true
            ];

            // Check if differences are within acceptable rounding tolerance
            $tolerance = 0.01;
            foreach ($consistencyCheck['differences'] as $key => $difference) {
                if ($difference > $tolerance) {
                    $consistencyCheck['is_consistent'] = false;
                    break;
                }
            }

            return response()->json([
                'success' => true,
                'consistency_check' => $consistencyCheck,
                'invoice_id' => $invoice->id,
                'trip_code' => $tripCode
            ], 200);

        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Verification failed: ' . $e->getMessage()
            ], 500);
        }
    }

    // Add other existing methods like sendWhatsapp, sendEmail, generatePdf, etc.
    // ... your other existing methods ...
}