/*
 * Copyright (C) 2026 SHX VPN
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or (at your
 * option) any later version.
 */

package org.strongswan.android.ui

import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Bundle
import androidx.activity.OnBackPressedCallback
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.Checkbox
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ListItem
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.core.graphics.drawable.toBitmap
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.strongswan.android.R
import org.strongswan.android.data.VpnProfileDataSource
import org.strongswan.android.ui.adapter.SelectedApplicationEntry
import org.strongswan.android.ui.compose.SecondaryScaffold
import org.strongswan.android.ui.compose.theme.ShxTheme
import java.util.TreeSet

class SelectedApplicationsActivity : AppCompatActivity()
{
	private val selection = TreeSet<String>()
	private var readOnly = false

	override fun onCreate(savedInstanceState: Bundle?)
	{
		super.onCreate(savedInstanceState)
		enableEdgeToEdge()
		readOnly = intent.getBooleanExtra(VpnProfileDataSource.KEY_READ_ONLY, false)
		val initial = savedInstanceState?.getStringArrayList(VpnProfileDataSource.KEY_SELECTED_APPS_LIST)
			?: intent.getStringArrayListExtra(VpnProfileDataSource.KEY_SELECTED_APPS_LIST)
			?: arrayListOf()
		selection.addAll(initial)
		onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true)
		{
			override fun handleOnBackPressed()
			{
				prepareResult()
				finish()
			}
		})
		setContent {
			ShxTheme {
				SelectedAppsScreen(
					initial = selection,
					readOnly = readOnly,
					onBack = {
						prepareResult()
						finish()
					},
					onChange = {
						selection.clear()
						selection.addAll(it)
					},
				)
			}
		}
	}

	override fun onSaveInstanceState(outState: Bundle)
	{
		super.onSaveInstanceState(outState)
		outState.putStringArrayList(VpnProfileDataSource.KEY_SELECTED_APPS_LIST, ArrayList(selection))
	}

	private fun prepareResult()
	{
		val data = Intent()
		data.putExtra(VpnProfileDataSource.KEY_SELECTED_APPS_LIST, ArrayList(selection))
		setResult(RESULT_OK, data)
	}
}

@Composable
private fun SelectedAppsScreen(
	initial: Set<String>,
	readOnly: Boolean,
	onBack: () -> Unit,
	onChange: (Set<String>) -> Unit,
)
{
	val context = LocalContext.current
	var query by remember { mutableStateOf("") }
	var apps by remember { mutableStateOf<List<SelectedApplicationEntry>>(emptyList()) }
	var selected by remember { mutableStateOf(initial.toSet()) }
	var loading by remember { mutableStateOf(true) }

	LaunchedEffect(Unit) {
		val loaded = withContext(Dispatchers.IO) {
			val pm = context.packageManager
			val list = ArrayList<SelectedApplicationEntry>()
			for (info in pm.getInstalledApplications(PackageManager.GET_META_DATA))
			{
				if (pm.checkPermission(Manifest.permission.INTERNET, info.packageName) == PackageManager.PERMISSION_GRANTED)
				{
					val entry = SelectedApplicationEntry(pm, info)
					entry.isSelected = selected.contains(info.packageName)
					list.add(entry)
				}
			}
			list.sorted()
		}
		apps = loaded
		loading = false
	}

	fun toggle(pkg: String)
	{
		if (readOnly) return
		selected = if (selected.contains(pkg)) selected - pkg else selected + pkg
		onChange(selected)
	}

	val filtered = remember(apps, query) {
		if (query.isBlank()) apps
		else apps.filter { it.toString().contains(query, ignoreCase = true) || it.info.packageName.contains(query, ignoreCase = true) }
	}

	SecondaryScaffold(title = stringResource(R.string.profile_select_apps), onBack = onBack) { padding ->
		Column(Modifier.fillMaxSize().padding(padding)) {
			OutlinedTextField(
				value = query,
				onValueChange = { query = it },
				label = { Text(stringResource(R.string.search)) },
				singleLine = true,
				modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp).fillMaxWidth(),
			)
			if (loading)
			{
				CircularProgressIndicator(Modifier.padding(24.dp).size(32.dp))
			}
			else
			{
				LazyColumn(Modifier.fillMaxSize()) {
					items(filtered, key = { it.info.packageName }) { entry ->
						val pkg = entry.info.packageName
						val checked = selected.contains(pkg)
						ListItem(
							headlineContent = { Text(entry.toString()) },
							supportingContent = { Text(pkg) },
							leadingContent = {
								val bmp = remember(pkg) { entry.icon.toBitmap() }
								Image(bitmap = bmp.asImageBitmap(), contentDescription = null, modifier = Modifier.size(40.dp))
							},
							trailingContent = {
								Checkbox(checked = checked, onCheckedChange = { toggle(pkg) }, enabled = !readOnly)
							},
							modifier = Modifier.clickable(enabled = !readOnly) { toggle(pkg) },
						)
					}
				}
			}
		}
	}
}
