<template>
    <div class="container">
        <div class="tool-header">
            <router-link to="/" class="back-link">
                <ChevronLeft class="icon-sm" /> 返回首页
            </router-link>
            <h2>
                <SquareStack class="icon-lg" /> 面积计算工具
            </h2>
            <p>基于 Turf.js 的地理几何计算，支持球面/平面面积</p>
        </div>

        <div class="grid grid-2 gap-xl">
            <!-- Points Input -->
            <div class="card">
                <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem;">
                    <h3 class="card-title" style="margin: 0; display: flex; align-items: center; gap: 8px;">
                        <LayoutList class="icon-md" /> 顶点坐标 (经度, 纬度)
                    </h3>
                    <button @click="addPoint" class="btn btn-secondary btn-sm" style="display: flex; align-items: center; gap: 4px; padding: 4px 12px; font-size: 0.875rem;">
                        ➕ 添加顶点
                    </button>
                </div>

                <div class="mt-lg mb-md grid grid-2 gap-sm">
                    <div class="input-group">
                        <label class="input-label">坐标类型</label>
                        <select v-model="coordType" class="input" @change="handleModeChange">
                            <option value="lnglat">经纬度 (Lng/Lat)</option>
                            <option value="planar">平面坐标 (X/Y)</option>
                        </select>
                    </div>
                    <div class="input-group">
                        <label class="input-label">计算方式</label>
                        <select v-model="calcMethod" class="input" :disabled="coordType === 'planar'">
                            <option value="geodetic">测地线 (严密球面)</option>
                            <option value="planar">简单平面 (直角公式)</option>
                        </select>
                    </div>
                </div>

                <div class="points-list">
                    <div v-for="(point, index) in points" :key="index" class="point-input">
                        <span class="point-index">{{ index + 1 }}</span>
                        
                        <template v-if="coordType === 'lnglat'">
                            <input type="number" v-model.number="point.lng" class="input" placeholder="经度 (Lon)" step="0.000001">
                            <input type="number" v-model.number="point.lat" class="input" placeholder="纬度 (Lat)" step="0.000001">
                        </template>
                        <template v-else>
                            <input type="number" v-model.number="point.x" class="input" placeholder="X坐标 (北移)">
                            <input type="number" v-model.number="point.y" class="input" placeholder="Y坐标 (东移)">
                        </template>

                        <button v-if="points.length > 3" @click="removePoint(index)" class="btn-remove" title="删除">
                            <Trash2 class="icon-sm" />
                        </button>
                    </div>
                </div>

                <div class="mt-lg">
                    <button @click="calculate" class="btn btn-primary btn-full mt-md">开始计算</button>
                </div>
            </div>

            <!-- Result Display -->
            <div class="card">
                <h3 class="card-title">
                    <Activity class="icon-md" /> 计算结果
                </h3>

                <div v-if="area !== null" class="result-display">
                    <div class="main-result">
                        <div class="result-label">多边形面积</div>
                        <div class="result-value">{{ formatArea(area) }}</div>
                    </div>

                    <div class="result-grid mt-xl">
                        <div class="res-item">
                            <span class="res-label">顶点数</span>
                            <span class="res-val">{{ points.length }}</span>
                        </div>
                        <div class="res-item">
                            <span class="res-label">周长</span>
                            <span class="res-val">{{ formatDistance(perimeter) }}</span>
                        </div>
                        <div class="res-item">
                            <span class="res-label">亩 (换算)</span>
                            <span class="res-val">{{ (area * 0.0015).toFixed(2) }} 亩</span>
                        </div>
                        <div class="res-item">
                            <span class="res-label">公顷</span>
                            <span class="res-val">{{ (area / 10000).toFixed(4) }} ha</span>
                        </div>
                    </div>
                </div>
                <div v-else class="empty-state">
                    <Info class="icon-xl text-tertiary" />
                    <p>请输入至少 3 个顶点坐标并点击计算</p>
                </div>
            </div>
        </div>
    </div>
</template>

<script setup>
import { ref } from 'vue'
import * as turf from '@turf/turf'
import { ChevronLeft, SquareStack, LayoutList, Trash2, Activity, Info } from 'lucide-vue-next'

const points = ref([
    { lng: 108.5597255, lat: 22.8589543, x: 36557444.57, y: 2529026.75 },
    { lng: 108.5607409, lat: 22.8589507, x: 36557548.78, y: 2529026.75 },
    { lng: 108.5607373, lat: 22.8580860, x: 36557548.78, y: 2528930.99 },
    { lng: 108.5597220, lat: 22.8580896, x: 36557444.57, y: 2528930.99 }
])

const coordType = ref('lnglat')
const calcMethod = ref('geodetic')
const area = ref(null)
const perimeter = ref(0)

const handleModeChange = () => {
    area.value = null
    perimeter.value = 0
    if (coordType.value === 'planar') {
        calcMethod.value = 'planar'
    } else {
        calcMethod.value = 'geodetic'
    }
}

const addPoint = () => {
    const last = points.value[points.value.length - 1]
    points.value.push({ 
        lng: last.lng !== undefined ? Number(last.lng) + 0.001 : 116.391, 
        lat: last.lat !== undefined ? Number(last.lat) : 39.907,
        x: last.x !== undefined ? Number(last.x) + 100 : 4419500,
        y: last.y !== undefined ? Number(last.y) : 39533900
    })
}

const removePoint = (index) => {
    points.value.splice(index, 1)
}

const calculatePlanar = (pts) => {
    let a = 0;
    let p = 0;
    const n = pts.length;
    for (let i = 0; i < n; i++) {
        const j = (i + 1) % n;
        // Shoelace: sum(x_i * y_{i+1} - x_{i+1} * y_i)
        a += pts[i].x * pts[j].y;
        a -= pts[j].x * pts[i].y;
        
        // Perimeter
        const dx = pts[j].x - pts[i].x;
        const dy = pts[j].y - pts[i].y;
        p += Math.sqrt(dx*dx + dy*dy);
    }
    return { area: Math.abs(a / 2), perimeter: p };
}

const calculate = () => {
    try {
        // Ensure all inputs are numbers
        const rawPoints = points.value.map(p => ({
            lng: Number(p.lng || 0),
            lat: Number(p.lat || 0),
            x: Number(p.x || 0),
            y: Number(p.y || 0)
        }));

        if (coordType.value === 'lnglat' && calcMethod.value === 'geodetic') {
            const coords = rawPoints.map(p => [p.lng, p.lat])
            coords.push(coords[0]) 
            const polygon = turf.polygon([coords])
            area.value = turf.area(polygon)
            perimeter.value = turf.length(polygon, { units: 'meters' })
        } else {
            let pts = [];
            if (coordType.value === 'planar') {
                // *** 关键改进：使用相对坐标偏移，防止大数计算丢失精度 ***
                const x0 = rawPoints[0].x;
                const y0 = rawPoints[0].y;
                pts = rawPoints.map(p => ({ x: p.x - x0, y: p.y - y0 }));
            } else {
                // Approximate LngLat to meters using Equirectangular projection at local latitude
                const latAvg = rawPoints.reduce((acc, cur) => acc + cur.lat, 0) / rawPoints.length;
                const radLat = latAvg * Math.PI / 180;
                const kx = 111319.49 * Math.cos(radLat);
                const ky = 111319.49;
                
                // Use relative coordinates to avoid large number precision issues with degree calculation
                const lng0 = rawPoints[0].lng;
                const lat0 = rawPoints[0].lat;
                
                pts = rawPoints.map(p => ({
                    x: (p.lng - lng0) * kx,
                    y: (p.lat - lat0) * ky
                }));
            }

            if (pts.length < 3) {
                alert('顶点数量不足')
                return
            }
            const res = calculatePlanar(pts)
            area.value = res.area
            perimeter.value = res.perimeter
        }
    } catch (e) {
        alert('计算失败: ' + e.message)
    }
}

const formatArea = (val) => {
    if (val >= 1000000) return (val / 1000000).toFixed(4) + ' km²'
    return val.toFixed(2) + ' m²'
}

const formatDistance = (val) => {
    if (val >= 1000) return (val / 1000).toFixed(3) + ' km'
    return val.toFixed(2) + ' m'
}
</script>

<style scoped>
.tool-header {
    text-align: center;
    margin-bottom: var(--spacing-xl);
}

.back-link {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    color: var(--text-secondary);
    text-decoration: none;
    margin-bottom: var(--spacing-md);
    transition: color var(--transition-base);
}

.back-link:hover {
    color: var(--primary);
}

.points-list {
    max-height: 400px;
    overflow-y: auto;
    padding-right: 8px;
}

.point-input {
    display: grid;
    grid-template-columns: 30px 1fr 1fr auto;
    gap: var(--spacing-xs);
    align-items: center;
    margin-bottom: var(--spacing-sm);
}

.point-index {
    font-weight: 700;
    color: var(--text-tertiary);
    font-size: var(--font-size-sm);
}

.btn-remove {
    background: transparent;
    color: var(--danger);
    border: 1px solid var(--danger);
    border-radius: var(--border-radius-sm);
    width: 32px;
    height: 32px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.2s;
}

.btn-remove:hover {
    background: var(--danger);
    color: white;
}

.icon-sm { width: 16px; height: 16px; }
.icon-md { width: 20px; height: 20px; }
.icon-lg { width: 24px; height: 24px; vertical-align: bottom; }
.icon-xl { width: 48px; height: 48px; opacity: 0.2; margin-bottom: 16px; }

.btn-full { width: 100%; }

.empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    height: 300px;
    color: var(--text-tertiary);
    text-align: center;
}

.main-result {
    text-align: center;
    padding: var(--spacing-xl);
    background: var(--bg-secondary);
    border-radius: var(--border-radius);
    border: 1px dashed var(--primary);
}

.result-value {
    font-size: var(--font-size-3xl);
    font-weight: 800;
    color: var(--primary);
    margin-top: 8px;
}

.result-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--spacing-md);
}

.res-item {
    background: var(--bg-tertiary);
    padding: var(--spacing-md);
    border-radius: var(--border-radius-sm);
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.res-label {
    font-size: var(--font-size-xs);
    color: var(--text-tertiary);
    text-transform: uppercase;
}

.res-val {
    font-weight: 600;
    color: var(--text-primary);
}

@media (max-width: 768px) {
    .point-input {
        grid-template-columns: 25px 1fr 1fr 32px;
    }
}
</style>
