package com.jordanbot.autoride.service

import android.annotation.SuppressLint
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.Service
import android.content.Intent
import android.location.Location
import android.os.Build
import android.os.IBinder
import android.os.Looper
import android.util.Log
import androidx.core.app.NotificationCompat
import com.google.android.gms.location.*
import com.jordanbot.autoride.R
import com.jordanbot.autoride.api.ApiClient
import com.jordanbot.autoride.api.BulkLocationRequest
import com.jordanbot.autoride.api.LocationPoint
import com.jordanbot.autoride.utils.DeviceUtils
import kotlinx.coroutines.*
import java.util.concurrent.TimeUnit

class BotForegroundService : Service() {

    private val serviceScope = CoroutineScope(Dispatchers.IO + SupervisorJob())
    private lateinit var fusedLocationClient: FusedLocationProviderClient
    private val locationBuffer = mutableListOf<LocationPoint>()

    // Battery-optimized intervals
    private val UPLOAD_INTERVAL_MS = TimeUnit.MINUTES.toMillis(5)    // Upload every 5 minutes
    private val TRACK_INTERVAL_MS = TimeUnit.SECONDS.toMillis(15)    // GPS poll every 15 seconds
    private val MIN_DISPLACEMENT_METERS = 15f                         // Ignore movement < 15m

    // Displacement filter: track last known location
    private var lastTrackedLocation: Location? = null

    private val locationCallback = object : LocationCallback() {
        override fun onLocationResult(locationResult: LocationResult) {
            locationResult.lastLocation?.let { location ->
                // Displacement filter: skip if driver hasn't moved 15 meters
                val last = lastTrackedLocation
                if (last != null && last.distanceTo(location) < MIN_DISPLACEMENT_METERS) {
                    return // Driver is stationary, save battery
                }

                lastTrackedLocation = location

                val point = LocationPoint(
                    latitude = location.latitude,
                    longitude = location.longitude,
                    speed = location.speed,
                    timestamp = System.currentTimeMillis()
                )
                synchronized(locationBuffer) {
                    locationBuffer.add(point)
                }
                Log.d("JordanBot", "📍 Location tracked: ${location.latitude}, ${location.longitude}")
            }
        }
    }

    override fun onBind(intent: Intent?): IBinder? = null

    override fun onCreate() {
        super.onCreate()
        createNotificationChannel()
        fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
        startTracking()
        startUploadTimer()
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        val notification = NotificationCompat.Builder(this, CHANNEL_ID)
            .setContentTitle("Jordan Bot يعمل حالياً")
            .setContentText("نبحث عن طلبات قريبة منك...")
            .setSmallIcon(R.drawable.bg_bubble)
            .setPriority(NotificationCompat.PRIORITY_LOW)
            .build()

        startForeground(1, notification)
        return START_STICKY
    }

    @SuppressLint("MissingPermission")
    private fun startTracking() {
        val locationRequest = LocationRequest.Builder(
            Priority.PRIORITY_BALANCED_POWER_ACCURACY, TRACK_INTERVAL_MS
        )
            .setMinUpdateDistanceMeters(MIN_DISPLACEMENT_METERS)
            .setMinUpdateIntervalMillis(TRACK_INTERVAL_MS)
            .build()

        fusedLocationClient.requestLocationUpdates(
            locationRequest,
            locationCallback,
            Looper.getMainLooper()
        )
    }

    private fun startUploadTimer() {
        serviceScope.launch {
            while (isActive) {
                delay(UPLOAD_INTERVAL_MS)
                uploadLocations()
            }
        }
    }

    private fun uploadLocations() {
        val pointsToUpload = synchronized(locationBuffer) {
            val copy = locationBuffer.toList()
            locationBuffer.clear()
            copy
        }

        if (pointsToUpload.isEmpty()) return

        val fingerprint = DeviceUtils.getDeviceFingerprint(this)
        val request = BulkLocationRequest(fingerprint, pointsToUpload)

        serviceScope.launch {
            try {
                val response = ApiClient.service.updateBulkLocation(request)
                if (response.success) {
                    Log.d("JordanBot", "✅ Successfully uploaded ${pointsToUpload.size} locations")
                } else {
                    Log.e("JordanBot", "❌ Failed to upload locations: ${response.message}")
                }
            } catch (e: retrofit2.HttpException) {
                val errorBody = e.response()?.errorBody()?.string()
                Log.e("JordanBot", "❌ Error uploading locations: HTTP ${e.code()} - Body: $errorBody", e)
            } catch (e: Exception) {
                Log.e("JordanBot", "❌ Error uploading locations", e)
                // If failed, we might want to add them back to the buffer, 
                // but for now we just log to keep it simple.
            }
        }
    }

    private fun createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val serviceChannel = NotificationChannel(
                CHANNEL_ID,
                "Jordan Bot Service Channel",
                NotificationManager.IMPORTANCE_LOW
            )
            val manager = getSystemService(NotificationManager::class.java)
            manager.createNotificationChannel(serviceChannel)
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        fusedLocationClient.removeLocationUpdates(locationCallback)
        serviceScope.cancel()
    }

    companion object {
        const val CHANNEL_ID = "JordanBotForegroundChannel"
    }
}
