package com.example.coloricam

import android.Manifest
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Bundle
import android.util.Base64
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.compose.setContent
import androidx.activity.result.contract.ActivityResultContracts
import androidx.browser.customtabs.CustomTabsIntent
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.KeyboardArrowLeft
import androidx.compose.material.icons.automirrored.filled.KeyboardArrowRight
import androidx.compose.material.icons.filled.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.core.content.ContextCompat
import androidx.exifinterface.media.ExifInterface
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import com.example.coloricam.ui.theme.ColoricamTheme
import com.google.android.gms.auth.api.signin.GoogleSignIn
import com.google.android.gms.auth.api.signin.GoogleSignInOptions
import com.google.android.gms.common.api.ApiException
import kotlinx.coroutines.launch
import okhttp3.OkHttpClient
import okhttp3.ResponseBody
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import java.text.SimpleDateFormat
import java.util.*
import java.util.concurrent.TimeUnit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.*
import java.io.ByteArrayOutputStream
import org.json.JSONObject
import org.json.JSONArray

// --- API MODELS ---
data class N8nMealRequest(
    val imageBase64: String?,
    val mealName: String?,
    val prompt: String
)

interface N8nApi {
    @POST("webhook/v1/gemini-proxy")
    suspend fun analyzeMeal(
        @Header("X-API-KEY") apiKey: String,
        @Body request: N8nMealRequest
    ): ResponseBody
}

// --- STRAVA API ---
data class StravaActivity(
    val id: Long,
    val name: String,
    val type: String,
    val distance: Float,
    val moving_time: Int,
    val elapsed_time: Int,
    val calories: Float?,
    val start_date: String,
    val start_date_local: String
)

data class StravaTokenResponse(
    val access_token: String,
    val refresh_token: String,
    val expires_at: Long
)

interface StravaApi {
    @GET("athlete/activities")
    suspend fun getActivities(
        @Header("Authorization") token: String,
        @Query("before") before: Long? = null,
        @Query("after") after: Long? = null,
        @Query("page") page: Int? = null,
        @Query("per_page") perPage: Int? = 30
    ): List<StravaActivity>

    @POST("oauth/token")
    suspend fun exchangeToken(
        @Query("client_id") clientId: String,
        @Query("client_secret") clientSecret: String,
        @Query("code") code: String,
        @Query("grant_type") grantType: String = "authorization_code"
    ): StravaTokenResponse

    @POST("oauth/token")
    suspend fun refreshToken(
        @Query("client_id") clientId: String,
        @Query("client_secret") clientSecret: String,
        @Query("refresh_token") refreshToken: String,
        @Query("grant_type") grantType: String = "refresh_token"
    ): StravaTokenResponse
}

// Helpers
object ApiClient {
    private val loggingInterceptor = HttpLoggingInterceptor().apply {
        level = HttpLoggingInterceptor.Level.BODY
    }

    private val okHttpClient = OkHttpClient.Builder()
        .addInterceptor(loggingInterceptor)
        .connectTimeout(60, TimeUnit.SECONDS)
        .readTimeout(60, TimeUnit.SECONDS)
        .writeTimeout(60, TimeUnit.SECONDS)
        .build()

    private val retrofitStrava = Retrofit.Builder()
        .baseUrl("https://www.strava.com/api/v3/")
        .addConverterFactory(GsonConverterFactory.create())
        .build()

    private val retrofitN8n = Retrofit.Builder()
        .baseUrl("https://n8n.marquis1987.com/")
        .client(okHttpClient)
        .addConverterFactory(GsonConverterFactory.create())
        .build()

    val stravaApi: StravaApi = retrofitStrava.create(StravaApi::class.java)
    val n8nApi: N8nApi = retrofitN8n.create(N8nApi::class.java)

    suspend fun getValidStravaToken(prefs: SharedPreferences): String? {
        val stravaToken = prefs.getString("strava_token", null) ?: return null
        val expiresAt = prefs.getLong("strava_expires_at", 0)
        val refreshToken = prefs.getString("strava_refresh_token", null)
        val clientId = prefs.getString("strava_client_id", "") ?: ""
        val clientSecret = prefs.getString("strava_client_secret", "") ?: ""

        val currentTime = System.currentTimeMillis() / 1000
        if (currentTime >= expiresAt && refreshToken != null && clientId.isNotBlank()) {
            try {
                val refreshResponse = stravaApi.refreshToken(clientId, clientSecret, refreshToken)
                prefs.edit()
                    .putString("strava_token", refreshResponse.access_token)
                    .putString("strava_refresh_token", refreshResponse.refresh_token)
                    .putLong("strava_expires_at", refreshResponse.expires_at)
                    .apply()
                return refreshResponse.access_token
            } catch (e: Exception) {
                return null
            }
        }
        return stravaToken
    }

    fun parseStravaDate(dateStr: String): Long {
        return try {
            val inputFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US)
            inputFormat.timeZone = TimeZone.getTimeZone("UTC")
            inputFormat.parse(dateStr)?.time ?: 0L
        } catch (e: Exception) { 0L }
    }

    fun estimateCaloriesFromDb(activity: SportActivity, weightKg: Double): Int {
        if (activity.calories != null && activity.calories > 0) return activity.calories.toInt()
        val met = when (activity.type.lowercase()) {
            "run" -> 10.0
            "ride" -> 8.0
            "walk" -> 3.5
            "hike" -> 6.0
            "swim" -> 7.0
            "weighttraining" -> 5.0
            "workout" -> 4.5
            else -> 5.0
        }
        val durationHours = activity.movingTime / 3600.0
        return (met * weightKg * durationHours).toInt()
    }
}

// --- UI COMPONENTS ---

class MainActivity : ComponentActivity() {
    private lateinit var dao: AppDao
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        dao = AppDatabase.getDatabase(this).appDao()
        handleStravaCallback(intent)
        setContent {
            ColoricamTheme {
                AuthWrapper(dao)
            }
        }
    }

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        handleStravaCallback(intent)
    }

    private fun handleStravaCallback(intent: Intent) {
        val data: Uri? = intent.data
        if (data != null && data.toString().startsWith("coloricam://localhost")) {
            val code = data.getQueryParameter("code")
            if (code != null) {
                val prefs = getSharedPreferences("user_prefs", Context.MODE_PRIVATE)
                prefs.edit().putString("strava_code", code).apply()
            }
        }
    }
}

@Composable
fun AuthWrapper(dao: AppDao) {
    val context = LocalContext.current
    val gso = remember {
        GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestEmail()
            .build()
    }
    val googleSignInClient = remember { GoogleSignIn.getClient(context, gso) }
    var account by remember { mutableStateOf(GoogleSignIn.getLastSignedInAccount(context)) }
    
    // Whitelist
    val allowedEmails = listOf("marcandre.charest@gmail.com")

    val launcher = rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
        val task = GoogleSignIn.getSignedInAccountFromIntent(result.data)
        try {
            account = task.getResult(ApiException::class.java)
        } catch (e: ApiException) {
            Log.e("Auth", "signInResult:failed code=" + e.statusCode)
        }
    }

    val onLogout: () -> Unit = {
        googleSignInClient.signOut().addOnCompleteListener {
            account = null
        }
    }

    if (account == null) {
        LoginScreen { launcher.launch(googleSignInClient.signInIntent) }
    } else {
        if (allowedEmails.contains(account?.email)) {
            MainApp(dao, onLogout)
        } else {
            AccessDeniedScreen(onLogout)
        }
    }
}

@Composable
fun LoginScreen(onLoginClick: () -> Unit) {
    Column(
        modifier = Modifier.fillMaxSize().padding(16.dp),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {
        Text("Coloricam", style = MaterialTheme.typography.displayLarge, color = MaterialTheme.colorScheme.primary)
        Spacer(Modifier.height(32.dp))
        Button(onClick = onLoginClick, modifier = Modifier.fillMaxWidth().height(56.dp)) {
            Icon(Icons.Default.AccountCircle, null)
            Spacer(Modifier.width(8.dp))
            Text("Se connecter avec Google")
        }
    }
}

@Composable
fun AccessDeniedScreen(onLogout: () -> Unit) {
    Column(
        modifier = Modifier.fillMaxSize().padding(32.dp),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {
        Icon(Icons.Default.Warning, null, modifier = Modifier.size(80.dp), tint = MaterialTheme.colorScheme.error)
        Spacer(Modifier.height(16.dp))
        Text("Accès Refusé", style = MaterialTheme.typography.headlineMedium, color = MaterialTheme.colorScheme.error)
        Spacer(Modifier.height(8.dp))
        Text("Votre compte n'est pas autorisé à utiliser cette application.", style = MaterialTheme.typography.bodyLarge)
        Spacer(Modifier.height(32.dp))
        Button(onClick = onLogout) { Text("Changer de compte") }
    }
}

@Composable
fun MainApp(dao: AppDao, onLogout: () -> Unit) {
    val context = LocalContext.current
    val prefs = remember { context.getSharedPreferences("user_prefs", Context.MODE_PRIVATE) }
    var showSetup by remember { mutableStateOf(!prefs.contains("target_calories")) }
    var isDiabetic by remember { mutableStateOf(prefs.getBoolean("is_diabetic", false)) }

    if (showSetup) {
        SetupScreen(prefs) { 
            showSetup = false 
            isDiabetic = prefs.getBoolean("is_diabetic", false)
        }
    } else {
        val navController = rememberNavController()
        Scaffold(
            bottomBar = {
                NavigationBar {
                    NavigationBarItem(icon = { Icon(Icons.Default.Home, "Repas") }, label = { Text("Repas") }, selected = false, onClick = { navController.navigate("capture") })
                    NavigationBarItem(icon = { Icon(Icons.Default.Add, "Sport") }, label = { Text("Sport") }, selected = false, onClick = { navController.navigate("sport") })
                    NavigationBarItem(icon = { Icon(Icons.Default.Settings, "Paramètres") }, label = { Text("Paramètres") }, selected = false, onClick = { navController.navigate("settings") })
                }
            }
        ) { innerPadding ->
            NavHost(navController, "capture", Modifier.padding(innerPadding)) {
                composable("capture") { CaptureScreen(dao, prefs, isDiabetic) }
                composable("sport") { SportScreen(dao, prefs) }
                composable("settings") { SettingsScreen(prefs, onLogout) }
            }
        }
    }
}

@Composable
fun SetupScreen(prefs: SharedPreferences, onComplete: () -> Unit) {
    var targetCalories by remember { mutableStateOf("2000") }
    var targetCarbs by remember { mutableStateOf("250") }
    var weightKg by remember { mutableStateOf("70") }
    var isDiabetic by remember { mutableStateOf(false) }

    Column(
        modifier = Modifier.fillMaxSize().padding(24.dp).verticalScroll(rememberScrollState()),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {
        Text("Configuration initiale", style = MaterialTheme.typography.headlineLarge)
        Spacer(Modifier.height(24.dp))
        OutlinedTextField(value = targetCalories, onValueChange = { targetCalories = it }, label = { Text("Objectif Calories / jour") }, keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), modifier = Modifier.fillMaxWidth())
        Spacer(Modifier.height(16.dp))
        OutlinedTextField(value = targetCarbs, onValueChange = { targetCarbs = it }, label = { Text("Objectif Glucides / jour (g)") }, keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), modifier = Modifier.fillMaxWidth())
        Spacer(Modifier.height(16.dp))
        OutlinedTextField(value = weightKg, onValueChange = { weightKg = it }, label = { Text("Poids (kg)") }, keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), modifier = Modifier.fillMaxWidth())
        Spacer(Modifier.height(24.dp))
        Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.fillMaxWidth()) {
            Checkbox(checked = isDiabetic, onCheckedChange = { isDiabetic = it })
            Text("Je suis diabétique (ajoute l'estimation d'insuline)")
        }
        Spacer(Modifier.height(32.dp))
        Button(onClick = {
            prefs.edit()
                .putString("target_calories", targetCalories)
                .putString("target_carbs", targetCarbs)
                .putString("weight_kg", weightKg)
                .putBoolean("is_diabetic", isDiabetic)
                .apply()
            onComplete()
        }, modifier = Modifier.fillMaxWidth().height(56.dp)) {
            Text("Commencer")
        }
    }
}
