package com.openclaw.alfred

import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.os.Bundle
import android.os.IBinder
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.openclaw.alfred.auth.AuthManager
import com.openclaw.alfred.notifications.NotificationHelper
import com.openclaw.alfred.service.AlfredConnectionService
import com.openclaw.alfred.ui.screens.LoginScreen
import com.openclaw.alfred.ui.screens.MainScreen
import com.openclaw.alfred.ui.theme.AlfredTheme
import dagger.hilt.android.AndroidEntryPoint

/**
 * Main entry point for the Alfred Mobile app.
 * Handles OAuth authentication flow.
 */
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
    
    private val TAG = "MainActivity"
    private lateinit var authManager: AuthManager
    private var isLoggedIn = mutableStateOf(false)
    private var accessToken = mutableStateOf("")
    
    // Service binding
    private var connectionService = mutableStateOf<AlfredConnectionService?>(null)
    private var serviceBound = mutableStateOf(false)
    
    private val serviceConnection = object : ServiceConnection {
        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
            Log.d(TAG, "Service connected")
            val binder = service as AlfredConnectionService.LocalBinder
            connectionService.value = binder.getService()
            serviceBound.value = true
        }
        
        override fun onServiceDisconnected(name: ComponentName?) {
            Log.d(TAG, "Service disconnected")
            connectionService.value = null
            serviceBound.value = false
        }
    }
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        Log.d(TAG, "onCreate called")
        
        // Initialize notification channel
        NotificationHelper.createNotificationChannel(this)
        
        authManager = AuthManager(this)
        
        // Check if token needs refresh
        checkAndRefreshToken()
        
        setContent {
            AlfredTheme {
                // Check if this is first run (no gateway URL configured)
                val prefs = getSharedPreferences("alfred_settings", Context.MODE_PRIVATE)
                val gatewayUrl = prefs.getString("gateway_url", null)
                var showSetup = remember { mutableStateOf(gatewayUrl == null) }
                
                when {
                    showSetup.value -> {
                        // First run - show setup dialog
                        FirstRunSetup(
                            onComplete = { url ->
                                prefs.edit().putString("gateway_url", url).apply()
                                showSetup.value = false
                            }
                        )
                    }
                    isLoggedIn.value -> {
                        // Show main app UI
                        MainScreen(
                            connectionService = connectionService.value,
                            serviceBound = serviceBound.value,
                            onLogout = {
                                stopService()
                                authManager.logout()
                                isLoggedIn.value = false
                            },
                            onAuthError = {
                                // Connection got 401 - try to refresh token
                                Log.w(TAG, "Auth error from connection, attempting token refresh")
                                refreshTokenOrLogout()
                            }
                        )
                    }
                    else -> {
                        // Show login screen
                        LoginScreen(
                            onLoginClick = {
                                authManager.startLogin(this) { success, _ ->
                                    if (success) {
                                        isLoggedIn.value = true
                                    }
                                }
                            }
                        )
                    }
                }
            }
        }
    }
    
    private fun checkAndRefreshToken() {
        if (!authManager.isLoggedIn()) {
            Log.d(TAG, "Not logged in")
            stopService()
            isLoggedIn.value = false
            accessToken.value = ""
            return
        }
        
        if (authManager.needsRefresh()) {
            Log.d(TAG, "Token needs refresh, refreshing...")
            refreshTokenOrLogout()
        } else {
            Log.d(TAG, "Token is still valid")
            val token = authManager.getAccessToken() ?: ""
            accessToken.value = token
            isLoggedIn.value = true
            
            // Start/bind service if not already bound
            if (!serviceBound.value && token.isNotEmpty()) {
                startAndBindService(token)
            }
        }
    }
    
    private fun refreshTokenOrLogout() {
        authManager.refreshToken(
            onSuccess = {
                Log.d(TAG, "Token refresh successful")
                val newToken = authManager.getAccessToken() ?: ""
                accessToken.value = newToken
                isLoggedIn.value = true
                
                // Update service with new token
                if (serviceBound.value && newToken.isNotEmpty()) {
                    connectionService.value?.reconnectWithToken(newToken)
                } else if (newToken.isNotEmpty()) {
                    startAndBindService(newToken)
                }
            },
            onError = { error ->
                Log.e(TAG, "Token refresh failed: $error - logging out")
                stopService()
                authManager.logout()
                accessToken.value = ""
                isLoggedIn.value = false
            }
        )
    }
    
    private fun startAndBindService(token: String) {
        Log.d(TAG, "Starting and binding to connection service")
        
        // Start foreground service
        AlfredConnectionService.start(
            context = this,
            gatewayUrl = "ws://192.168.1.190:18790", // Proxy URL
            accessToken = token,
            userId = "shadow" // This will be extracted from JWT by service
        )
        
        // Bind to service
        val intent = Intent(this, AlfredConnectionService::class.java)
        bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)
    }
    
    private fun stopService() {
        Log.d(TAG, "Stopping connection service")
        if (serviceBound.value) {
            unbindService(serviceConnection)
            serviceBound.value = false
        }
        AlfredConnectionService.stop(this)
        connectionService.value = null
    }
    
    override fun onResume() {
        super.onResume()
        Log.d(TAG, "onResume called")
        // Check if we just logged in (after OAuth callback) or if token needs refresh
        checkAndRefreshToken()
    }
    
    override fun onDestroy() {
        super.onDestroy()
        // Unbind from service (but don't stop it - it continues in background)
        if (serviceBound.value) {
            unbindService(serviceConnection)
            serviceBound.value = false
        }
        authManager.dispose()
    }
}

/**
 * First-run setup screen to configure gateway URL.
 * Automatically adds wss:// or ws:// based on hostname.
 */
@Composable
fun FirstRunSetup(onComplete: (String) -> Unit) {
    var hostname by remember { mutableStateOf("") }
    var useInsecure by remember { mutableStateOf(false) }
    var errorMessage by remember { mutableStateOf("") }
    
    // Compute the full URL
    val fullUrl = remember(hostname, useInsecure) {
        if (hostname.isBlank()) {
            ""
        } else {
            val cleaned = hostname.trim()
                .removePrefix("ws://")
                .removePrefix("wss://")
                .removePrefix("http://")
                .removePrefix("https://")
            
            val protocol = if (useInsecure) "ws://" else "wss://"
            "$protocol$cleaned"
        }
    }
    
    AlertDialog(
        onDismissRequest = { /* Can't dismiss - required setup */ },
        title = {
            Text(
                text = "Welcome to Alfred Mobile",
                style = MaterialTheme.typography.headlineSmall
            )
        },
        text = {
            Column(
                modifier = Modifier.fillMaxWidth()
            ) {
                Text(
                    text = "Enter your OpenClaw Gateway hostname or IP address.",
                    style = MaterialTheme.typography.bodyMedium,
                    modifier = Modifier.padding(bottom = 16.dp)
                )
                
                OutlinedTextField(
                    value = hostname,
                    onValueChange = { 
                        hostname = it
                        errorMessage = ""
                    },
                    label = { Text("Gateway Hostname") },
                    placeholder = { Text("alfred.yourdomain.com") },
                    singleLine = true,
                    modifier = Modifier.fillMaxWidth(),
                    isError = errorMessage.isNotEmpty()
                )
                
                androidx.compose.foundation.layout.Row(
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(top = 8.dp),
                    verticalAlignment = androidx.compose.ui.Alignment.CenterVertically
                ) {
                    androidx.compose.material3.Checkbox(
                        checked = useInsecure,
                        onCheckedChange = { useInsecure = it }
                    )
                    Text(
                        text = "Use insecure connection (ws://)",
                        style = MaterialTheme.typography.bodySmall,
                        modifier = Modifier.padding(start = 8.dp)
                    )
                }
                
                if (fullUrl.isNotEmpty()) {
                    Text(
                        text = "Will connect to: $fullUrl",
                        style = MaterialTheme.typography.bodySmall,
                        color = MaterialTheme.colorScheme.primary,
                        modifier = Modifier.padding(top = 8.dp)
                    )
                }
                
                if (errorMessage.isNotEmpty()) {
                    Text(
                        text = errorMessage,
                        color = MaterialTheme.colorScheme.error,
                        style = MaterialTheme.typography.bodySmall,
                        modifier = Modifier.padding(top = 4.dp)
                    )
                }
                
                Text(
                    text = "Example: alfred.yourdomain.com or 192.168.1.169:18790",
                    style = MaterialTheme.typography.bodySmall,
                    color = MaterialTheme.colorScheme.onSurfaceVariant,
                    modifier = Modifier.padding(top = 8.dp)
                )
            }
        },
        confirmButton = {
            Button(
                onClick = {
                    val trimmed = hostname.trim()
                    if (trimmed.isEmpty()) {
                        errorMessage = "Hostname is required"
                    } else {
                        onComplete(fullUrl)
                    }
                }
            ) {
                Text("Continue")
            }
        }
    )
}
