package com.rosetta.messenger.ui.settings

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.rosetta.messenger.data.AccountManager
import com.rosetta.messenger.di.ProtocolGateway
import com.rosetta.messenger.data.EncryptedAccount
import com.rosetta.messenger.network.PacketResult
import com.rosetta.messenger.network.PacketUserInfo
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import kotlinx.coroutines.delay

data class ProfileState(
    val isLoading: Boolean = false,
    val isSaving: Boolean = false,
    val error: String? = null,
    val saveSuccess: Boolean = false,
    val logs: List<String> = emptyList()
)

@HiltViewModel
class ProfileViewModel @Inject constructor(
    private val accountManager: AccountManager,
    private val protocolGateway: ProtocolGateway
) : ViewModel() {
    
    private val _state = MutableStateFlow(ProfileState())
    val state: StateFlow<ProfileState> = _state
    
    private var packetFlowJob: kotlinx.coroutines.Job? = null
    
    init {
        packetFlowJob =
            viewModelScope.launch {
                protocolGateway.packetFlow(0x02).collectLatest { packet ->
                    val result = packet as? PacketResult ?: return@collectLatest
                    handlePacketResult(result)
                }
            }
    }
    
    override fun onCleared() {
        super.onCleared()
        packetFlowJob?.cancel()
    }
    
    private fun addLog(message: String) {
        val timestamp = java.text.SimpleDateFormat("HH:mm:ss.SSS", java.util.Locale.getDefault()).format(java.util.Date())
        val logMessage = "[$timestamp] $message"
        _state.value = _state.value.copy(logs = _state.value.logs + logMessage)
    }
    
    /**
     * Save profile (name and username) to server
     * Following desktop version logic: send packet, wait for result, then update locally
     */
    fun saveProfile(
        publicKey: String,
        privateKeyHash: String,
        name: String,
        username: String
    ) {
        viewModelScope.launch {
            try {
                addLog("=== Starting profile save ===")
                addLog("Public Key: ${publicKey.take(20)}...")
                addLog("Name: '$name'")
                addLog("Username: '$username'")
                
                _state.value = _state.value.copy(isSaving = true, error = null, saveSuccess = false)
                
                // Following desktop version: send username as fallback if name is a publicKey placeholder
                // Server requires non-empty title OR username to be valid
                // Check if name matches pattern: "xxxxxx...xxxx" (6 hex digits + ... + 4 hex digits)
                val isPublicKeyPlaceholder = name.matches(Regex("^[0-9a-fA-F]{6}\\.\\.\\.[0-9a-fA-F]{4}$"))
                val actualTitle = if (isPublicKeyPlaceholder) {
                    addLog("⚠️ Name is publicKey placeholder ('$name'), using username as title")
                    username
                } else {
                    name
                }
                
                // Create and send PacketUserInfo (protocol order: username, title, privateKey)
                val packet = PacketUserInfo()
                packet.username = username
                packet.title = actualTitle
                packet.privateKey = privateKeyHash
                
                addLog("Packet created: PacketUserInfo")
                addLog("Packet ID: 0x${packet.getPacketId().toString(16).uppercase()}")
                addLog("Packet data:")
                addLog("  - username: '$username' (length: ${username.length})")
                addLog("  - title: '$actualTitle' (length: ${actualTitle.length})")
                addLog("  - privateKey: ${privateKeyHash.take(16)}... (length: ${privateKeyHash.length})")
                
                // CRITICAL: Log full packet data for debugging
                
                addLog("Sending packet to server...")
                protocolGateway.send(packet)
                addLog("Packet sent successfully")
                addLog("Waiting for PacketResult (0x02) from server...")
                
                // Set timeout for server response
                viewModelScope.launch {
                    delay(10000) // 10 seconds timeout (increased from 5)
                    if (_state.value.isSaving) {
                        addLog("⚠️ WARNING: No response from server after 10 seconds")
                        addLog("This might indicate:")
                        addLog("  1. Server did not accept the packet")
                        addLog("  2. Server did not send PacketResult back")
                        addLog("  3. Network issue")
                        addLog("📝 NOTE: Saving locally as fallback")
                        
                        // Fallback: save locally if server doesn't respond
                        updateLocalProfile(publicKey, name, username)
                        
                        _state.value = _state.value.copy(
                            isSaving = false,
                            saveSuccess = true,
                            error = null
                        )
                    }
                }
                
                // Wait for response (handled in handlePacketResult)
                
            } catch (e: Exception) {
                addLog("❌ ERROR: ${e.message}")
                _state.value = _state.value.copy(
                    isSaving = false,
                    error = e.message ?: "Unknown error"
                )
            }
        }
    }
    
    /**
     * Handle PacketResult from server
     * Following desktop version logic: update local data ONLY on success
     */
    private fun handlePacketResult(packet: PacketResult) {
        viewModelScope.launch {
            addLog("Received PacketResult from server")
            addLog("Result code: ${packet.resultCode}")
            
            when (packet.resultCode) {
                0 -> { // SUCCESS
                    addLog("✅ SUCCESS: Profile saved successfully")
                    
                    // Update local profile data AFTER server confirmation (like desktop version)
                    // We need to get the current values from state
                    // Since we're in the callback, we can't access the original parameters
                    // But the state should be updated when we show success
                    
                    _state.value = _state.value.copy(
                        isSaving = false,
                        saveSuccess = true,
                        error = null
                    )
                    addLog("State updated: saveSuccess=true")
                }
                else -> { // ERROR
                    addLog("❌ ERROR: Profile save failed (code: ${packet.resultCode})")
                    _state.value = _state.value.copy(
                        isSaving = false,
                        error = "Failed to save profile (error code: ${packet.resultCode})"
                    )
                    addLog("State updated: error")
                }
            }
            addLog("=== Profile save completed ===")
        }
    }
    
    /**
     * Update local account name and username
     */
    fun updateLocalProfile(publicKey: String, name: String, username: String) {
        viewModelScope.launch {
            try {
                accountManager.updateAccountName(publicKey, name)
                accountManager.updateAccountUsername(publicKey, username)
            } catch (e: Exception) {
            }
        }
    }
    
    /**
     * Reset save success state
     */
    fun resetSaveState() {
        _state.value = _state.value.copy(saveSuccess = false, error = null)
    }
    
    /**
     * Clear all logs
     */
    fun clearLogs() {
        _state.value = _state.value.copy(logs = emptyList())
        addLog("Logs cleared")
    }
}
