package com.fieldlabel.collector.ui.screens

import android.content.Context
import android.graphics.Paint
import androidx.compose.foundation.layout.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.compose.LocalLifecycleOwner
import com.fieldlabel.collector.domain.model.RoutePoint
import com.fieldlabel.collector.ui.viewmodel.RouteLogViewModel
import org.osmdroid.config.Configuration
import org.osmdroid.util.BoundingBox
import com.fieldlabel.collector.ui.map.TILE_STANDARD
import org.osmdroid.util.GeoPoint
import org.osmdroid.views.MapView
import org.osmdroid.views.overlay.Marker
import org.osmdroid.views.overlay.Polyline
import org.osmdroid.views.overlay.ScaleBarOverlay
import org.osmdroid.views.overlay.compass.CompassOverlay
import org.osmdroid.views.overlay.compass.InternalCompassOrientationProvider

// ════════════════════════════════════════════════════════════════════════════
// RouteMapScreen  — 単一ルートの地図表示
// ════════════════════════════════════════════════════════════════════════════

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun RouteMapScreen(
    routeLogId:     String,
    onNavigateBack: () -> Unit,
    viewModel:      RouteLogViewModel = hiltViewModel()
) {
    val context       = LocalContext.current
    val lifecycleOwner = LocalLifecycleOwner.current
    val routeLogs     by viewModel.routeLogs.collectAsState()
    val points        by viewModel.selectedRoutePoints.collectAsState()

    // ルート名を取得
    val routeLog = remember(routeLogs, routeLogId) {
        routeLogs.find { it.id == routeLogId }
    }

    // 測位点をロード
    LaunchedEffect(routeLogId) {
        viewModel.loadRoutePoints(routeLogId)
    }

    // テーマカラー
    val primaryArgb = MaterialTheme.colorScheme.primary.toArgb()
    val errorArgb   = MaterialTheme.colorScheme.error.toArgb()

    // OSMDroid 初期化
    remember(Unit) {
        Configuration.getInstance().load(
            context,
            context.getSharedPreferences("osmdroid", Context.MODE_PRIVATE)
        )
    }

    val mapView = remember { MapView(context) }

    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()
        }
    }

    DisposableEffect(Unit) {
        onDispose { viewModel.clearSelectedRoute() }
    }

    Scaffold(
        topBar = {
            TopAppBar(
                title = { Text(routeLog?.name ?: "ルートマップ") },
                navigationIcon = {
                    IconButton(onClick = onNavigateBack) {
                        Icon(Icons.Default.ArrowBack, "戻る")
                    }
                }
            )
        }
    ) { padding ->
        Box(
            modifier = Modifier
                .fillMaxSize()
                .padding(padding)
        ) {
            AndroidView(
                factory = { ctx ->
                    mapView.apply {
                        setTileSource(TILE_STANDARD)
                        setMultiTouchControls(true)
                        controller.setZoom(14.0)
                        controller.setCenter(GeoPoint(36.5, 136.0))

                        // コンパス
                        val compass = CompassOverlay(
                            ctx, InternalCompassOrientationProvider(ctx), this
                        )
                        compass.enableCompass()
                        overlays.add(compass)

                        // スケールバー
                        overlays.add(ScaleBarOverlay(this).apply {
                            setCentred(false)
                            setAlignBottom(true)
                        })
                    }
                },
                update = { mv ->
                    // 固定オーバーレイ（コンパス + スケールバー）以外をクリア
                    val fixed = mv.overlays.take(2).toMutableList()
                    mv.overlays.clear()
                    mv.overlays.addAll(fixed)

                    if (points.isNotEmpty()) {
                        val geoPoints = points.map { GeoPoint(it.latitude, it.longitude) }

                        // ── ポリライン ──────────────────────────────────────
                        val polyline = Polyline(mv).apply {
                            setPoints(ArrayList(geoPoints))
                            outlinePaint.color       = primaryArgb
                            outlinePaint.strokeWidth = 8f
                            outlinePaint.style       = Paint.Style.STROKE
                            outlinePaint.strokeCap   = Paint.Cap.ROUND
                            outlinePaint.strokeJoin  = Paint.Join.ROUND
                        }
                        mv.overlays.add(polyline)

                        // ── 開始点マーカー（緑） ────────────────────────────
                        Marker(mv).apply {
                            position = geoPoints.first()
                            title    = "開始地点"
                            setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM)
                            mv.overlays.add(this)
                        }

                        // ── 終了点マーカー（赤） ────────────────────────────
                        if (geoPoints.size > 1) {
                            Marker(mv).apply {
                                position = geoPoints.last()
                                title    = "終了地点"
                                setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM)
                                mv.overlays.add(this)
                            }
                        }

                        // ── ズーム調整 ──────────────────────────────────────
                        mv.post {
                            if (geoPoints.size == 1) {
                                mv.controller.setZoom(16.0)
                                mv.controller.setCenter(geoPoints.first())
                            } else {
                                val bbox = BoundingBox.fromGeoPoints(ArrayList(geoPoints))
                                mv.zoomToBoundingBox(bbox.increaseByScale(1.3f), false)
                            }
                        }
                    }
                    mv.invalidate()
                },
                modifier = Modifier.fillMaxSize()
            )

            // ── 帰属表示 ───────────────────────────────────────────────────
            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 = 4.dp)
            )

            // ── ポイントなし表示 ─────────────────────────────────────────
            if (points.isEmpty()) {
                Card(
                    modifier = Modifier
                        .align(Alignment.Center)
                        .padding(24.dp)
                ) {
                    Column(
                        modifier              = Modifier.padding(24.dp),
                        horizontalAlignment   = Alignment.CenterHorizontally,
                        verticalArrangement   = Arrangement.spacedBy(8.dp)
                    ) {
                        CircularProgressIndicator(modifier = Modifier.size(32.dp))
                        Text(
                            "ルートデータを読み込み中...",
                            style = MaterialTheme.typography.bodyMedium
                        )
                    }
                }
            }

            // ── 統計情報オーバーレイ ─────────────────────────────────────
            if (points.isNotEmpty() && routeLog != null) {
                Card(
                    modifier  = Modifier
                        .align(Alignment.BottomCenter)
                        .padding(12.dp)
                        .fillMaxWidth(),
                    colors    = CardDefaults.cardColors(
                        containerColor = MaterialTheme.colorScheme.surface.copy(alpha = 0.92f)
                    ),
                    elevation = CardDefaults.cardElevation(4.dp)
                ) {
                    Row(
                        modifier              = Modifier
                            .fillMaxWidth()
                            .padding(horizontal = 16.dp, vertical = 10.dp),
                        horizontalArrangement = Arrangement.SpaceEvenly
                    ) {
                        RouteStatItem(label = "距離", value = formatDistance(routeLog.totalDistanceMeters))
                        RouteStatItem(label = "時間", value = formatDuration(routeLog.durationMs))
                        RouteStatItem(label = "ポイント", value = "${points.size}")
                    }
                }
            }
        }
    }
}

@Composable
private fun RouteStatItem(label: String, value: String) {
    Column(horizontalAlignment = Alignment.CenterHorizontally) {
        Text(value, style = MaterialTheme.typography.titleSmall)
        Text(label, style = MaterialTheme.typography.labelSmall,
             color = MaterialTheme.colorScheme.outline)
    }
}

private fun formatDistance(meters: Double): String = when {
    meters >= 1_000 -> "${"%.2f".format(meters / 1_000)} km"
    else            -> "${"%.0f".format(meters)} m"
}

private fun formatDuration(ms: Long): String {
    val totalSec = ms / 1_000
    val h = totalSec / 3600
    val m = (totalSec % 3600) / 60
    val s = totalSec % 60
    return if (h > 0) "%d:%02d:%02d".format(h, m, s)
    else   "%d:%02d".format(m, s)
}
