package com.mistral.chat.ui

import android.content.Context
import android.content.SharedPreferences
import android.os.Build
import android.os.Bundle
import android.view.KeyEvent
import android.view.View
import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputMethodManager
import android.view.MenuItem
import android.widget.ImageButton
import android.widget.ImageView
import android.widget.PopupMenu
import android.widget.TextView
import android.widget.Toast
import android.widget.EditText
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.view.GravityCompat
import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.security.crypto.EncryptedSharedPreferences
import androidx.security.crypto.MasterKey
import com.google.android.material.color.DynamicColors
import com.google.android.material.navigation.NavigationView
import com.google.android.material.progressindicator.LinearProgressIndicator
import com.google.android.material.textfield.TextInputEditText
import com.google.android.material.button.MaterialButton
import com.google.gson.Gson
import com.mistral.chat.R
import com.mistral.chat.api.MistralClient
import com.mistral.chat.data.ChatDatabase
import com.mistral.chat.data.Message
import com.mistral.chat.data.MessageEntity
import com.mistral.chat.data.Profile
import com.mistral.chat.data.Session
import com.mistral.chat.data.toMessage
import com.mistral.chat.data.toEntity
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.withTimeout
import kotlinx.coroutines.withTimeoutOrNull
import kotlinx.coroutines.withContext

class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {

    private lateinit var recyclerView: RecyclerView
    private lateinit var adapter: MessageAdapter
    private lateinit var inputField: TextInputEditText
    private lateinit var sendButton: ImageView
    private lateinit var progressIndicator: LinearProgressIndicator
    private lateinit var logoButton: ImageView
    private lateinit var menuButton: ImageButton
    private lateinit var toolbarTitle: TextView
    private lateinit var hamburgerButton: ImageButton
    private lateinit var drawerLayout: androidx.drawerlayout.widget.DrawerLayout
    private lateinit var navigationView: NavigationView
    private lateinit var rightPanel: View
    private lateinit var gson: Gson
    private var currentJob: kotlinx.coroutines.Job? = null

    private var client: MistralClient? = null
    private val messages = mutableListOf<Message>()
    private var availableModels: List<Pair<String, String>> = emptyList()
    private var selectedModelName: String = "mistral-small-latest"
    private lateinit var prefs: SharedPreferences
    private lateinit var encryptedPrefs: SharedPreferences
    private lateinit var database: ChatDatabase
    
    private val profiles = mutableListOf<Profile>()
    private val sessions = mutableListOf<Session>()
    private var currentProfileId: Long? = null
    private var currentSessionId: Long? = null
    private var profilesAdapter: ProfilesAdapter? = null
    private var isRightPanelVisible = false
    private var isLeftDrawerOpen = false
    private var userMessageCount = 0
    private var titleGenerationJob: kotlinx.coroutines.Job? = null
    private var isFirstLoad = true

    companion object {
        private const val PREFS_NAME = "mistral_chat_prefs"
        private const val KEY_API_KEY = "api_key"
        private const val KEY_NEW_SESSION_ON_START = "new_session_on_start"
        private const val KEY_LAST_PROFILE_ID = "last_profile_id"
        private const val KEY_SELECTED_MODEL = "selected_model"
        private const val MAX_PROFILES = 10
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            DynamicColors.applyToActivityIfAvailable(this)
        }
        
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        gson = Gson()
        prefs = getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
        
        val savedModel = prefs.getString(KEY_SELECTED_MODEL, null)
        if (savedModel != null) {
            selectedModelName = savedModel
        }
        
        val masterKey = MasterKey.Builder(this)
            .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
            .build()
        encryptedPrefs = EncryptedSharedPreferences.create(
            this,
            PREFS_NAME + "_secure",
            masterKey,
            EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
            EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
        )
        
        if (!hasApiKey()) {
            showApiKeyDialog()
        }
        
        client = MistralClient(getApiKey())

        logoButton = findViewById(R.id.logoButton)
        menuButton = findViewById(R.id.menuButton)
        hamburgerButton = findViewById(R.id.hamburgerButton)
        toolbarTitle = findViewById(R.id.toolbarTitle)
        recyclerView = findViewById(R.id.recyclerView)
        inputField = findViewById(R.id.inputField)
        sendButton = findViewById(R.id.sendButton)
        progressIndicator = findViewById(R.id.progressIndicator)
        drawerLayout = findViewById(R.id.drawerLayout)
        navigationView = findViewById(R.id.navigationView)
        rightPanel = findViewById(R.id.rightPanelContainer)

        database = ChatDatabase.getInstance(this)
        
        setupToolbar()
        setupRecyclerView()
        setupDrawer()
        setupRightPanel()
        loadModels()
        setupInput()
        loadProfilesAndSessions()

        inputField.postDelayed({
            val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
            inputField.requestFocus()
            imm.showSoftInput(inputField, InputMethodManager.SHOW_IMPLICIT)
        }, 300)
    }

    private fun setupDrawer() {
        navigationView.setNavigationItemSelectedListener(this)
        
        hamburgerButton.setOnClickListener {
            drawerLayout.openDrawer(GravityCompat.START)
        }

        drawerLayout.addDrawerListener(object : androidx.drawerlayout.widget.DrawerLayout.DrawerListener {
            override fun onDrawerSlide(drawerView: View, slideOffset: Float) {}
            override fun onDrawerOpened(drawerView: View) {
                if (drawerView == navigationView) {
                    isLeftDrawerOpen = true
                } else if (drawerView == rightPanel) {
                    isRightPanelVisible = true
                }
            }
            override fun onDrawerClosed(drawerView: View) {
                if (drawerView == navigationView) {
                    isLeftDrawerOpen = false
                } else if (drawerView == rightPanel) {
                    isRightPanelVisible = false
                }
            }
            override fun onDrawerStateChanged(newState: Int) {}
        })
    }

    override fun onNavigationItemSelected(item: MenuItem): Boolean {
        when (item.itemId) {
            R.id.action_profiles -> {
                showProfilesManager()
            }
            R.id.action_api_key -> {
                showApiKeyDialog()
            }
            R.id.action_clear_all -> {
                showClearAllDialog()
            }
            R.id.action_settings -> {
                showSettingsDialog()
            }
            R.id.action_about -> {
                showAboutDialog()
            }
        }
        drawerLayout.closeDrawer(GravityCompat.START)
        return true
    }

    private fun showProfilesManager() {
        if (profiles.isEmpty()) {
            showCreateProfileDialog()
        } else {
            val options = profiles.map { it.name }.toMutableList()
            if (profiles.size < MAX_PROFILES) {
                options.add("Создать новый профиль")
            }
            
            AlertDialog.Builder(this)
                .setTitle(R.string.manage_profiles)
                .setItems(options.toTypedArray()) { _, which ->
                    if (which < profiles.size) {
                        showEditProfileDialog(profiles[which])
                    } else if (profiles.size < MAX_PROFILES) {
                        showCreateProfileDialog()
                    }
                }
                .show()
        }
    }

    private fun showCreateProfileDialog() {
        showProfileDialog(null)
    }

    private fun showEditProfileDialog(profile: Profile) {
        showProfileDialog(profile)
    }

    private fun showClearAllDialog() {
        val dialogView = layoutInflater.inflate(R.layout.dialog_clear_all, null)
        val deleteProfilesCheckbox = dialogView.findViewById<android.widget.CheckBox>(R.id.deleteProfilesCheckbox)
        
        AlertDialog.Builder(this)
            .setTitle(R.string.clear_all_history)
            .setView(dialogView)
            .setPositiveButton(R.string.yes) { _, _ ->
                val deleteProfiles = deleteProfilesCheckbox.isChecked
                
                lifecycleScope.launch {
                    database.sessionDao().deleteAll()
                    
                    // Wait for transaction to complete
                    kotlinx.coroutines.delay(100)
                    
                    if (deleteProfiles) {
                        database.profileDao().deleteAll()
                        currentProfileId = null
                        prefs.edit().remove(KEY_LAST_PROFILE_ID).apply()
                        profiles.clear()
                    }
                    
                    messages.clear()
                    adapter.notifyDataSetChanged()
                    
                    // Create fresh session with null profileId
                    val newSession = Session(
                        profileId = null,
                        title = "Новая сессия"
                    )
                    val sessionId = database.sessionDao().insert(newSession)
                    currentSessionId = sessionId
                    userMessageCount = 0
                    messages.clear()
                    adapter.notifyDataSetChanged()
                    sessions.clear()
                    sessions.add(newSession.copy(id = sessionId))
                    
                    updateRightPanel()
                    Toast.makeText(this@MainActivity, R.string.history_cleared, Toast.LENGTH_SHORT).show()
                }
            }
            .setNegativeButton(R.string.no, null)
            .show()
    }

    private fun showSettingsDialog() {
        val currentSetting = prefs.getBoolean(KEY_NEW_SESSION_ON_START, false)
        val options = arrayOf("Открывать последнюю сессию", "Начинать новую сессию")
        val selectedIndex = if (currentSetting) 1 else 0
        
        AlertDialog.Builder(this)
            .setTitle(R.string.settings)
            .setSingleChoiceItems(options, selectedIndex) { dialog, which ->
                val newValue = which == 1
                prefs.edit().putBoolean(KEY_NEW_SESSION_ON_START, newValue).apply()
                dialog.dismiss()
                Toast.makeText(this, "Настройка сохранена", Toast.LENGTH_SHORT).show()
            }
            .setNegativeButton(R.string.cancel, null)
            .show()
    }

    private fun showAboutDialog() {
        AlertDialog.Builder(this)
            .setTitle(R.string.about)
            .setMessage(R.string.about_text)
            .setPositiveButton(R.string.ok, null)
            .show()
    }

    private fun setupToolbar() {
        hamburgerButton.isVisible = true
        
        logoButton.setOnClickListener {
            showModelSelectorDialog()
        }
        
        menuButton.setOnClickListener { view ->
            showRightPanelMenu(view)
        }
    }

    private fun showRightPanelMenu(view: View) {
        if (isRightPanelVisible) {
            drawerLayout.closeDrawer(GravityCompat.END)
        } else {
            if (isLeftDrawerOpen) {
                drawerLayout.closeDrawer(GravityCompat.START)
            }
            drawerLayout.openDrawer(GravityCompat.END)
        }
    }

    private fun setupRightPanel() {
        val includedPanel = rightPanel.findViewById<View>(R.id.panelRightContent)
        val profilesRecyclerView = includedPanel.findViewById<RecyclerView>(R.id.profilesRecyclerView)
        val sessionsRecyclerView = includedPanel.findViewById<RecyclerView>(R.id.sessionsRecyclerView)
        val newSessionButton = includedPanel.findViewById<MaterialButton>(R.id.newSessionButton)
        
        profilesAdapter = ProfilesAdapter(
            profiles = profiles,
            onProfileClick = { profile -> selectProfile(profile) },
            onProfileLongClick = { profile -> showProfileOptions(profile) },
            getSelectedProfileId = { currentProfileId }
        )
        profilesRecyclerView.layoutManager = LinearLayoutManager(this)
        profilesRecyclerView.adapter = profilesAdapter
        
        val sessionsAdapter = SessionsAdapter(
            sessions = sessions,
            getCurrentSessionId = { currentSessionId },
            onSessionClick = { session -> selectSession(session) },
            onSessionLongClick = { session -> showSessionOptions(session) }
        )
        sessionsRecyclerView.layoutManager = LinearLayoutManager(this)
        sessionsRecyclerView.adapter = sessionsAdapter
        
        newSessionButton.setOnClickListener { createNewSession() }
    }
    
    private fun loadProfilesAndSessions() {
        lifecycleScope.launch {
            database.profileDao().getAllProfiles().collect { profileList ->
                profiles.clear()
                profiles.addAll(profileList)
                
                val lastProfileId = prefs.getLong(KEY_LAST_PROFILE_ID, -1L)
                val profileExists = profiles.any { it.id == lastProfileId }
                val currentStillValid = currentProfileId != null && profiles.any { it.id == currentProfileId }
                
                if (!currentStillValid) {
                    currentProfileId = if (lastProfileId > 0 && profileExists) {
                        lastProfileId
                    } else if (profiles.isNotEmpty()) {
                        profiles.first().id
                    } else {
                        null
                    }
                    val profileId = currentProfileId
                    if (profileId != null) {
                        prefs.edit().putLong(KEY_LAST_PROFILE_ID, profileId).apply()
                    }
                }
                
                profilesAdapter?.refresh()
                updateRightPanel()
            }
        }
        lifecycleScope.launch {
            database.sessionDao().getAllSessions().collect { sessionList ->
                sessions.clear()
                sessions.addAll(sessionList)
                updateRightPanel()
                
                val lastSessionId = prefs.getLong("last_session_id", -1L)
                
                if (currentSessionId == null && sessions.isNotEmpty() && isFirstLoad) {
                    val newSessionOnStart = prefs.getBoolean(KEY_NEW_SESSION_ON_START, false)
                    
                    if (newSessionOnStart) {
                        createNewSession()
                    } else if (lastSessionId > 0 && sessions.any { it.id == lastSessionId }) {
                        val session = sessions.find { it.id == lastSessionId }
                        if (session != null) {
                            selectSession(session)
                        } else {
                            selectSession(sessions.first())
                        }
                    } else {
                        selectSession(sessions.first())
                    }
                    isFirstLoad = false
                } else if (currentSessionId != null && !sessions.any { it.id == currentSessionId }) {
                    if (sessions.isNotEmpty()) {
                        selectSession(sessions.first())
                    }
                }
            }
        }
    }

    private fun updateRightPanel() {
        try {
            profilesAdapter?.refresh()
            val includedPanel = rightPanel.findViewById<View>(R.id.panelRightContent) ?: return
            val sessionsRecyclerView = includedPanel.findViewById<RecyclerView>(R.id.sessionsRecyclerView) ?: return
            (sessionsRecyclerView.adapter as? SessionsAdapter)?.notifyDataSetChanged()
        } catch (e: Exception) {
            // Panel not initialized yet
        }
    }

    private fun selectProfile(profile: Profile) {
        currentProfileId = profile.id
        prefs.edit().putLong(KEY_LAST_PROFILE_ID, profile.id).apply()
        profilesAdapter?.refresh()
        val profileName = profiles.find { it.id == currentProfileId }?.name ?: profile.name
        Toast.makeText(this, getString(R.string.profile_info, profileName), Toast.LENGTH_SHORT).show()
    }

    private fun showProfileOptions(profile: Profile) {
        val options = arrayOf("Редактировать", "Удалить")
        AlertDialog.Builder(this)
            .setTitle(profile.name)
            .setItems(options) { _, which ->
                when (which) {
                    0 -> editProfile(profile)
                    1 -> deleteProfile(profile)
                }
            }
            .show()
    }

    private fun editProfile(profile: Profile) {
        showProfileDialog(profile)
    }

    private fun deleteProfile(profile: Profile) {
        AlertDialog.Builder(this)
            .setTitle(R.string.delete)
            .setMessage("Удалить профиль ${profile.name}?")
            .setPositiveButton(R.string.yes) { _, _ ->
                lifecycleScope.launch {
                    database.profileDao().delete(profile)
                }
            }
            .setNegativeButton(R.string.no, null)
            .show()
    }

    private fun selectSession(session: Session) {
        currentSessionId = session.id
        userMessageCount = 0
        prefs.edit().putLong("last_session_id", session.id).apply()
        loadSessionMessages(session.id)
        updateRightPanel()
        drawerLayout.closeDrawer(GravityCompat.END)
    }

    private fun loadSessionMessages(sessionId: Long) {
        lifecycleScope.launch {
            val dbMessages = database.messageDao().getMessagesBySessionSync(sessionId)
            messages.clear()
            messages.addAll(dbMessages.map { it.toMessage() })
            adapter.notifyDataSetChanged()
        }
    }

    private fun showSessionOptions(session: Session) {
        val options = arrayOf("Переименовать", "Удалить")
        AlertDialog.Builder(this)
            .setTitle(session.title)
            .setItems(options) { _, which ->
                when (which) {
                    0 -> renameSession(session)
                    1 -> deleteSession(session)
                }
            }
            .show()
    }

    private fun renameSession(session: Session) {
        val input = EditText(this)
        input.setText(session.title)
        AlertDialog.Builder(this)
            .setTitle("Переименовать")
            .setView(input)
            .setPositiveButton(R.string.save) { _, _ ->
                val newTitle = input.text.toString().trim()
                if (newTitle.isNotEmpty()) {
                    lifecycleScope.launch {
                        database.sessionDao().updateTitle(session.id, newTitle)
                    }
                }
            }
            .setNegativeButton(R.string.cancel, null)
            .show()
    }

    private fun deleteSession(session: Session) {
        AlertDialog.Builder(this)
            .setTitle(R.string.delete)
            .setMessage("Удалить сессию ${session.title}?")
            .setPositiveButton(R.string.yes) { _, _ ->
                lifecycleScope.launch {
                    database.sessionDao().delete(session)
                }
            }
            .setNegativeButton(R.string.no, null)
            .show()
    }

    private fun createNewSession() {
        lifecycleScope.launch {
            val session = Session(
                profileId = if (currentProfileId != null && profiles.any { it.id == currentProfileId }) currentProfileId else null,
                title = "Новая сессия"
            )
            val sessionId = database.sessionDao().insert(session)
            currentSessionId = sessionId
            userMessageCount = 0
            messages.clear()
            adapter.notifyDataSetChanged()
            updateRightPanel()
            Toast.makeText(this@MainActivity, R.string.new_session, Toast.LENGTH_SHORT).show()
            drawerLayout.closeDrawer(GravityCompat.END)
        }
    }

    private fun showModelSelectorDialog() {
        val uniqueModels = availableModels.distinctBy { it.second }
        val modelNames = uniqueModels.map { it.second }.toTypedArray()
        val currentModelId = uniqueModels.find { it.first == selectedModelName }?.second 
            ?: uniqueModels.firstOrNull()?.second 
            ?: ""
        val currentIndex = uniqueModels.indexOfFirst { it.second == currentModelId }.coerceAtLeast(0)

        AlertDialog.Builder(this)
            .setTitle(R.string.select_model)
            .setSingleChoiceItems(modelNames, currentIndex) { dialog, which ->
                selectedModelName = uniqueModels[which].first
                prefs.edit().putString(KEY_SELECTED_MODEL, selectedModelName).apply()
                dialog.dismiss()
            }
            .setNegativeButton(R.string.cancel, null)
            .show()
    }

    private fun setupRecyclerView() {
        adapter = MessageAdapter(messages)
        recyclerView.layoutManager = LinearLayoutManager(this).apply {
            stackFromEnd = true
        }
        recyclerView.adapter = adapter
    }

    private fun setupInput() {
        sendButton.setOnClickListener {
            if (currentJob?.isActive == true) {
                cancelRequest()
            } else {
                sendInput()
            }
        }
        
        inputField.setOnEditorActionListener { _, actionId, event ->
            if (actionId == EditorInfo.IME_ACTION_SEND || actionId == EditorInfo.IME_ACTION_GO || actionId == EditorInfo.IME_ACTION_DONE || (event?.keyCode == KeyEvent.KEYCODE_ENTER && event.action == KeyEvent.ACTION_DOWN)) {
                sendInput()
                true
            } else {
                false
            }
        }
    }
    
    private fun sendInput() {
        val userInput = inputField.text?.toString()?.trim()
        if (userInput.isNullOrEmpty()) return

        if (currentSessionId == null) {
            createNewSessionAndSend(userInput)
            return
        }

        addMessage(Message(content = userInput, isUser = true, senderName = getCurrentProfileName()))
        
        inputField.text?.clear()
        sendMessage(userInput)
    }

    private fun createNewSessionAndSend(userInput: String) {
        lifecycleScope.launch {
            val session = Session(
                profileId = if (currentProfileId != null && profiles.any { it.id == currentProfileId }) currentProfileId else null,
                title = "Новая сессия"
            )
            val sessionId = database.sessionDao().insert(session)
            currentSessionId = sessionId
            userMessageCount = 0
            messages.clear()
            adapter.notifyDataSetChanged()
            updateRightPanel()
            
            addMessage(Message(content = userInput, isUser = true, senderName = getCurrentProfileName()))
            inputField.text?.clear()
            sendMessage(userInput)
        }
    }

    private fun generateSessionTitle(): kotlinx.coroutines.Job {
        val sessionId = currentSessionId ?: return kotlinx.coroutines.Job()
        
        return lifecycleScope.launch(Dispatchers.IO) {
            var attempts = 0
            val maxAttempts = 2
            
            while (attempts < maxAttempts && isActive) {
                attempts++
                try {
                    val recentMessages = messages.takeLast(4).map { msg ->
                        if (msg.isUser) "User: ${msg.content}" else "AI: ${msg.content}"
                    }.joinToString("\n")
                    
                    val prompt = "Кратко озаглавь этот чат в 3-5 слов. Отвечай только названием, без кавычек."
                    val fullPrompt = "$prompt\n\n$recentMessages"
                    
                    val result = withTimeoutOrNull(10000L) {
                        client?.chat(selectedModelName, listOf(
                            Message(content = fullPrompt, isUser = true)
                        ))
                    }
                    
                    if (!isActive) return@launch
                    
                    if (result != null) {
                        result.onSuccess { (response, _) ->
                            val title = response.trim().take(50)
                            if (title.isNotEmpty() && currentSessionId == sessionId) {
                                database.sessionDao().updateTitle(sessionId, title)
                                runOnUiThread {
                                    sessions.find { it.id == sessionId }?.let { session ->
                                        val index = sessions.indexOf(session)
                                        if (index >= 0) {
                                            sessions[index] = session.copy(title = title)
                                            updateRightPanel()
                                        }
                                    }
                                }
                            }
                        }
                        return@launch
                    }
                } catch (e: Exception) {
                    if (!isActive) return@launch
                }
                if (attempts < maxAttempts && isActive) {
                    kotlinx.coroutines.delay(1000L)
                }
            }
        }
    }

    private fun loadModels() {
        lifecycleScope.launch {
            val result = client?.getModels()
            result?.onSuccess { models ->
                availableModels = models
                val hasUserSelectedModel = prefs.contains(KEY_SELECTED_MODEL)
                if (!hasUserSelectedModel) {
                    runOnUiThread {
                        val codestralIndex = models.indexOfFirst { it.first.contains("codestral", ignoreCase = true) }
                        if (codestralIndex >= 0) {
                            selectedModelName = models[codestralIndex].first
                        } else if (models.isNotEmpty()) {
                            selectedModelName = models[0].first
                        }
                    }
                }
            }?.onFailure {
                availableModels = MistralClient.AVAILABLE_MODELS
                val hasUserSelectedModel = prefs.contains(KEY_SELECTED_MODEL)
                if (!hasUserSelectedModel) {
                    runOnUiThread {
                        selectedModelName = MistralClient.AVAILABLE_MODELS.firstOrNull()?.first ?: "mistral-small-latest"
                    }
                }
            }
        }
    }

    private fun addMessage(message: Message) {
        val isAssistantMessage = !message.isUser
        val newPosition = messages.size - 1
        
        messages.add(message)
        adapter.notifyItemInserted(newPosition)
        
        // Scroll to beginning of assistant messages so user sees the sender name first
        if (isAssistantMessage) {
            recyclerView.post {
                recyclerView.scrollToPosition(0)
                // Then scroll to show the new message from beginning
                val scrollAmount = (recyclerView.computeVerticalScrollExtent() - 200).coerceAtLeast(0)
                recyclerView.post {
                    recyclerView.scrollBy(0, scrollAmount)
                }
            }
        }
        
        val sessionId = currentSessionId
        if (sessionId != null) {
            lifecycleScope.launch {
                val entity = MessageEntity(
                    sessionId = sessionId,
                    content = message.content,
                    isUser = message.isUser,
                    timestamp = message.timestamp
                )
                database.messageDao().insert(entity)
                database.sessionDao().updateTimestamp(sessionId)
            }
        }
        
        recyclerView.postDelayed({
            recyclerView.scrollToPosition(messages.size - 1)
        }, 100)
    }

    private fun saveMessageToDatabase(sessionId: Long?, content: String, isUser: Boolean, senderName: String?) {
        if (sessionId != null) {
            lifecycleScope.launch {
                database.messageDao().insert(MessageEntity(
                    sessionId = sessionId,
                    content = content,
                    isUser = isUser,
                    timestamp = System.currentTimeMillis()
                ))
                database.sessionDao().updateTimestamp(sessionId)
            }
        }
    }

    private fun getApiKey(): String {
        return encryptedPrefs.getString(KEY_API_KEY, null) ?: ""
    }

    private fun hasApiKey(): Boolean {
        return encryptedPrefs.contains(KEY_API_KEY)
    }

    private fun saveApiKey(apiKey: String) {
        encryptedPrefs.edit().putString(KEY_API_KEY, apiKey).apply()
        client = MistralClient(apiKey)
    }

    private fun deleteApiKey() {
        encryptedPrefs.edit().remove(KEY_API_KEY).apply()
        Toast.makeText(this, getString(R.string.api_key_deleted), Toast.LENGTH_SHORT).show()
        showApiKeyDialog()
    }

    private fun showApiKeyDialog() {
        val currentKey = getApiKey()
        val hasCustomKey = currentKey.isNotEmpty()
        val displayKey = if (hasCustomKey && currentKey.length > 8) {
            currentKey.take(4) + "*".repeat(currentKey.length - 8) + currentKey.takeLast(4)
        } else if (hasCustomKey) {
            "******"
        } else {
            getString(R.string.no_api_key)
        }

        val dialogView = layoutInflater.inflate(R.layout.dialog_api_key, null)
        val inputField = dialogView.findViewById<TextInputEditText>(R.id.apiKeyInput)
        
        if (hasCustomKey) {
            inputField.setText(currentKey)
        }

        AlertDialog.Builder(this)
            .setTitle(R.string.api_key_title)
            .setMessage(getString(R.string.api_key_current, displayKey))
            .setView(dialogView)
            .setPositiveButton(R.string.save) { _, _ ->
                val newKey = inputField.text?.toString()?.trim()
                if (!newKey.isNullOrEmpty()) {
                    saveApiKey(newKey)
                    Toast.makeText(this, getString(R.string.api_key_saved), Toast.LENGTH_SHORT).show()
                } else {
                    Toast.makeText(this, getString(R.string.enter_api_key), Toast.LENGTH_SHORT).show()
                }
            }
            .apply {
                if (hasCustomKey) {
                    setNegativeButton(R.string.cancel, null)
                    setNeutralButton(R.string.delete) { _, _ ->
                        deleteApiKey()
                    }
                }
            }
            .setCancelable(false)
            .show()
    }

    private fun sendMessage(userInput: String) {
        val selectedModel = selectedModelName
        
        sendButton.isEnabled = false
        sendButton.setImageResource(R.drawable.ic_stop)
        progressIndicator.isVisible = true

        currentJob = lifecycleScope.launch {
            try {
                val profileContext = getSelectedProfileContext()

                val apiMessages = messages.map { msg ->
                    Message(
                        content = msg.content,
                        isUser = msg.isUser
                    )
                }.toMutableList()

                if (profileContext.isNotEmpty()) {
                    apiMessages.add(0, Message(content = profileContext, isUser = true))
                }

                val result = withTimeout(15000L) {
                    client?.chat(selectedModel, apiMessages) ?: Result.failure(Exception("Client not initialized"))
                }

                if (!isActive) return@launch

                result.onSuccess { (response, usedModel) ->
                    val displayModel = usedModel.ifEmpty { "Assistant" }
                    addMessage(Message(content = response, isUser = false, senderName = displayModel))
                    lifecycleScope.launch {
                        saveMessageToDatabase(currentSessionId, response, false, displayModel)
                    }
                    
                    val count = userMessageCount + 1
                    userMessageCount = count
                    if (count == 2 && titleGenerationJob?.isActive != true) {
                        titleGenerationJob = generateSessionTitle()
                    }
                }.onFailure { error ->
                    if (!isActive) return@launch
                    val errorMessage = error.message ?: "Unknown error"
                    if (!errorMessage.contains("cancelled", ignoreCase = true)) {
                        val userFriendlyMessage = getUserFriendlyError(errorMessage)
                        addMessage(Message(content = userFriendlyMessage, isUser = false, senderName = "Error"))
                    }
                }
                
                sendButton.isEnabled = true
                sendButton.setImageResource(R.drawable.ic_mistral_logo)
                progressIndicator.isVisible = false
            } catch (e: kotlinx.coroutines.CancellationException) {
                if (!isActive) return@launch
                addMessage(Message(content = "Запрос отменён", isUser = false, senderName = "System"))
                sendButton.isEnabled = true
                sendButton.setImageResource(R.drawable.ic_mistral_logo)
                progressIndicator.isVisible = false
            } catch (e: Exception) {
                if (!isActive) return@launch
                val userFriendlyMessage = getUserFriendlyError(e.message ?: "Unknown error")
                addMessage(Message(content = userFriendlyMessage, isUser = false, senderName = "Error"))
                sendButton.isEnabled = true
                sendButton.setImageResource(R.drawable.ic_mistral_logo)
                progressIndicator.isVisible = false
            }
        }
    }
    
    private fun cancelRequest() {
        currentJob?.cancel()
        titleGenerationJob?.cancel()
        client?.cancelRequest()
        
        sendButton.isEnabled = true
        sendButton.setImageResource(R.drawable.ic_mistral_logo)
        progressIndicator.isVisible = false
    }

    private fun getSelectedProfileContext(): String {
        if (currentProfileId == null) return ""
        
        val profile = profiles.find { it.id == currentProfileId }
        if (profile == null) return ""
        
        return buildString {
            append("[Profile: ${profile.name}]\n")
            if (profile.bio.isNotBlank()) append("Bio: ${profile.bio}\n")
            if (profile.preferences.isNotBlank()) append("Preferences: ${profile.preferences}\n")
        }
    }

    private fun getCurrentProfileName(): String {
        if (currentProfileId == null) return "Вы"
        val profileName = profiles.find { it.id == currentProfileId }?.name
        return if (profileName.isNullOrBlank()) "Вы" else profileName
    }

    private fun showProfileDialog(existingProfile: Profile? = null) {
        if (existingProfile == null && profiles.size >= MAX_PROFILES) {
            Toast.makeText(this, "Максимум $MAX_PROFILES профилей", Toast.LENGTH_SHORT).show()
            return
        }
        
        val dialogView = layoutInflater.inflate(R.layout.dialog_profile, null)
        
        val nameInput = dialogView.findViewById<TextInputEditText>(R.id.nameInput)
        val bioInput = dialogView.findViewById<TextInputEditText>(R.id.bioInput)
        val preferencesInput = dialogView.findViewById<TextInputEditText>(R.id.preferencesInput)

        existingProfile?.let {
            nameInput.setText(it.name)
            bioInput.setText(it.bio)
            preferencesInput.setText(it.preferences)
        }

        val dialog = AlertDialog.Builder(this)
            .setTitle(if (existingProfile != null) R.string.profile_title else R.string.new_profile)
            .setView(dialogView)
            .setPositiveButton(R.string.save) { _, _ ->
                val name = nameInput.text?.toString()?.trim() ?: ""
                if (name.isNotEmpty()) {
                    lifecycleScope.launch {
                        if (existingProfile != null) {
                            database.profileDao().update(existingProfile.copy(
                                name = name,
                                bio = bioInput.text?.toString() ?: "",
                                preferences = preferencesInput.text?.toString() ?: "",
                                updatedAt = System.currentTimeMillis()
                            ))
                        } else {
                            val newId = database.profileDao().insert(Profile(
                                name = name,
                                bio = bioInput.text?.toString() ?: "",
                                preferences = preferencesInput.text?.toString() ?: ""
                            ))
                            if (currentProfileId == null) {
                                currentProfileId = newId
                            }
                        }
                    }
                }
            }
            .setNegativeButton(R.string.cancel, null)

        if (existingProfile != null) {
            dialog.setNeutralButton(R.string.delete) { _, _ ->
                lifecycleScope.launch {
                    database.profileDao().delete(existingProfile)
                    if (currentProfileId == existingProfile.id) {
                        currentProfileId = null
                    }
                }
            }
        }

        dialog.show()
    }

    private fun showClearChatDialog() {
        AlertDialog.Builder(this)
            .setMessage(R.string.clear_chat_confirm)
            .setPositiveButton(R.string.yes) { _, _ ->
                messages.clear()
                adapter.notifyDataSetChanged()
            }
            .setNegativeButton(R.string.no, null)
            .show()
    }

    private fun getUserFriendlyError(error: String): String {
        return when {
            error.contains("timeout", ignoreCase = true) ||
            error.contains("TimedOut", ignoreCase = true) ||
            error.contains("SocketTimeoutException", ignoreCase = true) || 
            error.contains("connection abort", ignoreCase = true) ||
            error.contains("Software caused connection abort", ignoreCase = true) ->
                "⚠️ Время ожидания истекло. Проверьте интернет-соединение и попробуйте снова."
            
            error.contains("network", ignoreCase = true) ||
            error.contains("Unable to resolve host", ignoreCase = true) ||
            error.contains("No route to host", ignoreCase = true) ->
                "🌐 Нет подключения к интернету. Проверьте соединение и попробуйте снова."
            
            error.contains("401", ignoreCase = true) ||
            error.contains("unauthorized", ignoreCase = true) ->
                "🔑 Ошибка авторизации. Проверьте API ключ в настройках приложения."
            
            error.contains("403", ignoreCase = true) ||
            error.contains("forbidden", ignoreCase = true) ->
                "🚫 Доступ запрещён. Возможно, API ключ истёк или недействителен."
            
            error.contains("429", ignoreCase = true) ||
            error.contains("rate limit", ignoreCase = true) ||
            error.contains("too many requests", ignoreCase = true) ->
                "⏳ Слишком много запросов. Подождите немного и попробуйте снова."
            
            error.contains("500", ignoreCase = true) ||
            error.contains("internal server error", ignoreCase = true) ->
                "🔧 Ошибка сервера Mistral. Попробуйте выбрать другую модель или повторите позже."
            
            error.contains("503", ignoreCase = true) ||
            error.contains("service unavailable", ignoreCase = true) ->
                "🛠️ Сервис временно недоступен. Попробуйте позже."
            
            error.contains("404", ignoreCase = true) ||
            error.contains("not found", ignoreCase = true) ->
                "❓ Ресурс не найден. Попробуйте выбрать другую модель."
            
            error.contains("null", ignoreCase = true) ||
            error.contains("empty response", ignoreCase = true) ->
                "📭 Пустой ответ от сервера. Попробуйте ещё раз."
            
            else -> "❌ Произошла ошибка: $error"
        }
    }
}