<?php

namespace App\Http\Controllers;

use App\Models\Ride;
use App\Models\Driver;
use App\Models\Wallet;
use App\Models\Transaction;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Carbon\Carbon;

use App\Services\PricingService;

class RideController extends Controller
{
    protected $pricingService;

    public function __construct(PricingService $pricingService)
    {
        $this->pricingService = $pricingService;
    }

    /**
     * Store a new ride request.
     */
    public function request(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'pickup_name' => 'required|string',
            'pickup_lat' => 'required|numeric',
            'pickup_lng' => 'required|numeric',
            'destination_name' => 'required|string',
            'destination_lat' => 'required|numeric',
            'destination_lng' => 'required|numeric',
        ]);

        if ($request->pickup_lat == $request->destination_lat && $request->pickup_lng == $request->destination_lng) {
            return response()->json(['success' => false, 'message' => 'Pickup and destination cannot be the same.'], 422);
        }

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

        $user = $request->user();

        // Check if user has an active ride
        $activeRide = Ride::where('rider_id', $user->id)
            ->whereIn('status', ['pending', 'accepted', 'ongoing'])
            ->first();

        if ($activeRide) {
            return response()->json([
                'success' => false,
                'message' => 'You already have an active ride request.',
            ], 400);
        }

        // --- REAL OSM DATA FETCHING ---
        $start = "{$request->pickup_lng},{$request->pickup_lat}";
        $end = "{$request->destination_lng},{$request->destination_lat}";

        $routeUrl = "https://router.project-osrm.org/route/v1/driving/{$start};{$end}?overview=false";
        
        $distance = 0;
        $duration = 0;
        $fare = 1200; // default min fare fallback

        try {
            $osrmResponse = Http::get($routeUrl);
            if ($osrmResponse->successful()) {
                $osrmData = $osrmResponse->json();
                $distance = $osrmData['routes'][0]['distance']; // meters
                $duration = $osrmData['routes'][0]['duration']; // seconds
                
                $fareDetails = $this->pricingService->calculateFare(
                    $distance, 
                    $duration, 
                    $request->pickup_lat, 
                    $request->pickup_lng
                );
                $fare = $fareDetails['final_fare'];
            }
        } catch (\Exception $e) {
            Log::error("OSRM/Pricing Error: " . $e->getMessage());
        }

        // Wallet Check
        $wallet = $user->wallet ?: Wallet::firstOrCreate(['user_id' => $user->id], ['balance' => 0.00]);
        if ($wallet->balance < $fare) {
            return response()->json([
                'success' => false,
                'message' => 'Insufficient wallet balance. Please fund your wallet first.',
                'required' => $fare,
                'current' => (float)$wallet->balance
            ], 402);
        }

        $ride = Ride::create([
            'rider_id' => $user->id,
            'pickup_name' => $request->pickup_name,
            'pickup_lat' => $request->pickup_lat,
            'pickup_lng' => $request->pickup_lng,
            'destination_name' => $request->destination_name,
            'destination_lat' => $request->destination_lat,
            'destination_lng' => $request->destination_lng,
            'status' => 'pending',
            'fare' => $fare,
            'distance' => $distance,
            'duration' => $duration,
        ]);

        return response()->json([
            'success' => true,
            'message' => 'Ride requested successfully',
            'ride' => $ride,
        ], 201);
    }

    /**
     * Accept a ride (Driver only).
     */
    public function accept(Request $request, $id)
    {
        $ride = Ride::where('id', $id)->where('status', 'pending')->firstOrFail();
        $user = $request->user();

        if ($user->user_type !== 'driver') {
            return response()->json(['success' => false, 'message' => 'Only drivers can accept rides.'], 403);
        }

        $driver = Driver::where('user_id', $user->id)->first();
        if (!$driver || !$driver->is_online) {
            return response()->json(['success' => false, 'message' => 'Driver must be online.'], 400);
        }

        // Check if driver has an active ride
        $activeDriverRide = Ride::where('driver_id', $user->id)
            ->whereIn('status', ['accepted', 'ongoing'])
            ->first();

        if ($activeDriverRide) {
            return response()->json([
                'success' => false,
                'message' => 'You already have an active ride. Complete it before accepting a new one.',
            ], 400);
        }

        // Generate 4-digit OTP for the rider
        $otp = (string) rand(1000, 9999);

        $ride->update([
            'driver_id' => $user->id, // This stores the driver USER_ID
            'status' => 'accepted',
            'ride_otp' => $otp,
        ]);

        return response()->json([
            'success' => true,
            'message' => 'Ride accepted. Please pick up the rider.',
            'ride' => $ride
        ]);
    }

    /**
     * Start a trip (Driver verifies OTP).
     */
    public function startTrip(Request $request, $id)
    {
        $ride = Ride::where('id', $id)
            ->where('driver_id', $request->user()->id)
            ->where('status', 'accepted')
            ->firstOrFail();

        $validator = Validator::make($request->all(), [
            'otp' => 'required|string|size:4',
        ]);

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

        if ($ride->ride_otp !== $request->otp) {
            return response()->json(['success' => false, 'message' => 'Invalid OTP. Trip cannot start.'], 400);
        }

        $ride->update([
            'status' => 'ongoing',
            'started_at' => Carbon::now(),
        ]);

        return response()->json([
            'success' => true,
            'message' => 'Trip started successfully.',
            'ride' => $ride
        ]);
    }

    /**
     * End a trip & Process Payments.
     */
    public function endTrip(Request $request, $id)
    {
        $ride = Ride::where('id', $id)
            ->where('driver_id', $request->user()->id)
            ->where('status', 'ongoing')
            ->firstOrFail();

        return DB::transaction(function () use ($ride) {
            $fare = $ride->fare;
            $rider = User::find($ride->rider_id);
            $driver = User::find($ride->driver_id);

            // 1. Deduct from Rider
            $riderWallet = $rider->wallet ?: Wallet::create(['user_id' => $rider->id, 'balance' => 0.00]);
            $riderWallet->decrement('balance', $fare);

            Transaction::create([
                'user_id' => $rider->id,
                'type' => 'debit',
                'amount' => $fare,
                'status' => 'completed',
                'description' => "Payment for Ride #{$ride->id}",
                'reference' => 'RIDE-' . $ride->id
            ]);

            // 2. Credit Driver
            $driverWallet = $driver->wallet ?: Wallet::create(['user_id' => $driver->id, 'balance' => 0.00]);
            $driverWallet->increment('balance', $fare);

            Transaction::create([
                'user_id' => $driver->id,
                'type' => 'credit',
                'amount' => $fare,
                'status' => 'completed',
                'description' => "Earnings for Ride #{$ride->id}",
                'reference' => 'RIDE-' . $ride->id
            ]);

            // 3. Update Ride Status
            $ride->update([
                'status' => 'completed',
                'completed_at' => Carbon::now(),
            ]);

            return response()->json([
                'success' => true,
                'message' => 'Trip ended and payment processed.',
                'ride' => $ride
            ]);
        });
    }

    /**
     * Get nearby available drivers.
     */
    public function availableDrivers(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'latitude' => 'required|numeric',
            'longitude' => 'required|numeric',
            'radius' => 'nullable|numeric', 
        ]);

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

        $lat = $request->latitude;
        $lng = $request->longitude;
        $radius = $request->radius ?? 10;

        $drivers = Driver::select('drivers.*')
            ->join('users', 'users.id', '=', 'drivers.user_id')
            ->where('drivers.is_online', true)
            ->selectRaw(
                "(6371 * acos(cos(radians(?)) * cos(radians(current_location_lat)) * cos(radians(current_location_lng) - radians(?)) + sin(radians(?)) * sin(radians(current_location_lat)))) AS distance",
                [$lat, $lng, $lat]
            )
            ->having('distance', '<=', $radius)
            ->orderBy('distance')
            ->with('user:id,name,phone')
            ->get();

        return response()->json([
            'success' => true,
            'drivers' => $drivers,
        ]);
    }

    /**
     * Cancel a ride.
     */
    public function cancel(Request $request, $id)
    {
        $ride = Ride::findOrFail($id);

        if ($ride->rider_id !== $request->user()->id && $ride->driver_id !== $request->user()->id) {
            return response()->json(['success' => false, 'message' => 'Unauthorized'], 403);
        }

        if (in_array($ride->status, ['completed', 'cancelled', 'ongoing'])) {
            return response()->json(['success' => false, 'message' => 'Ride cannot be cancelled at this stage.'], 400);
        }

        $ride->status = 'cancelled';
        $ride->save();

        return response()->json(['success' => true, 'message' => 'Ride cancelled successfully']);
    }

    /**
     * Get ride status and driver location.
     */
    public function status(Request $request, $id)
    {
        $ride = Ride::with(['driver.driver', 'rider'])->findOrFail($id);

        $driver = $ride->driver ? $ride->driver->driver : null;

        return response()->json([
            'success' => true,
            'status' => $ride->status,
            'ride' => array_merge($ride->toArray(), [
                'driver_lat' => $driver ? $driver->current_location_lat : null,
                'driver_lng' => $driver ? $driver->current_location_lng : null,
                'otp' => $ride->ride_otp, // for frontend compatibility
            ]),
        ]);
    }

    /**
     * Get ride history for the user.
     */
    public function history(Request $request)
    {
        $status = $request->query('status'); 
        $query = Ride::where('rider_id', $request->user()->id)->with('driver.driver');

        if ($status === 'history' || $status === 'completed') {
            $query->whereIn('status', ['completed', 'cancelled']);
        } else if ($status === 'active') {
            $query->whereIn('status', ['accepted', 'ongoing']);
        } else if ($status === 'upcoming') {
            $query->where('status', 'pending');
        }

        $rides = $query->orderBy('created_at', 'desc')->get();

        return response()->json([
            'success' => true,
            'rides' => $rides
        ]);
    }

    public function driverHistory(Request $request)
    {
        $status = $request->query('status'); 
        $query = Ride::where('driver_id', $request->user()->id)->with('rider');

        if ($status === 'history' || $status === 'completed') {
            $query->whereIn('status', ['completed', 'cancelled']);
        } else if ($status === 'active') {
            $query->whereIn('status', ['accepted', 'ongoing']);
        }

        $rides = $query->orderBy('created_at', 'desc')->get();

        return response()->json([
            'success' => true,
            'rides' => $rides
        ]);
    }
}
