package com.manalejandro.odb2bluetooth.ui.viewmodel

import android.app.Application
import android.bluetooth.BluetoothDevice
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import com.manalejandro.odb2bluetooth.data.bluetooth.BluetoothService
import com.manalejandro.odb2bluetooth.data.database.ObdDatabase
import com.manalejandro.odb2bluetooth.data.obd.ObdCommand
import com.manalejandro.odb2bluetooth.data.obd.ObdCommands
import com.manalejandro.odb2bluetooth.data.repository.ObdRepository
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch

/**
 * Main ViewModel for Bluetooth connection and OBD communication
 */
class MainViewModel(application: Application) : AndroidViewModel(application) {

    private val database = ObdDatabase.getDatabase(application)
    val repository = ObdRepository(
        database.vehicleDao(),
        database.obdSignalDao(),
        database.dtcCodeDao()
    )

    val bluetoothService = BluetoothService()

    private val _pairedDevices = MutableStateFlow<List<BluetoothDevice>>(emptyList())
    val pairedDevices: StateFlow<List<BluetoothDevice>> = _pairedDevices

    private val _selectedDevice = MutableStateFlow<BluetoothDevice?>(null)
    val selectedDevice: StateFlow<BluetoothDevice?> = _selectedDevice

    private val _commandHistory = MutableStateFlow<List<CommandResult>>(emptyList())
    val commandHistory: StateFlow<List<CommandResult>> = _commandHistory

    private val _isLoading = MutableStateFlow(false)
    val isLoading: StateFlow<Boolean> = _isLoading

    private val _errorMessage = MutableStateFlow<String?>(null)
    val errorMessage: StateFlow<String?> = _errorMessage

    /**
     * Load paired Bluetooth devices
     */
    fun loadPairedDevices() {
        try {
            _pairedDevices.value = bluetoothService.getPairedDevices()
        } catch (e: SecurityException) {
            _errorMessage.value = "Bluetooth permission denied"
        }
    }

    /**
     * Connect to a Bluetooth device
     */
    fun connectToDevice(device: BluetoothDevice) {
        viewModelScope.launch {
            _isLoading.value = true
            _selectedDevice.value = device

            bluetoothService.connect(device).fold(
                onSuccess = {
                    _errorMessage.value = null
                },
                onFailure = { error ->
                    _errorMessage.value = "Connection failed: ${error.message}"
                    _selectedDevice.value = null
                }
            )

            _isLoading.value = false
        }
    }

    /**
     * Disconnect from current device
     */
    fun disconnect() {
        bluetoothService.disconnect()
        _selectedDevice.value = null
        _commandHistory.value = emptyList()
    }

    /**
     * Send a command to the OBD device
     */
    fun sendCommand(command: String) {
        viewModelScope.launch {
            _isLoading.value = true

            bluetoothService.sendCommand(command).fold(
                onSuccess = { response ->
                    val parsed = ObdCommands.parseResponse(command, response) ?: response
                    addCommandToHistory(command, response, parsed)
                    _errorMessage.value = null
                },
                onFailure = { error ->
                    _errorMessage.value = "Command failed: ${error.message}"
                    addCommandToHistory(command, "", "Error: ${error.message}")
                }
            )

            _isLoading.value = false
        }
    }

    /**
     * Run generic safe diagnostic test
     */
    fun runDiagnosticTest() {
        viewModelScope.launch {
            _commandHistory.value = emptyList()

            for (cmd in ObdCommands.SAFE_DIAGNOSTIC_COMMANDS) {
                sendCommand(cmd.command)
                kotlinx.coroutines.delay(500) // Wait between commands
            }
        }
    }

    /**
     * Clear command history
     */
    fun clearHistory() {
        _commandHistory.value = emptyList()
    }

    /**
     * Clear error message
     */
    fun clearError() {
        _errorMessage.value = null
    }

    private fun addCommandToHistory(command: String, rawResponse: String, parsedResponse: String) {
        val history = _commandHistory.value.toMutableList()
        history.add(
            0, // Add to beginning
            CommandResult(
                command = command,
                rawResponse = rawResponse,
                parsedResponse = parsedResponse,
                timestamp = System.currentTimeMillis()
            )
        )
        // Keep only last 50 commands
        _commandHistory.value = history.take(50)
    }

    override fun onCleared() {
        super.onCleared()
        bluetoothService.disconnect()
    }
}

/**
 * Data class representing a command result
 */
data class CommandResult(
    val command: String,
    val rawResponse: String,
    val parsedResponse: String,
    val timestamp: Long
)

