package id.ac.ubharajaya.sistemakademik

import android.Manifest
import android.app.Activity
import android.content.Intent
import android.graphics.Bitmap
import android.os.Build
import android.os.Bundle
import android.provider.MediaStore
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Brush
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.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.google.android.gms.location.LocationServices
import id.ac.ubharajaya.sistemakademik.ui.theme.SistemAkademikTheme
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.text.SimpleDateFormat
import java.util.*
import kotlin.concurrent.thread

/* ================== KONFIG LOCKOUT ================== */
const val LOCKOUT_DURATION = 10 * 60 * 1000L // 1 menit

/* ================== REPOSITORY ================== */
class AbsensiRepository {
    fun kirimAbsensi(absensi: Absensi, onResult: (Boolean) -> Unit) {
        thread {
            try {
                val url = java.net.URL(
                    "https://n8n.lab.ubharajaya.ac.id/webhook/23c6993d-1792-48fb-ad1c-ffc78a3e6254"
                )
                val conn = url.openConnection() as java.net.HttpURLConnection
                conn.requestMethod = "POST"
                conn.setRequestProperty("Content-Type", "application/json")
                conn.doOutput = true

                conn.outputStream.use {
                    it.write(absensi.toJson().toString().toByteArray())
                }

                onResult(conn.responseCode == 200)
                conn.disconnect()
            } catch (e: Exception) {
                onResult(false)
            }
        }
    }
}

/* ================== VIEWMODEL ================== */
class AbsensiViewModel(
    private val repo: AbsensiRepository,
    private val activity: ComponentActivity
) : ViewModel() {

    var lokasi by mutableStateOf("Koordinat: -")
        private set

    var latitude by mutableStateOf<Double?>(null)
        private set

    var longitude by mutableStateOf<Double?>(null)
        private set

    var foto by mutableStateOf<Bitmap?>(null)
        private set

    var absensiList = mutableStateListOf<Absensi>()

    var waktuAbsensi by mutableStateOf<String?>(null)
        private set

    var isLoading by mutableStateOf(false)
        private set

    var sisaLockout by mutableStateOf(0L)
        private set

    init {
        startLockoutCountdown()
    }

    fun updateLokasi(lat: Double, lon: Double) {
        latitude = lat
        longitude = lon
        lokasi = "Lat: $lat\nLon: $lon"
    }

    fun updateFoto(bitmap: Bitmap) {
        foto = bitmap
    }

    private fun getLastAbsensiTime(): Long {
        val prefs = activity.getSharedPreferences("absensi_prefs", Activity.MODE_PRIVATE)
        return prefs.getLong("last_absensi_time", 0L)
    }

    private fun simpanWaktuAbsensi() {
        val prefs = activity.getSharedPreferences("absensi_prefs", Activity.MODE_PRIVATE)
        prefs.edit().putLong("last_absensi_time", System.currentTimeMillis()).apply()
    }

    private fun startLockoutCountdown() {
        viewModelScope.launch {
            while (true) {
                val diff = System.currentTimeMillis() - getLastAbsensiTime()
                sisaLockout =
                    if (diff < LOCKOUT_DURATION) LOCKOUT_DURATION - diff else 0L
                delay(1000)
            }
        }
    }

    fun kirimAbsensi() {
        if (sisaLockout > 0) {
            Toast.makeText(
                activity,
                "Sudah absen, tunggu ${(sisaLockout / 1000) / 60} menit",
                Toast.LENGTH_LONG
            ).show()
            return
        }

        if (latitude == null || longitude == null || foto == null) {
            Toast.makeText(activity, "Lokasi atau foto belum lengkap", Toast.LENGTH_SHORT).show()
            return
        }

        val waktu = SimpleDateFormat(
            "dd MMM yyyy HH:mm:ss",
            Locale.getDefault()
        ).format(System.currentTimeMillis())

        val absensi = Absensi(
            npm = "202310715307",
            nama = "Satrio Putra Wardani",
            latitude = latitude!!,
            longitude = longitude!!,
            waktu = waktu,
            foto = foto
        )

        isLoading = true
        repo.kirimAbsensi(absensi) { success ->
            viewModelScope.launch {
                isLoading = false
                if (success) {
                    absensiList.add(absensi)
                    waktuAbsensi = waktu
                    simpanWaktuAbsensi()
                    Toast.makeText(activity, "Absensi berhasil", Toast.LENGTH_SHORT).show()
                } else {
                    Toast.makeText(activity, "Gagal kirim absensi", Toast.LENGTH_SHORT).show()
                }
            }
        }
    }
}

/* ================== MAIN ACTIVITY ================== */
@OptIn(ExperimentalMaterial3Api::class)
class MainActivity : ComponentActivity() {

    private lateinit var viewModel: AbsensiViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()

        viewModel = AbsensiViewModel(AbsensiRepository(), this)

        setContent {
            SistemAkademikTheme {
                Scaffold(
                    topBar = { TopBarLogout(this) }
                ) { padding ->
                    AbsensiScreen(
                        modifier = Modifier.padding(padding),
                        viewModel = viewModel
                    )
                }
            }
        }
    }
}

/* ================== TOP BAR ================== */
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TopBarLogout(activity: ComponentActivity) {
    val context = LocalContext.current
    TopAppBar(
        title = {
            Text(
                " Sistem Akademik ",
                style = MaterialTheme.typography.titleLarge.copy(
                    fontWeight = FontWeight.SemiBold,
                    color = Color.White
                )
            )
        },
        actions = {
            TextButton(onClick = {
                val intent = Intent(context, LoginActivity::class.java)
                intent.flags =
                    Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
                context.startActivity(intent)
            }) {
                Text(
                    "Logout",
                    style = MaterialTheme.typography.labelLarge,
                    color = Color.Red
                )
            }
        }
    )
}

/* ================== UI ================== */
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AbsensiScreen(modifier: Modifier, viewModel: AbsensiViewModel) {

    val context = LocalContext.current

    val locationPermissionLauncher =
        rememberLauncherForActivityResult(ActivityResultContracts.RequestPermission()) { granted ->
            if (granted) {
                LocationServices.getFusedLocationProviderClient(context)
                    .lastLocation.addOnSuccessListener {
                        it?.let { loc ->
                            viewModel.updateLokasi(loc.latitude, loc.longitude)
                        }
                    }
            }
        }

    val cameraLauncher =
        rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) {
            if (it.resultCode == Activity.RESULT_OK) {
                val bitmap =
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
                        it.data?.extras?.getParcelable("data", Bitmap::class.java)
                    else it.data?.extras?.getParcelable("data")
                bitmap?.let { bmp -> viewModel.updateFoto(bmp) }
            }
        }

    val cameraPermissionLauncher =
        rememberLauncherForActivityResult(ActivityResultContracts.RequestPermission()) {
            if (it) cameraLauncher.launch(Intent(MediaStore.ACTION_IMAGE_CAPTURE))
        }

    LaunchedEffect(Unit) {
        locationPermissionLauncher.launch(Manifest.permission.ACCESS_FINE_LOCATION)
    }

    Column(
        modifier = modifier
            .fillMaxSize()
            .background(Color.White)
            .padding(24.dp)
    ) {

        Text(
            text = "Absensi Akademik",
            modifier = Modifier.fillMaxWidth(),
            textAlign = TextAlign.Center,
            style = MaterialTheme.typography.headlineSmall.copy(
                fontWeight = FontWeight.Bold,
                color = Color.Black
            )
        )

        Spacer(Modifier.height(16.dp))

        Card(
            modifier = Modifier.fillMaxWidth(),
            elevation = CardDefaults.cardElevation(6.dp)
        ) {
            Column(Modifier.padding(16.dp)) {
                Text(
                    "Lokasi:",
                    style = MaterialTheme.typography.bodyLarge.copy(
                        fontWeight = FontWeight.SemiBold,
                        color = Color.White
                    )
                )
                Text(
                    viewModel.lokasi,
                    style = MaterialTheme.typography.bodyMedium.copy(
                        color = Color.White
                    )
                )
            }
        }

        Spacer(Modifier.height(16.dp))

        Button(
            onClick = { cameraPermissionLauncher.launch(Manifest.permission.CAMERA) },
            modifier = Modifier.fillMaxWidth()
        ) {
            Text("Ambil Foto")
        }

        Spacer(Modifier.height(12.dp))

        Button(
            onClick = { viewModel.kirimAbsensi() },
            modifier = Modifier.fillMaxWidth(),
            enabled = !viewModel.isLoading
        ) {
            if (viewModel.isLoading)
                CircularProgressIndicator(
                    modifier = Modifier.size(22.dp),
                    strokeWidth = 2.dp
                )
            else Text("Kirim Absensi")
        }

        Spacer(Modifier.height(24.dp))

        LazyColumn {
            items(viewModel.absensiList) { item ->
                Card(
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(bottom = 12.dp)
                        .animateContentSize()
                ) {
                    Column(Modifier.padding(16.dp)) {
                        Text(
                            item.nama,
                            style = MaterialTheme.typography.bodyLarge.copy(
                                fontWeight = FontWeight.Bold,
                                color = Color.White
                            )
                        )
                        Text(item.npm, color = Color.White)
                        Text(item.waktu, color = Color.White)
                        item.foto?.let {
                            Image(
                                bitmap = it.asImageBitmap(),
                                contentDescription = null,
                                modifier = Modifier
                                    .fillMaxWidth()
                                    .height(150.dp)
                                    .clip(RoundedCornerShape(12.dp))
                            )
                        }
                    }
                }
            }
        }
    }
}
