<?php

namespace App\Http\Controllers;

use App\Models\Order;
use App\Models\OrderItem;
use App\Models\Product;
use App\Models\Appointment;
use App\Models\AuditLog;
use App\Models\SystemSetting;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\DB;

class OrderController extends Controller
{
    /**
     * Display a listing of the authenticated user's orders
     */
    public function index(Request $request)
    {
        try {
            $user = auth()->user();
            
            $query = Order::with(['items.product', 'payments', 'appointment'])
                ->byCustomer($user->id);

            // Filter by status
            if ($request->has('status') && $request->status) {
                $query->where('status', $request->status);
            }

            // Filter by payment status
            if ($request->has('payment_status') && $request->payment_status) {
                $query->where('payment_status', $request->payment_status);
            }

            // Sort options
            $sortBy = $request->get('sort_by', 'created_at');
            $sortOrder = $request->get('sort_order', 'desc');
            $query->orderBy($sortBy, $sortOrder);

            // Pagination
            $perPage = $request->get('per_page', 10);
            $orders = $query->paginate($perPage);

            return response()->json([
                'success' => true,
                'message' => 'Orders retrieved successfully',
                'data' => [
                    'orders' => $orders->items(),
                    'pagination' => [
                        'current_page' => $orders->currentPage(),
                        'per_page' => $orders->perPage(),
                        'total' => $orders->total(),
                        'last_page' => $orders->lastPage(),
                    ]
                ]
            ]);

        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Failed to retrieve orders',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Display the specified order
     */
    public function show($id)
    {
        try {
            $user = auth()->user();
            
            $order = Order::with([
                'items.product', 
                'payments', 
                'appointment',
                'customer'
            ])->find($id);

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

            // Check if user owns the order or is admin
            if ($order->customer_id != $user->id && !$user->isAdmin()) {
                return response()->json([
                    'success' => false,
                    'message' => 'Unauthorized to view this order'
                ], 403);
            }

            return response()->json([
                'success' => true,
                'message' => 'Order retrieved successfully',
                'data' => [
                    'order' => $order
                ]
            ]);

        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Failed to retrieve order',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Store a newly created order (booking)
     */
    public function store(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'items' => 'required|array|min:1',
            'items.*.product_id' => 'required|exists:products,id',
            'items.*.quantity' => 'required|integer|min:1',
            'items.*.service_date' => 'required|date|after_or_equal:today',
            'items.*.service_time' => 'required|date_format:H:i',
            'customer_name' => 'required|string|max:255',
            'customer_email' => 'required|email|max:255',
            'customer_phone' => 'required|string|max:20',
            'vehicle_make' => 'required|string|max:255',
            'vehicle_model' => 'required|string|max:255',
            'vehicle_year' => 'nullable|integer|min:1900|max:' . (date('Y') + 1),
            'vehicle_registration' => 'nullable|string|max:20',
            'special_instructions' => 'nullable|string',
            'booking_date' => 'required|date|after_or_equal:today',
            'booking_time' => 'required|date_format:H:i',
        ]);

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

        try {
            DB::beginTransaction();
            
            $user = auth()->user();
            
            // Calculate order totals
            $totalAmount = 0;
            $items = [];

            foreach ($request->items as $itemData) {
                $product = Product::active()->find($itemData['product_id']);
                
                if (!$product) {
                    DB::rollBack();
                    return response()->json([
                        'success' => false,
                        'message' => "Product with ID {$itemData['product_id']} not found or inactive"
                    ], 422);
                }

                $unitPrice = $product->final_price;
                $itemTotal = $unitPrice * $itemData['quantity'];
                $totalAmount += $itemTotal;

                $items[] = [
                    'product' => $product,
                    'quantity' => $itemData['quantity'],
                    'unit_price' => $unitPrice,
                    'total_price' => $itemTotal,
                    'service_date' => $itemData['service_date'],
                    'service_time' => $itemData['service_time'],
                    'duration' => $product->duration,
                ];
            }

            // Create order
            $order = Order::create([
                'order_number' => Order::generateOrderNumber(),
                'customer_id' => $user->id,
                'total_amount' => $totalAmount,
                'discount_amount' => 0,
                'tax_amount' => 0,
                'final_amount' => $totalAmount,
                'status' => 'pending',
                'payment_status' => 'pending',
                'booking_date' => $request->booking_date,
                'booking_time' => $request->booking_time,
                'customer_name' => $request->customer_name,
                'customer_email' => $request->customer_email,
                'customer_phone' => $request->customer_phone,
                'vehicle_make' => $request->vehicle_make,
                'vehicle_model' => $request->vehicle_model,
                'vehicle_year' => $request->vehicle_year,
                'vehicle_registration' => $request->vehicle_registration,
                'special_instructions' => $request->special_instructions,
                'created_by' => $user->id,
            ]);

            // Create order items
            foreach ($items as $item) {
                OrderItem::create([
                    'order_id' => $order->id,
                    'product_id' => $item['product']->id,
                    'quantity' => $item['quantity'],
                    'unit_price' => $item['unit_price'],
                    'total_price' => $item['total_price'],
                    'duration' => $item['duration'],
                    'service_date' => $item['service_date'],
                    'service_time' => $item['service_time'],
                ]);
            }

            // Create appointment
            $appointment = Appointment::create([
                'order_id' => $order->id,
                'customer_id' => $user->id,
                'customer_name' => $request->customer_name,
                'customer_phone' => $request->customer_phone,
                'customer_email' => $request->customer_email,
                'car_make' => $request->vehicle_make,
                'car_model' => $request->vehicle_model,
                'car_year' => $request->vehicle_year,
                'vehicle_registration' => $request->vehicle_registration,
                'service_type' => 'Window Tinting Service', // Default service type
                'appointment_date' => $request->booking_date,
                'appointment_time' => $request->booking_time,
                'service_date' => $request->booking_date,
                'service_time' => $request->booking_time,
                'duration' => array_sum(array_column($items, 'duration')),
                'status' => 'scheduled',
                'notes' => $request->special_instructions,
            ]);

            // Log the creation
            AuditLog::logCreate($user, $order, $request);

            DB::commit();

            return response()->json([
                'success' => true,
                'message' => 'Order created successfully',
                'data' => [
                    'order' => $order->load(['items.product', 'appointment']),
                    'appointment' => $appointment
                ]
            ], 201);

        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json([
                'success' => false,
                'message' => 'Failed to create order',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Cancel an order
     */
    public function cancel($id)
    {
        try {
            $user = auth()->user();
            $order = Order::find($id);

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

            // Check if user owns the order
            if ($order->customer_id != $user->id) {
                return response()->json([
                    'success' => false,
                    'message' => 'Unauthorized to cancel this order'
                ], 403);
            }

            // Check if order can be cancelled
            if (!in_array($order->status, ['pending', 'confirmed'])) {
                return response()->json([
                    'success' => false,
                    'message' => 'Order cannot be cancelled in its current status'
                ], 422);
            }

            $order->update([
                'status' => 'cancelled',
                'cancelled_at' => now(),
            ]);

            // Update appointment status
            if ($order->appointment) {
                $order->appointment->update([
                    'status' => 'cancelled',
                    'cancelled_at' => now(),
                    'cancellation_reason' => 'Cancelled by customer',
                ]);
            }

            // Log the cancellation
            AuditLog::log($user, 'cancel', $order, null, null, request());

            return response()->json([
                'success' => true,
                'message' => 'Order cancelled successfully',
                'data' => [
                    'order' => $order->load(['items.product', 'appointment'])
                ]
            ]);

        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Failed to cancel order',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Get order history for authenticated user
     */
    public function orderHistory(Request $request)
    {
        try {
            $user = auth()->user();
            
            $query = Order::with(['items.product', 'payments'])
                ->byCustomer($user->id)
                ->whereIn('status', ['completed', 'cancelled']);

            // Filter by date range
            if ($request->has('start_date') && $request->has('end_date')) {
                $query->byDateRange($request->start_date, $request->end_date);
            }

            // Sort by creation date (most recent first)
            $query->orderBy('created_at', 'desc');

            // Pagination
            $perPage = $request->get('per_page', 10);
            $orders = $query->paginate($perPage);

            return response()->json([
                'success' => true,
                'message' => 'Order history retrieved successfully',
                'data' => [
                    'orders' => $orders->items(),
                    'pagination' => [
                        'current_page' => $orders->currentPage(),
                        'per_page' => $orders->perPage(),
                        'total' => $orders->total(),
                        'last_page' => $orders->lastPage(),
                    ]
                ]
            ]);

        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Failed to retrieve order history',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Display a listing of all orders (admin only)
     */
    public function adminIndex(Request $request)
    {
        try {
            $query = Order::with(['items.product', 'payments', 'appointment', 'customer']);

            // Filter by status
            if ($request->has('status') && $request->status) {
                $query->where('status', $request->status);
            }

            // Filter by payment status
            if ($request->has('payment_status') && $request->payment_status) {
                $query->where('payment_status', $request->payment_status);
            }

            // Filter by date range
            if ($request->has('start_date') && $request->has('end_date')) {
                $query->byDateRange($request->start_date, $request->end_date);
            }

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

            // Sort options
            $sortBy = $request->get('sort_by', 'created_at');
            $sortOrder = $request->get('sort_order', 'desc');
            $query->orderBy($sortBy, $sortOrder);

            // Pagination
            $perPage = $request->get('per_page', 15);
            $orders = $query->paginate($perPage);

            return response()->json([
                'success' => true,
                'message' => 'Orders retrieved successfully',
                'data' => [
                    'orders' => $orders->items(),
                    'pagination' => [
                        'current_page' => $orders->currentPage(),
                        'per_page' => $orders->perPage(),
                        'total' => $orders->total(),
                        'last_page' => $orders->lastPage(),
                    ]
                ]
            ]);

        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Failed to retrieve orders',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Update order status (admin only)
     */
    public function updateStatus(Request $request, $id)
    {
        $validator = Validator::make($request->all(), [
            'status' => 'required|in:pending,confirmed,in_progress,completed,cancelled',
            'notes' => 'nullable|string',
        ]);

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

        try {
            $user = auth()->user();
            $order = Order::with(['appointment'])->find($id);

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

            $oldStatus = $order->status;
            $order->update(['status' => $request->status]);

            // Update appointment status if exists
            if ($order->appointment) {
                $order->appointment->update(['status' => $request->status]);
                
                // Mark as completed if order is completed
                if ($request->status === 'completed') {
                    $order->appointment->update(['completed_at' => now()]);
                }
            }

            // Log the status update
            AuditLog::log($user, 'status_update', $order, ['status' => $oldStatus], ['status' => $request->status], request());

            return response()->json([
                'success' => true,
                'message' => 'Order status updated successfully',
                'data' => [
                    'order' => $order->load(['items.product', 'appointment'])
                ]
            ]);

        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Failed to update order status',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Assign technician to order (admin only)
     */
    public function assignTechnician(Request $request, $id)
    {
        $validator = Validator::make($request->all(), [
            'technician_id' => 'required|exists:users,id',
        ]);

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

        try {
            $user = auth()->user();
            $order = Order::with(['appointment'])->find($id);

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

            // Update appointment with assigned technician
            if ($order->appointment) {
                $order->appointment->update(['assigned_to' => $request->technician_id]);
            }

            // Log the assignment
            AuditLog::log($user, 'assign_technician', $order, null, ['technician_id' => $request->technician_id], request());

            return response()->json([
                'success' => true,
                'message' => 'Technician assigned successfully',
                'data' => [
                    'order' => $order->load(['items.product', 'appointment.assignedTechnician'])
                ]
            ]);

        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Failed to assign technician',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Generate sales report (admin only)
     */
    public function salesReport(Request $request)
    {
        try {
            $startDate = $request->get('start_date', now()->subMonth()->format('Y-m-d'));
            $endDate = $request->get('end_date', now()->format('Y-m-d'));

            $report = DB::table('orders')
                ->select(
                    DB::raw('COUNT(*) as total_orders'),
                    DB::raw('SUM(final_amount) as total_revenue'),
                    DB::raw('AVG(final_amount) as average_order_value'),
                    DB::raw('COUNT(CASE WHEN status = "completed" THEN 1 END) as completed_orders'),
                    DB::raw('COUNT(CASE WHEN status = "cancelled" THEN 1 END) as cancelled_orders'),
                    DB::raw('COUNT(CASE WHEN payment_status = "paid" THEN 1 END) as paid_orders')
                )
                ->whereBetween('created_at', [$startDate, $endDate])
                ->first();

            // Daily sales trend
            $dailyTrend = DB::table('orders')
                ->select(
                    DB::raw('DATE(created_at) as date'),
                    DB::raw('COUNT(*) as order_count'),
                    DB::raw('SUM(final_amount) as daily_revenue')
                )
                ->whereBetween('created_at', [$startDate, $endDate])
                ->groupBy('date')
                ->orderBy('date')
                ->get();

            // Top products
            $topProducts = DB::table('order_items')
                ->join('products', 'order_items.product_id', '=', 'products.id')
                ->select(
                    'products.name',
                    DB::raw('SUM(order_items.quantity) as total_quantity'),
                    DB::raw('SUM(order_items.total_price) as total_revenue')
                )
                ->whereBetween('order_items.created_at', [$startDate, $endDate])
                ->groupBy('order_items.product_id', 'products.name')
                ->orderByDesc('total_quantity')
                ->limit(10)
                ->get();

            return response()->json([
                'success' => true,
                'message' => 'Sales report generated successfully',
                'data' => [
                    'report_period' => [
                        'start_date' => $startDate,
                        'end_date' => $endDate,
                    ],
                    'summary' => $report,
                    'daily_trend' => $dailyTrend,
                    'top_products' => $topProducts,
                ]
            ]);

        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Failed to generate sales report',
                'error' => $e->getMessage()
            ], 500);
        }
    }
}