package com.atridad.openclimb.service

import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.Service
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.IBinder
import androidx.core.app.NotificationCompat
import com.atridad.openclimb.MainActivity
import com.atridad.openclimb.R
import com.atridad.openclimb.data.database.OpenClimbDatabase
import com.atridad.openclimb.data.repository.ClimbRepository
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.firstOrNull
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
import java.time.temporal.ChronoUnit

class SessionTrackingService : Service() {
    
    private val serviceScope = CoroutineScope(Dispatchers.IO + SupervisorJob())
    private var notificationJob: Job? = null
    
    private lateinit var repository: ClimbRepository
    
    companion object {
        const val NOTIFICATION_ID = 1001
        const val CHANNEL_ID = "session_tracking_channel"
        const val ACTION_START_SESSION = "start_session"
        const val ACTION_STOP_SESSION = "stop_session"
        const val EXTRA_SESSION_ID = "session_id"
        
        fun createStartIntent(context: Context, sessionId: String): Intent {
            return Intent(context, SessionTrackingService::class.java).apply {
                action = ACTION_START_SESSION
                putExtra(EXTRA_SESSION_ID, sessionId)
            }
        }
        
        fun createStopIntent(context: Context): Intent {
            return Intent(context, SessionTrackingService::class.java).apply {
                action = ACTION_STOP_SESSION
            }
        }
    }
    
    override fun onCreate() {
        super.onCreate()
        
        val database = OpenClimbDatabase.getDatabase(this)
        repository = ClimbRepository(database, this)
        
        createNotificationChannel()
    }
    
    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        when (intent?.action) {
            ACTION_START_SESSION -> {
                val sessionId = intent.getStringExtra(EXTRA_SESSION_ID)
                if (sessionId != null) {
                    startSessionTracking(sessionId)
                }
            }
            ACTION_STOP_SESSION -> {
                stopSessionTracking()
            }
        }
        return START_STICKY
    }
    
    override fun onBind(intent: Intent?): IBinder? = null
    
    private fun startSessionTracking(sessionId: String) {
        notificationJob?.cancel()
        notificationJob = serviceScope.launch {
            while (isActive) {
                updateNotification(sessionId)
                delay(1000)
            }
        }
    }
    
    private fun stopSessionTracking() {
        notificationJob?.cancel()
        stopForeground(STOP_FOREGROUND_REMOVE)
        stopSelf()
    }
    
    private suspend fun updateNotification(sessionId: String) {
        try {
            val session = repository.getSessionById(sessionId)
            if (session == null || session.status != com.atridad.openclimb.data.model.SessionStatus.ACTIVE) {
                stopSessionTracking()
                return
            }
            
            val gym = repository.getGymById(session.gymId)
            val attempts = repository.getAttemptsBySession(sessionId).firstOrNull() ?: emptyList()
            
            val duration = session.startTime?.let { startTime ->
                try {
                    val start = LocalDateTime.parse(startTime)
                    val now = LocalDateTime.now()
                    val minutes = ChronoUnit.MINUTES.between(start, now)
                    val hours = minutes / 60
                    val remainingMinutes = minutes % 60
                    
                    when {
                        hours > 0 -> "${hours}h ${remainingMinutes}m"
                        remainingMinutes > 0 -> "${remainingMinutes}m"
                        else -> "< 1m"
                    }
                } catch (e: Exception) {
                    "Active"
                }
            } ?: "Active"
            
            val notification = NotificationCompat.Builder(this, CHANNEL_ID)
                .setContentTitle("OpenClimb Session Active")
                .setContentText("${gym?.name ?: "Gym"} • $duration • ${attempts.size} attempts")
                .setSmallIcon(R.drawable.ic_launcher_foreground)
                .setOngoing(true)
                .setContentIntent(createOpenAppIntent())
                .addAction(
                    R.drawable.ic_launcher_foreground,
                    "Open Session",
                    createOpenAppIntent()
                )
                .addAction(
                    R.drawable.ic_launcher_foreground,
                    "End Session",
                    createStopIntent()
                )
                .build()
            
            startForeground(NOTIFICATION_ID, notification)
        } catch (e: Exception) {
            // Handle errors gracefully
            stopSessionTracking()
        }
    }
    
    private fun createOpenAppIntent(): PendingIntent {
        val intent = Intent(this, MainActivity::class.java).apply {
            flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
        }
        return PendingIntent.getActivity(
            this,
            0,
            intent,
            PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
        )
    }
    
    private fun createStopIntent(): PendingIntent {
        val intent = createStopIntent(this)
        return PendingIntent.getService(
            this,
            1,
            intent,
            PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
        )
    }
    
    private fun createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channel = NotificationChannel(
                CHANNEL_ID,
                "Session Tracking",
                NotificationManager.IMPORTANCE_LOW
            ).apply {
                description = "Shows active climbing session information"
                setShowBadge(false)
            }
            
            val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
            notificationManager.createNotificationChannel(channel)
        }
    }
    
    override fun onDestroy() {
        super.onDestroy()
        notificationJob?.cancel()
        serviceScope.cancel()
    }
}
