import { type FC, useState, useEffect } from 'react'
import { MapContainer, TileLayer, Polygon, Polyline, useMapEvents, useMap } from 'react-leaflet'
import type { LatLngTuple } from 'leaflet'
import type { LatLng } from 'leaflet'
import type { GeoJSONPolygon, GeoJSONPoint } from '../types/Types'
import { Trash } from 'iconsax-react'

interface ServiceAreaPickerProps {
    initialPolygon?: GeoJSONPolygon;
    onPolygonSelect: (polygon: GeoJSONPolygon | null) => void
}

const ChangeView = ({ center, zoom }: { center: LatLngTuple; zoom: number }) => {
    const map = useMap()
    useEffect(() => {
        map.setView(center, zoom)
    }, [map, center, zoom])
    return null
}

const ServiceAreaPicker: FC<ServiceAreaPickerProps> = ({ initialPolygon, onPolygonSelect }) => {
    const [points, setPoints] = useState<LatLngTuple[]>([])
    const [isDrawing, setIsDrawing] = useState(false)
    const [isPolygonClosed, setIsPolygonClosed] = useState(false)
    const mapCenter: LatLngTuple = [35.6892, 51.3890] // تهران به عنوان پیش‌فرض

    const handleClear = () => {
        setPoints([])
        setIsDrawing(false)
        setIsPolygonClosed(false)
        onPolygonSelect(null)
    }

    // تبدیل GeoJSON Polygon به LatLngTuple[]
    const convertGeoJSONToPoints = (polygon: GeoJSONPolygon): LatLngTuple[] => {
        if (!polygon.coordinates || polygon.coordinates.length === 0) {
            return []
        }
        // اولین ring از coordinates را بگیر (outer ring)
        const ring = polygon.coordinates[0]
        // تبدیل [lng, lat] به [lat, lng] و حذف آخرین نقطه اگر تکراری باشد
        const convertedPoints: LatLngTuple[] = ring.map((coord) => [coord[1], coord[0]])
        // اگر اولین و آخرین نقطه یکسان هستند، آخرین را حذف کن
        if (convertedPoints.length > 0 &&
            convertedPoints[0][0] === convertedPoints[convertedPoints.length - 1][0] &&
            convertedPoints[0][1] === convertedPoints[convertedPoints.length - 1][1]) {
            convertedPoints.pop()
        }
        return convertedPoints
    }

    // مقداردهی اولیه با initialPolygon
    useEffect(() => {
        if (initialPolygon) {
            const initialPoints = convertGeoJSONToPoints(initialPolygon)
            if (initialPoints.length >= 3) {
                setPoints(initialPoints)
                setIsPolygonClosed(true)
                onPolygonSelect(initialPolygon)
            } else {
                handleClear()
            }
        } else {
            handleClear()
        }
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [initialPolygon])

    const convertToGeoJSON = (pts: LatLngTuple[]): GeoJSONPolygon | null => {
        if (pts.length < 3) return null

        // تبدیل [lat, lng] به [lng, lat] و بستن Polygon با تکرار اولین نقطه
        const coords = pts.map((pt) => [pt[1], pt[0]] as GeoJSONPoint)

        // در GeoJSON Polygon، اولین نقطه باید در انتها تکرار شود تا بسته شود
        if (coords.length > 0 &&
            (coords[0][0] !== coords[coords.length - 1][0] ||
                coords[0][1] !== coords[coords.length - 1][1])) {
            coords.push(coords[0])
        }

        const coordinates: GeoJSONPoint[][] = [coords]

        return {
            type: 'Polygon',
            coordinates,
        }
    }

    // بررسی فاصله بین دو نقطه (به درجه)
    const getDistance = (pt1: LatLngTuple, pt2: LatLngTuple): number => {
        const latDiff = pt1[0] - pt2[0]
        const lngDiff = pt1[1] - pt2[1]
        return Math.sqrt(latDiff * latDiff + lngDiff * lngDiff)
    }

    const handleMapClick = (e: { latlng: LatLng }) => {
        if (!isDrawing && points.length === 0) {
            setIsDrawing(true)
        }

        const newPoint: LatLngTuple = [e.latlng.lat, e.latlng.lng]

        // اگر حداقل 3 نقطه داریم و کاربر روی نقطه اول کلیک کرد (یا نزدیک به آن)، Polygon را ببند
        if (points.length >= 3) {
            const firstPoint = points[0]
            const distance = getDistance(newPoint, firstPoint)
            // اگر فاصله کمتر از 0.002 درجه باشد (تقریباً 200 متر)، به عنوان کلیک روی نقطه اول در نظر بگیریم
            if (distance < 0.002) {
                // Polygon را ببند و کامل کن (convertToGeoJSON خودش نقطه اول را اضافه می‌کند)
                const geoJsonPolygon = convertToGeoJSON(points)
                if (geoJsonPolygon) {
                    onPolygonSelect(geoJsonPolygon)
                    setIsDrawing(false)
                    setIsPolygonClosed(true)
                    // نقاط را نگه دار تا Polygon کامل نمایش داده شود
                    return
                }
            }
        }

        // اگر Polygon قبلاً بسته شده بود، دوباره شروع کن
        if (isPolygonClosed) {
            setPoints([])
            setIsPolygonClosed(false)
            setIsDrawing(true)
            onPolygonSelect(null)
        }

        // نقطه جدید را اضافه کن
        const updatedPoints = [...points, newPoint]
        setPoints(updatedPoints)

        // تا زمانی که Polygon بسته نشده، null بفرست
        onPolygonSelect(null)
    }

    const MapClickHandler = () => {
        useMapEvents({
            click: handleMapClick,
        })
        return null
    }

    const polygonOptions = {
        color: '#3B82F6',
        fillColor: '#3B82F6',
        fillOpacity: 0.2,
        weight: 2,
    }

    const polylineOptions = {
        color: '#3B82F6',
        weight: 2,
        dashArray: '5, 10',
    }

    // فقط وقتی حداقل 2 نقطه داریم، center را تغییر می‌دهیم
    const centerPoint = points.length >= 2
        ? (() => {
            const sum = points.reduce(
                (acc, pt) => [acc[0] + pt[0], acc[1] + pt[1]],
                [0, 0] as [number, number]
            )
            return [sum[0] / points.length, sum[1] / points.length] as LatLngTuple
        })()
        : points.length === 1
            ? points[0] // با یک نقطه، center همان نقطه است
            : mapCenter

    return (
        <div className="w-full">
            <div className="w-full h-[400px] rounded-xl overflow-hidden relative">
                <MapContainer
                    center={centerPoint}
                    zoom={13}
                    style={{ height: '100%', width: '100%' }}
                    scrollWheelZoom={true}
                >
                    <TileLayer
                        attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
                        url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
                    />
                    {points.length >= 2 && (
                        <ChangeView center={centerPoint} zoom={13} />
                    )}
                    {points.length === 0 && (
                        <ChangeView center={mapCenter} zoom={13} />
                    )}
                    <MapClickHandler />
                    {points.length >= 2 && !isPolygonClosed && (
                        <Polyline
                            positions={points}
                            pathOptions={polylineOptions}
                        />
                    )}
                    {/* فقط وقتی Polygon بسته شده، نمایش بده */}
                    {points.length >= 3 && isPolygonClosed && (
                        <Polygon
                            positions={points}
                            pathOptions={polygonOptions}
                        />
                    )}
                </MapContainer>
            </div>

            <div className="mt-4 flex flex-col gap-3">
                <div className="text-xs text-gray-600 text-center">
                    {points.length === 0
                        ? 'روی نقشه کلیک کنید تا نقاط ناحیه را انتخاب کنید'
                        : isPolygonClosed
                            ? `ناحیه کامل شده (${points.length} نقطه)`
                            : points.length < 3
                                ? `نقاط انتخاب شده: ${points.length} (حداقل 3 نقطه لازم است)`
                                : `نقاط انتخاب شده: ${points.length} - برای بستن ناحیه روی نقطه اول کلیک کنید`}
                </div>

                <div className="flex gap-2">
                    {points.length > 0 && (
                        <button
                            type="button"
                            onClick={handleClear}
                            className=" w-fit h-10 px-4 text-xs rounded-xl border border-red-500 text-red-500 hover:bg-red-50 transition-colors flex items-center justify-center gap-2"
                        >
                            <Trash color='red' size={16} />
                            <span>پاک کردن ناحیه</span>
                        </button>
                    )}
                </div>
            </div>
        </div>
    )
}

export default ServiceAreaPicker