package com.gestoreasy.sync

import android.content.Context
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import android.util.Log
import com.gestoreasy.network.ApiClient
import com.gestoreasy.repository.*
import kotlinx.coroutines.*
import java.util.concurrent.atomic.AtomicBoolean

/**
 * Gerenciador de sincronização offline/online
 * Inspirado em: PedidoOK, Demander, Meus Pedidos, SuasVendas
 */
class SyncManager(
    private val context: Context,
    private val productRepository: ProductRepository,
    private val clientRepository: ClientRepository,
    private val orderRepository: OrderRepository
) {
    private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
    private val isSyncing = AtomicBoolean(false)
    
    /**
     * Sincroniza todos os dados (produtos, clientes, pedidos)
     */
    suspend fun syncAll(force: Boolean = false): SyncResult {
        if (isSyncing.get() && !force) {
            return SyncResult(false, "Sincronização já em andamento")
        }
        
        if (!isOnline() && !force) {
            return SyncResult(false, "Sem conexão com internet")
        }
        
        isSyncing.set(true)
        
        return try {
            // 1. Enviar pedidos pendentes
            val pendingOrders = orderRepository.getPendingSync()
            pendingOrders.forEach { order ->
                try {
                    sendOrder(order)
                    orderRepository.markAsSynced(order.id)
                } catch (e: Exception) {
                    Log.e("SyncManager", "Erro ao enviar pedido ${order.id}: ${e.message}")
                }
            }
            
            // 2. Baixar produtos atualizados
            val productsResult = syncProducts()
            
            // 3. Baixar clientes atualizados
            val clientsResult = syncClients()
            
            // 4. Baixar pedidos do servidor
            val ordersResult = syncOrders()
            
            SyncResult(
                success = true,
                message = "Sincronização concluída",
                productsUpdated = productsResult.count,
                clientsUpdated = clientsResult.count,
                ordersUpdated = ordersResult.count
            )
        } catch (e: Exception) {
            Log.e("SyncManager", "Erro na sincronização: ${e.message}", e)
            SyncResult(false, "Erro: ${e.message}")
        } finally {
            isSyncing.set(false)
        }
    }
    
    /**
     * Sincroniza apenas produtos
     */
    suspend fun syncProducts(): SyncResult {
        return try {
            val lastSync = productRepository.getLastSyncTime()
            val response = ApiClient.api.getProducts(lastSync)
            
            response.data?.forEach { product ->
                productRepository.insertOrUpdate(product)
            }
            
            productRepository.updateLastSyncTime(System.currentTimeMillis())
            
            SyncResult(true, "Produtos sincronizados", count = response.data?.size ?: 0)
        } catch (e: Exception) {
            Log.e("SyncManager", "Erro ao sincronizar produtos: ${e.message}", e)
            SyncResult(false, "Erro: ${e.message}")
        }
    }
    
    /**
     * Sincroniza apenas clientes
     */
    suspend fun syncClients(): SyncResult {
        return try {
            val lastSync = clientRepository.getLastSyncTime()
            val response = ApiClient.api.getClients(lastSync)
            
            response.data?.forEach { client ->
                clientRepository.insertOrUpdate(client)
            }
            
            clientRepository.updateLastSyncTime(System.currentTimeMillis())
            
            SyncResult(true, "Clientes sincronizados", count = response.data?.size ?: 0)
        } catch (e: Exception) {
            Log.e("SyncManager", "Erro ao sincronizar clientes: ${e.message}", e)
            SyncResult(false, "Erro: ${e.message}")
        }
    }
    
    /**
     * Sincroniza apenas pedidos
     */
    suspend fun syncOrders(): SyncResult {
        return try {
            val lastSync = orderRepository.getLastSyncTime()
            val response = ApiClient.api.getOrders(lastSync)
            
            response.data?.forEach { order ->
                orderRepository.insertOrUpdate(order)
            }
            
            orderRepository.updateLastSyncTime(System.currentTimeMillis())
            
            SyncResult(true, "Pedidos sincronizados", count = response.data?.size ?: 0)
        } catch (e: Exception) {
            Log.e("SyncManager", "Erro ao sincronizar pedidos: ${e.message}", e)
            SyncResult(false, "Erro: ${e.message}")
        }
    }
    
    /**
     * Envia um pedido para o servidor
     */
    private suspend fun sendOrder(order: Order) {
        ApiClient.api.createOrder(order)
    }
    
    /**
     * Verifica se há conexão com internet
     */
    private fun isOnline(): Boolean {
        val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        val network = connectivityManager.activeNetwork ?: return false
        val capabilities = connectivityManager.getNetworkCapabilities(network) ?: return false
        
        return capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) &&
               capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
    }
    
    /**
     * Inicia sincronização automática periódica
     */
    fun startAutoSync(intervalMinutes: Int = 15) {
        scope.launch {
            while (isActive) {
                delay(intervalMinutes * 60 * 1000L)
                if (isOnline()) {
                    syncAll()
                }
            }
        }
    }
    
    /**
     * Para sincronização automática
     */
    fun stopAutoSync() {
        scope.cancel()
    }
}

data class SyncResult(
    val success: Boolean,
    val message: String,
    val productsUpdated: Int = 0,
    val clientsUpdated: Int = 0,
    val ordersUpdated: Int = 0,
    val count: Int = 0
)

