package com.za.ui.map_search

import android.Manifest
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.util.Log
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Button
import androidx.compose.material3.Card
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Snackbar
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import androidx.core.content.ContextCompat
import com.amap.api.location.AMapLocationClient
import com.amap.api.location.AMapLocationClientOption
import com.amap.api.maps.CameraUpdateFactory
import com.amap.api.maps.MapView
import com.amap.api.maps.model.LatLng
import com.amap.api.services.core.AMapException
import com.amap.api.services.core.LatLonPoint
import com.amap.api.services.core.PoiItem
import com.amap.api.services.geocoder.GeocodeResult
import com.amap.api.services.geocoder.GeocodeSearch
import com.amap.api.services.geocoder.RegeocodeResult
import com.amap.api.services.poisearch.PoiResult
import com.amap.api.services.poisearch.PoiSearch
import com.za.base.BaseActivity
import com.za.base.view.CommonButton
import com.za.base.view.HeadView
import com.za.ext.finish
import kotlinx.coroutines.launch
import java.io.Serializable
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine

class MapSearchActivity : BaseActivity() {
    @SuppressLint("MissingPermission")
    @Composable
    override fun ContentView() {
        MapSearchScreen(onLocationSelected = ::onLocationSelected)
    }

    private fun onLocationSelected(poiData: PoiData) {
        val intent = Intent()
        intent.putExtra("poiData", poiData)
        setResult(RESULT_OK, intent)
        finish()
    }
}

@SuppressLint("MissingPermission")
@Composable
fun MapSearchScreen(onLocationSelected: (PoiData) -> Unit) {
    val context = LocalContext.current
    val scope = rememberCoroutineScope()
    var searchText by remember { mutableStateOf("") }
    var selectLatLng by remember { mutableStateOf(LatLonPoint(0.0, 0.0)) }
    var mapInitialized by remember { mutableStateOf(false) }
    val mapView = remember { MapView(context) } // Remember the MapView instance
    var locationClient: AMapLocationClient? by remember { mutableStateOf(null) }
    var isLoading by remember { mutableStateOf(false) }
    var errorMessage by remember { mutableStateOf<String?>(null) }
    var searchResults by remember { mutableStateOf<List<PoiItem>>(emptyList()) }

    // Permission handling
    val locationPermissionGranted = remember { mutableStateOf(false) }
    val locationPermissionLauncher = rememberLauncherForActivityResult(
        ActivityResultContracts.RequestPermission()
    ) { isGranted: Boolean ->
        locationPermissionGranted.value = isGranted
    }

    // Check if location permission is granted
    val checkPermission = {
        if (ContextCompat.checkSelfPermission(
                context,
                Manifest.permission.ACCESS_FINE_LOCATION
            ) == PackageManager.PERMISSION_GRANTED
        ) {
            locationPermissionGranted.value = true
        } else {
            locationPermissionLauncher.launch(Manifest.permission.ACCESS_FINE_LOCATION)
        }
    }

    errorMessage?.let { message ->
        Snackbar(
            action = {
                Button(onClick = { errorMessage = null }) {
                    Text("关闭")
                }
            },
            modifier = Modifier.padding(8.dp)
        ) {
            Text(message)
        }
    }

    LaunchedEffect(key1 = Unit) {
        checkPermission()
    }

    LaunchedEffect(key1 = locationPermissionGranted.value) {
        if (locationPermissionGranted.value) {
            locationClient = AMapLocationClient(context).apply {
                setLocationOption(AMapLocationClientOption().apply {
                    isOnceLocation = true // Only need the location once
                    isNeedAddress = true
                })
                setLocationListener { location ->
                    if (location != null) {
                        val latLng = LatLng(location.latitude, location.longitude)
                        selectLatLng = LatLonPoint(location.latitude, location.longitude)
                        scope.launch {
                            val address = reverseGeocode(context, selectLatLng)
                            searchText = address
                        }
                        mapView.map.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 15f))
                    } else {
                        Log.e("MapSearchScreen", "Location failed")
                        errorMessage = "位置获取失败"
                    }
                    locationClient?.apply {
                        stopLocation() // 停止位置更新
                        onDestroy() // 销毁位置客户端
                    }
                    locationClient = null
                }
                startLocation()
            }
        } else {
            Log.e("MapSearchScreen", "Location permission not granted")
            errorMessage = "位置权限未授予"
        }
    }

    DisposableEffect(key1 = mapView) {
        onDispose {
            locationClient?.onDestroy()
            mapView.onDestroy()
        }
    }

    Scaffold(
        topBar = {
            HeadView(title = "地图选点", onBack = { context.finish() })
        }
    ) { paddingValues ->
        Column(
            modifier = Modifier
                .fillMaxSize()
                .padding(paddingValues)
                .padding(16.dp)
                .verticalScroll(state = rememberScrollState())
        ) {
            Card(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(bottom = 16.dp)
            ) {
                Column(
                    modifier = Modifier.padding(16.dp)
                ) {
                    TextField(
                        value = searchText,
                        onValueChange = { searchText = it },
                        label = { Text("搜索地址") },
                        keyboardOptions = KeyboardOptions(imeAction = ImeAction.Search),
                        modifier = Modifier.fillMaxWidth()
                    )
                    Spacer(modifier = Modifier.height(8.dp))
                    Button(
                        onClick = {
                            if (searchText.isNotBlank()) {
                                isLoading = true
                                errorMessage = null
                                searchResults = emptyList() // Clear previous results
                                scope.launch {
                                    val results = searchPoi(context, searchText)
                                    searchResults = results
                                    isLoading = false
                                }
                            } else {
                                errorMessage = "请输入地址"
                            }
                        },
                        modifier = Modifier.fillMaxWidth()
                    ) {
                        Text("搜索")
                    }
                }
            }
            if (isLoading) {
                CircularProgressIndicator(
                    modifier = Modifier.align(Alignment.CenterHorizontally)
                )
            }
            if (searchResults.isNotEmpty()) {
                LazyColumn(
                    modifier = Modifier
                        .fillMaxWidth()
                        .height(180.dp)
                        .padding(bottom = 16.dp)
                ) {
                    items(items = searchResults) {
                        Box(modifier = Modifier
                            .fillMaxWidth()
                            .clickable {
                                selectLatLng = it.latLonPoint
                                searchText = it.title
                            }
                            .padding(5.dp)) {
                            Text(it.title, color = Color.Black)
                        }
                    }
                }
            }
            // Wrap MapView with AndroidView
            AndroidView(
                factory = {
                    mapView.apply {
                        onCreate(null)
                        onResume()
                    }
                },
                update = {
                    it.map.setOnMapClickListener { latLng ->
                        selectLatLng = LatLonPoint(latLng.latitude, latLng.longitude)
                        scope.launch {
                            val address = reverseGeocode(context, selectLatLng)
                            searchText = address
                        }
                    }
                    if (!mapInitialized) {
                        mapInitialized = true
                    }
                },
                modifier = Modifier
                    .fillMaxWidth()
                    .height(300.dp)
            )

            Spacer(modifier = Modifier.height(20.dp))

            CommonButton(text = "确定") {
                onLocationSelected(PoiData(name = searchText, lat = selectLatLng.latitude, lng = selectLatLng.longitude))
            }
        }
    }
}

private suspend fun searchPoi(context: Context, query: String): List<PoiItem> {
    return suspendCoroutine { continuation ->
        val poiSearchQuery = PoiSearch.Query(query, "", "") // 第二个参数是城市代码，留空表示全国搜索
        poiSearchQuery.pageNum = 0
        poiSearchQuery.pageSize = 10
        val poiSearch = PoiSearch(context, poiSearchQuery)

        poiSearch.setOnPoiSearchListener(object : PoiSearch.OnPoiSearchListener {
            override fun onPoiSearched(result: PoiResult?, rCode: Int) {
                if (rCode == AMapException.CODE_AMAP_SUCCESS) {
                    val pois = result?.pois ?: emptyList()
                    continuation.resume(pois)
                } else {
                    Log.e("MapSearchScreen", "POI 搜索失败：$rCode")
                    continuation.resume(emptyList())
                }
            }

            override fun onPoiItemSearched(poiItem: PoiItem?, rCode: Int) {
                // Not used in this case
            }
        })

        poiSearch.searchPOIAsyn()
    }
}

private suspend fun reverseGeocode(context: Context, latLng: LatLonPoint): String {
    return suspendCoroutine { continuation ->
        val geocodeSearch = GeocodeSearch(context)
        geocodeSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener {
            override fun onRegeocodeSearched(result: RegeocodeResult?, rCode: Int) {
                if (rCode == AMapException.CODE_AMAP_SUCCESS) {
                    val address = result?.regeocodeAddress?.formatAddress
                    continuation.resume(address ?: "")
                } else {
                    Log.e("MapSearchScreen", "Reverse Geocode failed: $rCode")
                    continuation.resume("")
                }
            }

            override fun onGeocodeSearched(result: GeocodeResult?, rCode: Int) {
                // Not used in reverse geocoding
            }
        })

        // Perform Reverse Geocoding (LatLng -> address)
        val query = com.amap.api.services.geocoder.RegeocodeQuery(latLng, 200f, GeocodeSearch.AMAP)
        geocodeSearch.getFromLocationAsyn(query) // Use the async version
    }
}

data class PoiData(val name: String? = null, val lat: Double? = null, val lng: Double? = null) : Serializable

@Preview
@Composable
fun PreviewMapSearchScreen() {
    MapSearchScreen(onLocationSelected = {})
}