<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\PosOrder;
use App\Models\PosOrderItem;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class AdminOrderController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth:sanctum');
    }

    public function index(Request $request)
    {
        $user = $request->user();
        
        // Allow admin, restaurant owners, branch managers, and branch cashiers
        if (!$user->isAdmin() && !$user->isRestaurantOwner() && !$user->isBranchManager() && !$user->isBranchCashier()) {
            return response()->json(['error' => 'Unauthorized'], 403);
        }

        $query = PosOrder::withTrashed()->with(['table.floor', 'tables.floor', 'waiter', 'items.menuItem', 'branch', 'restaurant']);

        // Filter by restaurant for restaurant owners
        if ($user->isRestaurantOwner() && $user->restaurant_id) {
            $query->where('restaurant_id', $user->restaurant_id);
            
            // Require branch selection for restaurant owners
            if ($request->has('branch_id') && $request->branch_id) {
                // Verify branch belongs to restaurant
                $branch = \App\Models\Branch::find($request->branch_id);
                if ($branch && $branch->restaurant_id === $user->restaurant_id) {
                    $query->where('branch_id', $request->branch_id);
                } else {
                    return response()->json([
                        'error' => 'Invalid branch. Please select a valid branch.'
                    ], 422);
                }
            } else {
                // Return empty result if branch not selected
$perPage = min((int) $request->get('per_page', 50), 250);
                    return response()->json([
                        'data' => [],
                        'message' => 'Please select a branch to view orders.',
                        'current_page' => 1,
                        'last_page' => 1,
                        'per_page' => $perPage,
                        'total' => 0,
                    ]);
            }
        }

        // Filter by branch for branch managers and branch cashiers
        if (($user->isBranchManager() || $user->isBranchCashier()) && $user->branch_id) {
            $query->where('branch_id', $user->branch_id);
            // Also filter by restaurant if branch has restaurant_id
            $branch = \App\Models\Branch::find($user->branch_id);
            if ($branch && $branch->restaurant_id) {
                $query->where('restaurant_id', $branch->restaurant_id);
            }
        }

        // Handle branch timing-based date filters
        $useBranchTimings = $request->has('use_branch_timings') && $request->use_branch_timings == 'true';
        $quickFilter = $request->input('quick_filter', '');
        
        if ($useBranchTimings && in_array($quickFilter, ['today', 'yesterday'])) {
            // Get branch ID
            $branchId = null;
            if ($user && $user->branch_id) {
                $branchId = $user->branch_id;
            } elseif ($request->has('branch_id') && $request->branch_id) {
                $branchId = $request->branch_id;
            } elseif ($request->has('selectedBranchId') && $request->selectedBranchId) {
                $branchId = $request->selectedBranchId;
            }
            
            if ($branchId) {
                $branch = \App\Models\Branch::find($branchId);
                if ($branch && $branch->opening_time && $branch->closing_time) {
                    // Get restaurant timezone
                    $restaurantId = $branch->restaurant_id ?? ($user->restaurant_id ?? null);
                    $timezone = \App\Models\PosSetting::getSetting('timezone', $restaurantId, $branchId, '+05:00');
                    
                    // Parse timezone offset
                    $timezoneOffset = 0;
                    if (preg_match('/([+-])(\d{2}):(\d{2})/', $timezone, $matches)) {
                        $sign = $matches[1] === '+' ? 1 : -1;
                        $hours = (int)$matches[2];
                        $minutes = (int)$matches[3];
                        $timezoneOffset = $sign * ($hours * 60 + $minutes) * 60; // Offset in seconds
                    }
                    
                    // Determine target date
                    $now = \Carbon\Carbon::now('UTC');
                    if ($quickFilter === 'today') {
                        $targetDate = $now->copy();
                    } else { // yesterday
                        $targetDate = $now->copy()->subDay();
                    }
                    
                    // Parse opening and closing times (format: H:i:s or H:i)
                    $openingTimeParts = explode(':', $branch->opening_time);
                    $closingTimeParts = explode(':', $branch->closing_time);
                    $openingHour = (int)($openingTimeParts[0] ?? 13);
                    $openingMinute = (int)($openingTimeParts[1] ?? 0);
                    $closingHour = (int)($closingTimeParts[0] ?? 12);
                    $closingMinute = (int)($closingTimeParts[1] ?? 0);
                    
                    // Calculate opening datetime in restaurant timezone, then convert to UTC
                    $openingDateTime = $targetDate->copy()
                        ->setTime($openingHour, $openingMinute, 0)
                        ->subSeconds($timezoneOffset);
                    
                    // For closing time, check if it's next day (closing < opening)
                    $closingDateTime = $targetDate->copy()
                        ->setTime($closingHour, $closingMinute, 0)
                        ->subSeconds($timezoneOffset);
                    
                    // If closing time is earlier than opening time, it's next day
                    if ($closingHour < $openingHour || ($closingHour === $openingHour && $closingMinute < $openingMinute)) {
                        $closingDateTime->addDay();
                    }
                    
                    // Override date_from and date_to
                    $request->merge([
                        'date_from' => $openingDateTime->toIso8601String(),
                        'date_to' => $closingDateTime->toIso8601String(),
                    ]);
                }
            }
        }

        // Filter by orders_date (business day) when frontend sends these params (today/yesterday/last week/last month)
        if ($request->has('orders_date') && $request->orders_date !== '') {
            $query->where('orders_date', $request->orders_date);
        } elseif ($request->has('orders_date_from') || $request->has('orders_date_to')) {
            if ($request->has('orders_date_from') && $request->orders_date_from !== '') {
                $query->where('orders_date', '>=', $request->orders_date_from);
            }
            if ($request->has('orders_date_to') && $request->orders_date_to !== '') {
                $query->where('orders_date', '<=', $request->orders_date_to);
            }
        }
        // Otherwise filter by date range - frontend sends UTC ISO strings
        elseif ($request->has('date_from') && $request->date_from && $request->has('date_to') && $request->date_to) {
            try {
                // Parse the incoming dates (they are in UTC ISO format from frontend)
                // Frontend sends dates like "2025-01-20T19:00:00.000Z" (UTC) which represents
                // "2025-01-20 00:00:00 +05:00" (restaurant timezone start of day)
                $dateFrom = \Carbon\Carbon::parse($request->date_from)->setTimezone('UTC');
                $dateTo = \Carbon\Carbon::parse($request->date_to)->setTimezone('UTC');
                
                // Filter using UTC timestamps - orders are stored in UTC
                $query->whereBetween('created_at', [
                    $dateFrom->toDateTimeString(),
                    $dateTo->toDateTimeString()
                ]);
                
            } catch (\Exception $e) {
                // Fallback: try to parse as UTC dates with better error handling
                \Illuminate\Support\Facades\Log::warning('Date parsing failed in AdminOrderController index: ' . $e->getMessage(), [
                    'date_from' => $request->date_from,
                    'date_to' => $request->date_to,
                ]);
                try {
                    // Try parsing again with explicit UTC timezone
                    $dateFrom = \Carbon\Carbon::parse($request->date_from, 'UTC');
                    $dateTo = \Carbon\Carbon::parse($request->date_to, 'UTC');
                    $query->whereBetween('created_at', [
                        $dateFrom->toDateTimeString(),
                        $dateTo->toDateTimeString()
                    ]);
                } catch (\Exception $e2) {
                    // Last resort: don't apply date filter if parsing fails completely
                    \Illuminate\Support\Facades\Log::error('Date parsing completely failed in AdminOrderController: ' . $e2->getMessage());
                }
            }
        } elseif ($request->has('date_from') && $request->date_from) {
            try {
                $dateFrom = \Carbon\Carbon::parse($request->date_from)->setTimezone('UTC');
                $query->where('created_at', '>=', $dateFrom->toDateTimeString());
            } catch (\Exception $e) {
                \Illuminate\Support\Facades\Log::warning('Date parsing failed for date_from in AdminOrderController: ' . $e->getMessage());
            }
        } elseif ($request->has('date_to') && $request->date_to) {
            try {
                $dateTo = \Carbon\Carbon::parse($request->date_to)->setTimezone('UTC');
                $query->where('created_at', '<=', $dateTo->toDateTimeString());
            } catch (\Exception $e) {
                \Illuminate\Support\Facades\Log::warning('Date parsing failed for date_to in AdminOrderController: ' . $e->getMessage());
            }
        }

        // Filter by status (handle deleted orders)
        if ($request->has('status') && $request->status !== '') {
            if ($request->status === 'deleted') {
                // Show only deleted orders
                $query->onlyTrashed();
            } else {
                // Show only non-deleted orders with specific status
                $query->whereNull('deleted_at')->where('status', $request->status);
            }
        } else {
            // By default, show both deleted and non-deleted orders
            // But we can filter to show only non-deleted if needed
            if (!$request->has('include_deleted') || !$request->include_deleted) {
                $query->whereNull('deleted_at');
            }
            // If include_deleted is true, withTrashed() is already applied above
        }

        // Filter by payment status
        if ($request->has('is_paid') && $request->is_paid !== '') {
            $isPaid = filter_var($request->is_paid, FILTER_VALIDATE_BOOLEAN);
            if ($isPaid) {
                $query->where('status', 'paid');
            } else {
                $query->where('status', '!=', 'paid');
            }
        }

        // Filter by order type
        if ($request->has('order_type') && $request->order_type !== '') {
            $query->where('order_type', $request->order_type);
        }

        // Filter by food bill
        if ($request->has('is_food_bill') && $request->is_food_bill !== '') {
            $isFoodBill = filter_var($request->is_food_bill, FILTER_VALIDATE_BOOLEAN);
            $query->where('is_food_bill', $isFoodBill);
        }

        // Filter by payment mode
        if ($request->has('payment_mode') && $request->payment_mode !== '') {
            $query->where('payment_mode', $request->payment_mode);
        }

        // Filter by branch (for admin and restaurant owners)
        if ($request->has('branch_id') && $request->branch_id) {
            // For branch managers, validate that the requested branch_id matches their branch_id
            if ($user->isBranchManager() && $user->branch_id != $request->branch_id) {
                return response()->json(['error' => 'Unauthorized'], 403);
            }
            // For restaurant owners, validate that the branch belongs to their restaurant
            if ($user->isRestaurantOwner() && $user->restaurant_id) {
                $branch = \App\Models\Branch::find($request->branch_id);
                if (!$branch || $branch->restaurant_id != $user->restaurant_id) {
                    return response()->json(['error' => 'Unauthorized'], 403);
                }
            }
            $query->where('branch_id', $request->branch_id);
        }

        // Filter by restaurant (for admin)
        if ($request->has('restaurant_id') && $request->restaurant_id) {
            // For restaurant owners, validate that the requested restaurant_id matches their restaurant_id
            if ($user->isRestaurantOwner() && $user->restaurant_id != $request->restaurant_id) {
                return response()->json(['error' => 'Unauthorized'], 403);
            }
            // For branch managers, validate that the restaurant_id matches their branch's restaurant
            if ($user->isBranchManager() && $user->branch_id) {
                $branch = \App\Models\Branch::find($user->branch_id);
                if (!$branch || $branch->restaurant_id != $request->restaurant_id) {
                    return response()->json(['error' => 'Unauthorized'], 403);
                }
            }
            $query->where('restaurant_id', $request->restaurant_id);
        }

        // Search
        if ($request->has('search') && $request->search) {
            $search = $request->search;
            $query->where(function($q) use ($search) {
                $q->where('order_number', 'like', '%' . $search . '%')
                  ->orWhere('customer_name', 'like', '%' . $search . '%')
                  ->orWhere('customer_phone', 'like', '%' . $search . '%');
            });
        }

        $perPage = min((int) $request->get('per_page', 50), 250);
        $orders = $query->orderBy('created_at', 'desc')->paginate($perPage);

        return response()->json($orders);
    }

    public function show(PosOrder $order)
    {
        $user = request()->user();
        
        // Allow admin, restaurant owners, branch managers, and branch cashiers
        if (!$user->isAdmin() && !$user->isRestaurantOwner() && !$user->isBranchManager() && !$user->isBranchCashier()) {
            return response()->json(['error' => 'Unauthorized'], 403);
        }

        // Verify access
        if ($user->isRestaurantOwner() && $order->restaurant_id !== $user->restaurant_id) {
            return response()->json(['error' => 'Unauthorized'], 403);
        }
        if ($user->isBranchManager() && $order->branch_id !== $user->branch_id) {
            return response()->json(['error' => 'Unauthorized'], 403);
        }

        $order->load(['table.floor', 'tables.floor', 'waiter', 'items.menuItem', 'branch', 'restaurant']);
        $currency = \App\Models\PosSetting::getSetting('currency', $order->restaurant_id, $order->branch_id, 'PKR');
        $order->currency = $currency;
        return response()->json($order);
    }

    public function update(Request $request, PosOrder $order)
    {
        $user = $request->user();
        
        // Allow admin, restaurant owners, branch managers, and branch cashiers
        if (!$user->isAdmin() && !$user->isRestaurantOwner() && !$user->isBranchManager() && !$user->isBranchCashier()) {
            return response()->json(['error' => 'Unauthorized'], 403);
        }

        // Verify access - ensure proper type casting for comparison
        if ($user->isRestaurantOwner()) {
            $orderRestaurantId = (int) $order->restaurant_id;
            $userRestaurantId = (int) $user->restaurant_id;
            if ($orderRestaurantId !== $userRestaurantId) {
                return response()->json(['error' => 'Unauthorized. You can only update orders from your own restaurant.'], 403);
            }
        }
        if ($user->isBranchManager()) {
            $orderBranchId = $order->branch_id ? (int) $order->branch_id : null;
            $userBranchId = $user->branch_id ? (int) $user->branch_id : null;
            if ($orderBranchId !== $userBranchId) {
                return response()->json(['error' => 'Unauthorized. You can only update orders from your own branch.'], 403);
            }
        }

        $validated = $request->validate([
            'status' => 'sometimes|in:pending,confirmed,preparing,ready,completed,paid,cancelled',
            'customer_name' => 'sometimes|string|max:255',
            'customer_phone' => 'sometimes|string|max:20',
            'notes' => 'nullable|string',
        ]);

        $order->update($validated);
        $order->load(['table.floor', 'tables.floor', 'waiter', 'items.menuItem', 'branch', 'restaurant']);

        return response()->json($order);
    }

    public function destroy(Request $request, PosOrder $order)
    {
        $user = request()->user();
        
        // Allow admin, restaurant owners, branch managers, and branch cashiers
        if (!$user->isAdmin() && !$user->isRestaurantOwner() && !$user->isBranchManager() && !$user->isBranchCashier()) {
            return response()->json(['error' => 'Unauthorized'], 403);
        }

        // Verify access - ensure proper type casting for comparison
        if ($user->isRestaurantOwner()) {
            $orderRestaurantId = (int) $order->restaurant_id;
            $userRestaurantId = (int) $user->restaurant_id;
            if ($orderRestaurantId !== $userRestaurantId) {
                return response()->json(['error' => 'Unauthorized. You can only delete orders from your own restaurant.'], 403);
            }
        }
        if ($user->isBranchManager()) {
            $orderBranchId = $order->branch_id ? (int) $order->branch_id : null;
            $userBranchId = $user->branch_id ? (int) $user->branch_id : null;
            if ($orderBranchId !== $userBranchId) {
                return response()->json(['error' => 'Unauthorized. You can only delete orders from your own branch.'], 403);
            }
        }

        // Validate delete comment
        $validated = $request->validate([
            'delete_comment' => 'required|string|min:3|max:500',
        ]);

        DB::beginTransaction();
        try {
            // Save deleted_by and delete_comment before soft deleting
            $order->deleted_by = $user->name;
            $order->delete_comment = $validated['delete_comment'];
            $order->save();
            
            // Delete order items first
            $order->items()->delete();
            
            // Soft delete the order
            $order->delete();
            
            DB::commit();

            return response()->json(['message' => 'Order deleted successfully']);
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json(['error' => 'Failed to delete order: ' . $e->getMessage()], 500);
        }
    }

    public function markAsPaid(Request $request, PosOrder $order)
    {
        $user = $request->user();
        
        // Allow admin, restaurant owners, branch managers, and branch cashiers
        if (!$user->isAdmin() && !$user->isRestaurantOwner() && !$user->isBranchManager() && !$user->isBranchCashier()) {
            return response()->json(['error' => 'Unauthorized'], 403);
        }

        // Verify access
        if ($user->isRestaurantOwner() && $order->restaurant_id !== $user->restaurant_id) {
            return response()->json(['error' => 'Unauthorized'], 403);
        }
        if ($user->isBranchManager() && $order->branch_id !== $user->branch_id) {
            return response()->json(['error' => 'Unauthorized'], 403);
        }

        $validated = $request->validate([
            'payment_mode' => 'required|string|in:cash,card,digital,online',
            'payment_amount' => 'required|numeric|min:0',
            'notes' => 'nullable|string|max:1000',
        ]);

        $order->update([
            'status' => 'paid',
            'is_paid' => true,
            'paid_at' => now(),
            'paid_by' => $user->name,
            'paid_by_id' => $user->id,
            'payment_mode' => $validated['payment_mode'],
            'payment_amount' => $validated['payment_amount'],
            'notes' => $validated['notes'] ?? $order->notes,
        ]);

        $order->load(['table.floor', 'tables.floor', 'waiter', 'items.menuItem', 'branch', 'restaurant']);

        return response()->json($order);
    }

    public function getStats(Request $request)
    {
        $user = $request->user();
        
        // Allow admin, restaurant owners, branch managers, and branch cashiers
        if (!$user->isAdmin() && !$user->isRestaurantOwner() && !$user->isBranchManager() && !$user->isBranchCashier()) {
            return response()->json(['error' => 'Unauthorized'], 403);
        }

        $query = PosOrder::query()->whereNull('deleted_at'); // Exclude deleted orders from stats

        // Filter by restaurant for restaurant owners
        if ($user->isRestaurantOwner() && $user->restaurant_id) {
            $query->where('restaurant_id', $user->restaurant_id);
        }

        // Filter by branch for branch managers and branch cashiers
        if (($user->isBranchManager() || $user->isBranchCashier()) && $user->branch_id) {
            $query->where('branch_id', $user->branch_id);
            // Also filter by restaurant if branch has restaurant_id
            $branch = \App\Models\Branch::find($user->branch_id);
            if ($branch && $branch->restaurant_id) {
                $query->where('restaurant_id', $branch->restaurant_id);
            }
        }

        // Filter by restaurant (for admin)
        if ($request->has('restaurant_id') && $request->restaurant_id) {
            // For restaurant owners, validate that the requested restaurant_id matches their restaurant_id
            if ($user->isRestaurantOwner() && $user->restaurant_id != $request->restaurant_id) {
                return response()->json(['error' => 'Unauthorized'], 403);
            }
            $query->where('restaurant_id', $request->restaurant_id);
        }

        // Filter by branch (for admin and restaurant owners)
        if ($request->has('branch_id') && $request->branch_id) {
            // For branch managers, validate that the requested branch_id matches their branch_id
            if ($user->isBranchManager() && $user->branch_id != $request->branch_id) {
                return response()->json(['error' => 'Unauthorized'], 403);
            }
            // For restaurant owners, validate that the branch belongs to their restaurant
            if ($user->isRestaurantOwner() && $user->restaurant_id) {
                $branch = \App\Models\Branch::find($request->branch_id);
                if (!$branch || $branch->restaurant_id != $user->restaurant_id) {
                    return response()->json(['error' => 'Unauthorized'], 403);
                }
            }
            $query->where('branch_id', $request->branch_id);
        }

        // Filter by date range - frontend sends UTC ISO strings
        // Frontend sends dates that have already been converted from restaurant timezone to UTC
        if ($request->has('date_from') && $request->date_from && $request->has('date_to') && $request->date_to) {
            try {
                // Parse the incoming dates (they are in UTC ISO format from frontend)
                // Frontend sends dates like "2025-01-20T19:00:00.000Z" (UTC) which represents
                // "2025-01-20 00:00:00 +05:00" (restaurant timezone start of day)
                $dateFrom = \Carbon\Carbon::parse($request->date_from)->setTimezone('UTC');
                $dateTo = \Carbon\Carbon::parse($request->date_to)->setTimezone('UTC');
                
                // Filter using UTC timestamps - orders are stored in UTC
                $query->whereBetween('created_at', [
                    $dateFrom->toDateTimeString(),
                    $dateTo->toDateTimeString()
                ]);
                
            } catch (\Exception $e) {
                // Fallback: try to parse as UTC dates with better error handling
                \Illuminate\Support\Facades\Log::warning('Date parsing failed in AdminOrderController getStats: ' . $e->getMessage(), [
                    'date_from' => $request->date_from,
                    'date_to' => $request->date_to,
                ]);
                try {
                    // Try parsing again with explicit UTC timezone
                    $dateFrom = \Carbon\Carbon::parse($request->date_from, 'UTC');
                    $dateTo = \Carbon\Carbon::parse($request->date_to, 'UTC');
                    $query->whereBetween('created_at', [
                        $dateFrom->toDateTimeString(),
                        $dateTo->toDateTimeString()
                    ]);
                } catch (\Exception $e2) {
                    // Last resort: don't apply date filter if parsing fails completely
                    \Illuminate\Support\Facades\Log::error('Date parsing completely failed in AdminOrderController getStats: ' . $e2->getMessage());
                }
            }
        } elseif ($request->has('date_from') && $request->date_from) {
            $query->whereDate('created_at', '>=', $request->date_from);
        } elseif ($request->has('date_to') && $request->date_to) {
            $query->whereDate('created_at', '<=', $request->date_to);
        }

        $orders = $query->get();

        $restaurantId = $request->get('restaurant_id') ?: ($user->restaurant_id ?? ($orders->first() ? $orders->first()->restaurant_id : null));
        $branchId = $request->get('branch_id') ?: ($user->branch_id ?? ($orders->first() ? $orders->first()->branch_id : null));
        $currency = \App\Models\PosSetting::getSetting('currency', $restaurantId, $branchId, 'PKR');

        return response()->json([
            'total_orders' => $orders->count(),
            'total_revenue' => $orders->sum('grand_total'),
            'total_amount' => $orders->sum('grand_total'),
            'total_subtotal' => $orders->sum('subtotal'),
            'total_service_charge' => $orders->sum('service_charge'),
            'total_tax' => $orders->sum('tax'),
            'total_discount' => $orders->sum('discount'),
            'paid_orders' => $orders->where('status', 'paid')->count(),
            'paid_revenue' => $orders->where('status', 'paid')->sum('grand_total'),
            'unpaid_orders' => $orders->where('status', '!=', 'paid')->count(),
            'unpaid_revenue' => $orders->where('status', '!=', 'paid')->sum('grand_total'),
            'average_order_value' => $orders->count() > 0 ? $orders->avg('grand_total') : 0,
            'currency' => $currency,
        ]);
    }
}

