package com.fieldlabel.collector.ui.components

import android.content.Context
import android.view.MotionEvent
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.MyLocation
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.RectangleShape
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.compose.LocalLifecycleOwner
import org.osmdroid.config.Configuration
import org.osmdroid.util.GeoPoint
import org.osmdroid.views.MapView
import org.osmdroid.views.overlay.Marker
import com.fieldlabel.collector.ui.map.TILE_STANDARD

/**
 * OSMDroid (OpenStreetMap) を使った地図ピッカー。
 *
 * - 設定済み座標にマーカーを表示する
 * - 画面中央の十字カーソルに地図をドラッグして新しい位置を指定する
 * - 「この地点に修正」→ 現在の地図中心座標を [onPositionChanged] で通知
 * - 「設定されている地点に戻る」→ 地図を元の座標に再センタリング
 */
@Composable
fun MapPickerView(
    latitude:          Double,
    longitude:         Double,
    modifier:          Modifier = Modifier,
    onPositionChanged: (lat: Double, lon: Double) -> Unit,
    onConfirmed:       () -> Unit = {}   // 「この地点に修正」確定後に呼ばれる（地図を閉じる用途）
) {
    val context        = LocalContext.current
    val lifecycleOwner = LocalLifecycleOwner.current

    // OSMDroid 設定を初期化（冪等）
    remember(Unit) {
        Configuration.getInstance().load(
            context,
            context.getSharedPreferences("osmdroid", Context.MODE_PRIVATE)
        )
    }

    val mapView   = remember { MapView(context) }
    val markerRef = remember { mutableStateOf<Marker?>(null) }

    // 親から lat/lon が変わったときにマーカーのみ移動（地図センターは変えない）
    LaunchedEffect(latitude, longitude) {
        markerRef.value?.let { m ->
            m.position = GeoPoint(latitude, longitude)
            mapView.invalidate()
        }
    }

    // Activity ライフサイクルと同期
    DisposableEffect(lifecycleOwner) {
        val observer = LifecycleEventObserver { _, event ->
            when (event) {
                Lifecycle.Event.ON_RESUME -> mapView.onResume()
                Lifecycle.Event.ON_PAUSE  -> mapView.onPause()
                else                      -> Unit
            }
        }
        lifecycleOwner.lifecycle.addObserver(observer)
        onDispose {
            lifecycleOwner.lifecycle.removeObserver(observer)
            mapView.onDetach()
        }
    }

    // clip(RectangleShape) でピンチズーム時に MapView が枠外に広がるのを防ぐ
    Box(modifier = modifier.clip(RectangleShape)) {

        // ── 地図本体 ────────────────────────────────────────────────────
        AndroidView(
            factory = { _ ->
                mapView.apply {
                    setTileSource(TILE_STANDARD)
                    setMultiTouchControls(true)

                    val startPoint = GeoPoint(latitude, longitude)
                    controller.setZoom(17.0)
                    controller.setCenter(startPoint)

                    // 設定済み地点を示すマーカー（ドラッグ不可）
                    val marker = Marker(this).apply {
                        position    = startPoint
                        title       = "設定済み地点"
                        snippet     = "中央の十字に合わせて「この地点に修正」を押してください"
                        setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM)
                        isDraggable = false
                    }
                    overlays.clear()
                    overlays.add(marker)
                    markerRef.value = marker

                    // ── 親スクロールへのタッチ横取りを防ぐ ──────────────────
                    // ACTION_DOWN / MOVE 時に親 View に「タッチイベントを渡さないで」と通知する。
                    // これにより 1 本指ドラッグが verticalScroll に奪われなくなる。
                    // false を返してイベント自体は MapView に処理させる。
                    setOnTouchListener { v, event ->
                        when (event.actionMasked) {
                            MotionEvent.ACTION_DOWN,
                            MotionEvent.ACTION_MOVE ->
                                v.parent?.requestDisallowInterceptTouchEvent(true)
                            MotionEvent.ACTION_UP,
                            MotionEvent.ACTION_CANCEL ->
                                v.parent?.requestDisallowInterceptTouchEvent(false)
                        }
                        false   // MapView 自身にもイベントを渡す
                    }
                }
            },
            modifier = Modifier.fillMaxSize()
        )

        // ── 中央の十字カーソル ──────────────────────────────────────────
        Box(
            modifier = Modifier
                .align(Alignment.Center)
                .size(40.dp),
            contentAlignment = Alignment.Center
        ) {
            // 薄い円形背景
            Box(
                modifier = Modifier
                    .size(40.dp)
                    .background(
                        MaterialTheme.colorScheme.error.copy(alpha = 0.12f),
                        CircleShape
                    )
            )
            // 縦線
            Box(
                modifier = Modifier
                    .width(2.5.dp)
                    .height(32.dp)
                    .background(MaterialTheme.colorScheme.error)
            )
            // 横線
            Box(
                modifier = Modifier
                    .width(32.dp)
                    .height(2.5.dp)
                    .background(MaterialTheme.colorScheme.error)
            )
        }

        // ── 帰属表示 ───────────────────────────────────────────────────
        Text(
            text  = "© OpenStreetMap contributors © CARTO",
            style = MaterialTheme.typography.labelSmall.copy(fontSize = androidx.compose.ui.unit.TextUnit(9f, androidx.compose.ui.unit.TextUnitType.Sp)),
            color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f),
            modifier = Modifier
                .align(Alignment.BottomStart)
                .padding(start = 4.dp, bottom = 78.dp)  // ボタンバーの上に表示
        )

        // ── 操作ボタン（下部半透明バー） ────────────────────────────────
        Column(
            modifier = Modifier
                .align(Alignment.BottomCenter)
                .fillMaxWidth()
                .background(MaterialTheme.colorScheme.surface.copy(alpha = 0.90f))
                .padding(horizontal = 10.dp, vertical = 8.dp),
            verticalArrangement = Arrangement.spacedBy(6.dp)
        ) {
            // 確定: 現在の地図中心を新しい座標として採用し、地図を閉じる
            Button(
                onClick  = {
                    val center = mapView.mapCenter
                    // マーカーを新しい地点へ移動して視覚フィードバック
                    markerRef.value?.let { m ->
                        m.position = GeoPoint(center.latitude, center.longitude)
                        mapView.invalidate()
                    }
                    onPositionChanged(center.latitude, center.longitude)
                    onConfirmed()   // 地図パネルを閉じる
                },
                modifier = Modifier.fillMaxWidth()
            ) {
                Icon(Icons.Default.Check, null, modifier = Modifier.size(18.dp))
                Spacer(Modifier.width(6.dp))
                Text("この地点に修正")
            }

            // リセット: 元の座標へ戻る
            OutlinedButton(
                onClick  = {
                    val gp = GeoPoint(latitude, longitude)
                    markerRef.value?.position = gp
                    mapView.controller.animateTo(gp)
                    mapView.invalidate()
                    onPositionChanged(latitude, longitude)
                },
                modifier = Modifier.fillMaxWidth()
            ) {
                Icon(Icons.Default.MyLocation, null, modifier = Modifier.size(18.dp))
                Spacer(Modifier.width(6.dp))
                Text("設定されている地点に戻る")
            }
        }
    }
}
