package com.bitchat.android

import android.Manifest
import android.content.Intent
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.ViewModelProvider
import androidx.activity.OnBackPressedCallback
import androidx.activity.addCallback
import com.bitchat.android.mesh.BluetoothMeshService
import com.bitchat.android.onboarding.*
import com.bitchat.android.ui.ChatScreen
import com.bitchat.android.ui.ChatViewModel
import com.bitchat.android.ui.MainAppScreen
import com.bitchat.android.ui.theme.BitchatTheme
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

class MainActivity : ComponentActivity() {
    
    private lateinit var permissionManager: PermissionManager
    private lateinit var onboardingCoordinator: OnboardingCoordinator
    private lateinit var bluetoothStatusManager: BluetoothStatusManager
    private lateinit var locationStatusManager: LocationStatusManager
    
    // Core mesh service - managed at app level
    private lateinit var meshService: BluetoothMeshService
    private val chatViewModel: ChatViewModel by viewModels { 
        object : ViewModelProvider.Factory {
            override fun <T : androidx.lifecycle.ViewModel> create(modelClass: Class<T>): T {
                @Suppress("UNCHECKED_CAST")
                return ChatViewModel(application, meshService) as T
            }
        }
    }
    
    // UI state for onboarding flow
    private var onboardingState by mutableStateOf(OnboardingState.CHECKING)
    private var bluetoothStatus by mutableStateOf(BluetoothStatus.ENABLED)
    private var locationStatus by mutableStateOf(LocationStatus.ENABLED)
    private var errorMessage by mutableStateOf("")
    private var isBluetoothLoading by mutableStateOf(false)
    private var isLocationLoading by mutableStateOf(false)
    
    enum class OnboardingState {
        CHECKING,
        BLUETOOTH_CHECK,
        LOCATION_CHECK,
        PERMISSION_EXPLANATION,
        PERMISSION_REQUESTING,
        INITIALIZING,
        COMPLETE,
        ERROR
    }
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        // Initialize core mesh service first
        meshService = BluetoothMeshService(this)
        
        // Initialize permission management
        permissionManager = PermissionManager(this)
        bluetoothStatusManager = BluetoothStatusManager(
            activity = this,
            context = this,
            onBluetoothEnabled = ::handleBluetoothEnabled,
            onBluetoothDisabled = ::handleBluetoothDisabled
        )
        locationStatusManager = LocationStatusManager(
            activity = this,
            context = this,
            onLocationEnabled = ::handleLocationEnabled,
            onLocationDisabled = ::handleLocationDisabled
        )
        onboardingCoordinator = OnboardingCoordinator(
            activity = this,
            permissionManager = permissionManager,
            onOnboardingComplete = ::handleOnboardingComplete,
            onOnboardingFailed = ::handleOnboardingFailed
        )
        
        setContent {
            BitchatTheme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    OnboardingFlowScreen()
                }
            }
        }
        
        // Start the onboarding process
        checkOnboardingStatus()
    }
    
    @Composable
    private fun OnboardingFlowScreen() {
        when (onboardingState) {
            OnboardingState.CHECKING -> {
                InitializingScreen()
            }
            
            OnboardingState.BLUETOOTH_CHECK -> {
                BluetoothCheckScreen(
                    status = bluetoothStatus,
                    onEnableBluetooth = {
                        isBluetoothLoading = true
                        bluetoothStatusManager.requestEnableBluetooth()
                    },
                    onRetry = {
                        checkBluetoothAndProceed()
                    },
                    isLoading = isBluetoothLoading
                )
            }
            
            OnboardingState.LOCATION_CHECK -> {
                LocationCheckScreen(
                    status = locationStatus,
                    onEnableLocation = {
                        isLocationLoading = true
                        locationStatusManager.requestEnableLocation()
                    },
                    onRetry = {
                        checkLocationAndProceed()
                    },
                    isLoading = isLocationLoading
                )
            }
            
            OnboardingState.PERMISSION_EXPLANATION -> {
                PermissionExplanationScreen(
                    permissionCategories = permissionManager.getCategorizedPermissions(),
                    onContinue = {
                        onboardingState = OnboardingState.PERMISSION_REQUESTING
                        onboardingCoordinator.requestPermissions()
                    }
                )
            }
            
            OnboardingState.PERMISSION_REQUESTING -> {
                InitializingScreen()
            }
            
            OnboardingState.INITIALIZING -> {
                InitializingScreen()
            }
            
            OnboardingState.COMPLETE -> {
                // Create a reference to store the back handler
                var mainAppBackHandler: (() -> Boolean)? = null
                
                // Set up back navigation handling for the main app screen
                val backCallback = object : OnBackPressedCallback(true) {
                    override fun handleOnBackPressed() {
                        // Try to handle back press through MainAppScreen
                        val handled = mainAppBackHandler?.invoke() ?: false
                        if (!handled) {
                            // If MainAppScreen doesn't handle it, disable this callback 
                            // and let the system handle it (which will exit the app)
                            this.isEnabled = false
                            onBackPressedDispatcher.onBackPressed()
                            this.isEnabled = true
                        }
                    }
                }
                
                // Add the callback - this will be automatically removed when the activity is destroyed
                onBackPressedDispatcher.addCallback(this, backCallback)
                
                MainAppScreen(
                    chatViewModel = chatViewModel,
                    onBackPress = { handler ->
                        // Store the back handler from MainAppScreen
                        mainAppBackHandler = handler
                    }
                )
            }
            
            OnboardingState.ERROR -> {
                InitializationErrorScreen(
                    errorMessage = errorMessage,
                    onRetry = {
                        onboardingState = OnboardingState.CHECKING
                        checkOnboardingStatus()
                    },
                    onOpenSettings = {
                        onboardingCoordinator.openAppSettings()
                    }
                )
            }
        }
    }
    
    private fun checkOnboardingStatus() {
        android.util.Log.d("MainActivity", "Checking onboarding status")
        
        lifecycleScope.launch {
            // Small delay to show the checking state
            delay(500)
            
            // First check Bluetooth status (always required)
            checkBluetoothAndProceed()
        }
    }
    
    /**
     * Check Bluetooth status and proceed with onboarding flow
     */
    private fun checkBluetoothAndProceed() {
        // android.util.Log.d("MainActivity", "Checking Bluetooth status")
        
        // For first-time users, skip Bluetooth check and go straight to permissions
        // We'll check Bluetooth after permissions are granted
        if (permissionManager.isFirstTimeLaunch()) {
            android.util.Log.d("MainActivity", "First-time launch, skipping Bluetooth check - will check after permissions")
            proceedWithPermissionCheck()
            return
        }
        
        // For existing users, check Bluetooth status first
        bluetoothStatusManager.logBluetoothStatus()
        bluetoothStatus = bluetoothStatusManager.checkBluetoothStatus()
        
        when (bluetoothStatus) {
            BluetoothStatus.ENABLED -> {
                // Bluetooth is enabled, check location services next
                checkLocationAndProceed()
            }
            BluetoothStatus.DISABLED -> {
                // Show Bluetooth enable screen (should have permissions as existing user)
                android.util.Log.d("MainActivity", "Bluetooth disabled, showing enable screen")
                onboardingState = OnboardingState.BLUETOOTH_CHECK
                isBluetoothLoading = false
            }
            BluetoothStatus.NOT_SUPPORTED -> {
                // Device doesn't support Bluetooth
                android.util.Log.e("MainActivity", "Bluetooth not supported")
                onboardingState = OnboardingState.BLUETOOTH_CHECK
                isBluetoothLoading = false
            }
        }
    }
    
    /**
     * Proceed with permission checking 
     */
    private fun proceedWithPermissionCheck() {
        android.util.Log.d("MainActivity", "Proceeding with permission check")
        
        lifecycleScope.launch {
            delay(200) // Small delay for smooth transition
            
            if (permissionManager.isFirstTimeLaunch()) {
                android.util.Log.d("MainActivity", "First time launch, showing permission explanation")
                onboardingState = OnboardingState.PERMISSION_EXPLANATION
            } else if (permissionManager.areAllPermissionsGranted()) {
                android.util.Log.d("MainActivity", "Existing user with permissions, initializing app")
                onboardingState = OnboardingState.INITIALIZING
                initializeApp()
            } else {
                android.util.Log.d("MainActivity", "Existing user missing permissions, showing explanation")
                onboardingState = OnboardingState.PERMISSION_EXPLANATION
            }
        }
    }
    
    /**
     * Handle Bluetooth enabled callback
     */
    private fun handleBluetoothEnabled() {
        android.util.Log.d("MainActivity", "Bluetooth enabled by user")
        isBluetoothLoading = false
        bluetoothStatus = BluetoothStatus.ENABLED
        checkLocationAndProceed()
    }

    /**
     * Check Location services status and proceed with onboarding flow
     */
    private fun checkLocationAndProceed() {
        android.util.Log.d("MainActivity", "Checking location services status")
        
        // For first-time users, skip location check and go straight to permissions
        // We'll check location after permissions are granted
        if (permissionManager.isFirstTimeLaunch()) {
            android.util.Log.d("MainActivity", "First-time launch, skipping location check - will check after permissions")
            proceedWithPermissionCheck()
            return
        }
        
        // For existing users, check location status
        locationStatusManager.logLocationStatus()
        locationStatus = locationStatusManager.checkLocationStatus()
        
        when (locationStatus) {
            LocationStatus.ENABLED -> {
                // Location services enabled, proceed with permission/onboarding check
                proceedWithPermissionCheck()
            }
            LocationStatus.DISABLED -> {
                // Show location enable screen (should have permissions as existing user)
                android.util.Log.d("MainActivity", "Location services disabled, showing enable screen")
                onboardingState = OnboardingState.LOCATION_CHECK
                isLocationLoading = false
            }
            LocationStatus.NOT_AVAILABLE -> {
                // Device doesn't support location services (very unusual)
                android.util.Log.e("MainActivity", "Location services not available")
                onboardingState = OnboardingState.LOCATION_CHECK
                isLocationLoading = false
            }
        }
    }

    /**
     * Handle Location enabled callback
     */
    private fun handleLocationEnabled() {
        android.util.Log.d("MainActivity", "Location services enabled by user")
        isLocationLoading = false
        locationStatus = LocationStatus.ENABLED
        proceedWithPermissionCheck()
    }

    /**
     * Handle Location disabled callback
     */
    private fun handleLocationDisabled(message: String) {
        android.util.Log.w("MainActivity", "Location services disabled or failed: $message")
        isLocationLoading = false
        locationStatus = locationStatusManager.checkLocationStatus()
        
        when {
            locationStatus == LocationStatus.NOT_AVAILABLE -> {
                // Show permanent error for devices without location services
                errorMessage = message
                onboardingState = OnboardingState.ERROR
            }
            else -> {
                // Stay on location check screen for retry
                onboardingState = OnboardingState.LOCATION_CHECK
            }
        }
    }
    
    /**
     * Handle Bluetooth disabled callback
     */
    private fun handleBluetoothDisabled(message: String) {
        android.util.Log.w("MainActivity", "Bluetooth disabled or failed: $message")
        isBluetoothLoading = false
        bluetoothStatus = bluetoothStatusManager.checkBluetoothStatus()
        
        when {
            bluetoothStatus == BluetoothStatus.NOT_SUPPORTED -> {
                // Show permanent error for unsupported devices
                errorMessage = message
                onboardingState = OnboardingState.ERROR
            }
            message.contains("Permission") && permissionManager.isFirstTimeLaunch() -> {
                // During first-time onboarding, if Bluetooth enable fails due to permissions,
                // proceed to permission explanation screen where user will grant permissions first
                android.util.Log.d("MainActivity", "Bluetooth enable requires permissions, proceeding to permission explanation")
                proceedWithPermissionCheck()
            }
            message.contains("Permission") -> {
                // For existing users, redirect to permission explanation to grant missing permissions
                android.util.Log.d("MainActivity", "Bluetooth enable requires permissions, showing permission explanation")
                onboardingState = OnboardingState.PERMISSION_EXPLANATION
            }
            else -> {
                // Stay on Bluetooth check screen for retry
                onboardingState = OnboardingState.BLUETOOTH_CHECK
            }
        }
    }
    
    private fun handleOnboardingComplete() {
        android.util.Log.d("MainActivity", "Onboarding completed, checking Bluetooth and Location before initializing app")
        
        // After permissions are granted, re-check both Bluetooth and Location status
        val currentBluetoothStatus = bluetoothStatusManager.checkBluetoothStatus()
        val currentLocationStatus = locationStatusManager.checkLocationStatus()
        
        when {
            currentBluetoothStatus != BluetoothStatus.ENABLED -> {
                // Bluetooth still disabled, but now we have permissions to enable it
                android.util.Log.d("MainActivity", "Permissions granted, but Bluetooth still disabled. Showing Bluetooth enable screen.")
                bluetoothStatus = currentBluetoothStatus
                onboardingState = OnboardingState.BLUETOOTH_CHECK
                isBluetoothLoading = false
            }
            currentLocationStatus != LocationStatus.ENABLED -> {
                // Location services still disabled, but now we have permissions to enable it
                android.util.Log.d("MainActivity", "Permissions granted, but Location services still disabled. Showing Location enable screen.")
                locationStatus = currentLocationStatus
                onboardingState = OnboardingState.LOCATION_CHECK
                isLocationLoading = false
            }
            else -> {
                // Both are enabled, proceed to app initialization
                android.util.Log.d("MainActivity", "Both Bluetooth and Location services are enabled, proceeding to initialization")
                onboardingState = OnboardingState.INITIALIZING
                initializeApp()
            }
        }
    }
    
    private fun handleOnboardingFailed(message: String) {
        android.util.Log.e("MainActivity", "Onboarding failed: $message")
        errorMessage = message
        onboardingState = OnboardingState.ERROR
    }
    
    private fun initializeApp() {
        android.util.Log.d("MainActivity", "Starting app initialization")
        
        lifecycleScope.launch {
            try {
                // Initialize the app with a proper delay to ensure Bluetooth stack is ready
                // This solves the issue where app needs restart to work on first install
                delay(1000) // Give the system time to process permission grants
                
                android.util.Log.d("MainActivity", "Permissions verified, initializing chat system")
                
                // Ensure all permissions are still granted (user might have revoked in settings)
                if (!permissionManager.areAllPermissionsGranted()) {
                    val missing = permissionManager.getMissingPermissions()
                    android.util.Log.w("MainActivity", "Permissions revoked during initialization: $missing")
                    handleOnboardingFailed("Some permissions were revoked. Please grant all permissions to continue.")
                    return@launch
                }
                
                // Set up mesh service delegate and start services
                meshService.delegate = chatViewModel
                meshService.startServices()
                
                android.util.Log.d("MainActivity", "Mesh service started successfully")
                
                // Handle any notification intent
                handleNotificationIntent(intent)
                
                // Small delay to ensure mesh service is fully initialized
                delay(500)
                
                android.util.Log.d("MainActivity", "App initialization complete")
                onboardingState = OnboardingState.COMPLETE
                
            } catch (e: Exception) {
                android.util.Log.e("MainActivity", "Failed to initialize app", e)
                handleOnboardingFailed("Failed to initialize the app: ${e.message}")
            }
        }
    }
    
    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        // Handle notification intents when app is already running
        if (onboardingState == OnboardingState.COMPLETE) {
            handleNotificationIntent(intent)
        }
    }
    
    override fun onResume() {
        super.onResume()
        // Check Bluetooth and Location status on resume and handle accordingly
        if (onboardingState == OnboardingState.COMPLETE) {
            // Set app foreground state
            meshService.connectionManager.setAppBackgroundState(false)
            chatViewModel.setAppBackgroundState(false)
            
            // Check if Bluetooth was disabled while app was backgrounded
            val currentBluetoothStatus = bluetoothStatusManager.checkBluetoothStatus()
            if (currentBluetoothStatus != BluetoothStatus.ENABLED) {
                android.util.Log.w("MainActivity", "Bluetooth disabled while app was backgrounded")
                bluetoothStatus = currentBluetoothStatus
                onboardingState = OnboardingState.BLUETOOTH_CHECK
                isBluetoothLoading = false
                return
            }
            
            // Check if location services were disabled while app was backgrounded
            val currentLocationStatus = locationStatusManager.checkLocationStatus()
            if (currentLocationStatus != LocationStatus.ENABLED) {
                android.util.Log.w("MainActivity", "Location services disabled while app was backgrounded")
                locationStatus = currentLocationStatus
                onboardingState = OnboardingState.LOCATION_CHECK
                isLocationLoading = false
            }
        }
    }
    
    override fun onPause() {
        super.onPause()
        // Only set background state if app is fully initialized
        if (onboardingState == OnboardingState.COMPLETE) {
            // Set app background state
            meshService.connectionManager.setAppBackgroundState(true)
            chatViewModel.setAppBackgroundState(true)
        }
    }
    
    /**
     * Handle intents from notification clicks - open specific private chat
     */
    private fun handleNotificationIntent(intent: Intent) {
        val shouldOpenPrivateChat = intent.getBooleanExtra(
            com.bitchat.android.ui.NotificationManager.EXTRA_OPEN_PRIVATE_CHAT, 
            false
        )
        
        if (shouldOpenPrivateChat) {
            val peerID = intent.getStringExtra(com.bitchat.android.ui.NotificationManager.EXTRA_PEER_ID)
            val senderNickname = intent.getStringExtra(com.bitchat.android.ui.NotificationManager.EXTRA_SENDER_NICKNAME)
            
            if (peerID != null) {
                android.util.Log.d("MainActivity", "Opening private chat with $senderNickname (peerID: $peerID) from notification")
                
                // Open the private chat with this peer
                chatViewModel.startPrivateChat(peerID)
                
                // Clear notifications for this sender since user is now viewing the chat
                chatViewModel.clearNotificationsForSender(peerID)
            }
        }
    }
    
    /**
     * Restart mesh services (for debugging/troubleshooting)
     */
    fun restartMeshServices() {
        if (onboardingState == OnboardingState.COMPLETE) {
            lifecycleScope.launch {
                try {
                    android.util.Log.d("MainActivity", "Restarting mesh services")
                    meshService.stopServices()
                    delay(1000)
                    meshService.startServices()
                    android.util.Log.d("MainActivity", "Mesh services restarted successfully")
                } catch (e: Exception) {
                    android.util.Log.e("MainActivity", "Error restarting mesh services: ${e.message}")
                }
            }
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        
        // Cleanup location status manager
        try {
            locationStatusManager.cleanup()
            android.util.Log.d("MainActivity", "Location status manager cleaned up successfully")
        } catch (e: Exception) {
            android.util.Log.w("MainActivity", "Error cleaning up location status manager: ${e.message}")
        }
        
        // Stop mesh services if app was fully initialized
        if (onboardingState == OnboardingState.COMPLETE) {
            try {
                meshService.stopServices()
                android.util.Log.d("MainActivity", "Mesh services stopped successfully")
            } catch (e: Exception) {
                android.util.Log.w("MainActivity", "Error stopping mesh services in onDestroy: ${e.message}")
            }
        }
    }
}
