<?php

namespace App\Services;

use App\Models\Order;
use App\Models\Restaurant;
use App\Models\User;
use App\Models\OrderFlag;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;

class OrderRiskDetectionService
{
    private static array $riskThresholds = [
        'late_delivery_minutes' => 30,
        'restaurant_cancellation_rate' => 0.20, // 20%
        'delivery_rejection_count' => 3,
        'payment_mismatch_tolerance' => 0.01 // 1 cent
    ];

    public static function detectLateDeliveries(): array
    {
        $lateOrders = Order::where('status', 'delivered')
            ->where('delivered_at', '>', DB::raw('DATE_ADD(created_at, INTERVAL (estimated_delivery_time + ' . self::$riskThresholds['late_delivery_minutes'] . ') MINUTE)'))
            ->whereDoesntHave('flags', function($q) {
                $q->where('type', 'late_delivery')->where('resolved', false);
            })
            ->with(['restaurant:id,name', 'user:id,name'])
            ->get();

        foreach ($lateOrders as $order) {
            $delayMinutes = $order->delivered_at->diffInMinutes($order->created_at->addMinutes($order->estimated_delivery_time));
            
            self::createFlag($order, 'late_delivery', 'high', "Order delivered {$delayMinutes} minutes late");
        }

        return $lateOrders->toArray();
    }

    public static function detectHighCancellationRestaurants(): array
    {
        $timeframe = Carbon::now()->subDays(7);
        
        $restaurants = Restaurant::withCount([
            'orders as total_orders' => function($q) use ($timeframe) {
                $q->where('created_at', '>=', $timeframe);
            },
            'orders as cancelled_orders' => function($q) use ($timeframe) {
                $q->where('created_at', '>=', $timeframe)->where('status', 'cancelled');
            }
        ])
        ->having('total_orders', '>=', 5) // Minimum 5 orders to be considered
        ->get()
        ->filter(function($restaurant) {
            $cancellationRate = $restaurant->total_orders > 0 ? 
                $restaurant->cancelled_orders / $restaurant->total_orders : 0;
            return $cancellationRate >= self::$riskThresholds['restaurant_cancellation_rate'];
        });

        foreach ($restaurants as $restaurant) {
            $cancellationRate = round(($restaurant->cancelled_orders / $restaurant->total_orders) * 100, 1);
            
            // Create flag for latest order from this restaurant
            $latestOrder = $restaurant->orders()->latest()->first();
            if ($latestOrder) {
                self::createFlag($latestOrder, 'multiple_rejects', 'critical', 
                    "Restaurant has {$cancellationRate}% cancellation rate ({$restaurant->cancelled_orders}/{$restaurant->total_orders} orders)");
            }
        }

        return $restaurants->toArray();
    }

    public static function detectDeliveryBoyRejections(): array
    {
        // Skip this detection if no delivery boys exist
        return [];
    }

    public static function detectPaymentMismatches(): array
    {
        $orders = Order::whereHas('financialSnapshot')
            ->with('financialSnapshot')
            ->get()
            ->filter(function($order) {
                $snapshot = $order->financialSnapshot;
                $expectedTotal = $snapshot->restaurant_earning + 
                               $snapshot->platform_commission + 
                               $snapshot->delivery_boy_earning;
                $actualTotal = $snapshot->customer_payment - $snapshot->refund_amount;
                
                return abs($expectedTotal - $actualTotal) > self::$riskThresholds['payment_mismatch_tolerance'];
            });

        foreach ($orders as $order) {
            $snapshot = $order->financialSnapshot;
            $expectedTotal = $snapshot->restaurant_earning + $snapshot->platform_commission + $snapshot->delivery_boy_earning;
            $actualTotal = $snapshot->customer_payment - $snapshot->refund_amount;
            $difference = abs($expectedTotal - $actualTotal);
            
            self::createFlag($order, 'payment_issue', 'critical', 
                "Payment mismatch: Expected Rs.{$expectedTotal}, Actual Rs.{$actualTotal}, Difference Rs.{$difference}");
        }

        return $orders->toArray();
    }

    public static function runAllDetections(): array
    {
        return [
            'late_deliveries' => self::detectLateDeliveries(),
            'high_cancellation_restaurants' => self::detectHighCancellationRestaurants(),
            'delivery_boy_rejections' => self::detectDeliveryBoyRejections(),
            'payment_mismatches' => self::detectPaymentMismatches(),
            'detection_timestamp' => now()
        ];
    }

    private static function createFlag(Order $order, string $type, string $severity, string $description): void
    {
        // Check if similar flag already exists
        $existingFlag = $order->flags()
            ->where('type', $type)
            ->where('resolved', false)
            ->first();

        if (!$existingFlag) {
            OrderFlag::create([
                'order_id' => $order->id,
                'type' => $type,
                'severity' => $severity,
                'resolved' => false,
                'description' => $description
            ]);

            // Log audit trail
            OrderAuditService::logFlagAction($order, $type, 'auto_detected', $description);
        }
    }

    public static function getRiskSummary(): array
    {
        $last24Hours = Carbon::now()->subHours(24);
        
        return [
            'critical_flags' => OrderFlag::where('severity', 'critical')
                ->where('resolved', false)
                ->where('created_at', '>=', $last24Hours)
                ->count(),
            'high_flags' => OrderFlag::where('severity', 'high')
                ->where('resolved', false)
                ->where('created_at', '>=', $last24Hours)
                ->count(),
            'total_unresolved' => OrderFlag::where('resolved', false)->count(),
            'risk_breakdown' => OrderFlag::where('resolved', false)
                ->select('type', DB::raw('count(*) as count'))
                ->groupBy('type')
                ->pluck('count', 'type'),
            'thresholds' => self::$riskThresholds
        ];
    }

    public static function updateThresholds(array $newThresholds): void
    {
        self::$riskThresholds = array_merge(self::$riskThresholds, $newThresholds);
    }
}