import { useEffect, useState } from 'react'
import Taro from '@tarojs/taro'
import { Input, View } from '@tarojs/components'
import CustomNavBar from '@/components/layout/CustomNavBar'
import BottomTabBar from '@/components/navigation/BottomTabBar'
import Icon from '@/components/ui/Icon'
import ToastOverlay from '@/components/feedback/ToastOverlay'
import NearbyMap, { NEARBY_MAP_ID } from '@/features/nearby/components/NearbyMap'
import MapControls from '@/features/nearby/components/MapControls'
import NearbySheet from '@/features/nearby/components/NearbySheet'
import { useSystemLayout } from '@/hooks/useSystemLayout'
import { getNearbyPets, likeNearbyPet } from '@/services/nearby.service'
import { toggleFollow } from '@/services/social.service'
import { mockNearbyPets } from '@/services/mock'
import { useToast } from '@/hooks/useToast'
import type { GeoPoint, NearbyPet } from '@/types/domain'
import './index.scss'

// Fallback centre (Shanghai) when the user denies or has no location.
const DEFAULT_CENTER: GeoPoint = { latitude: 31.2304, longitude: 121.4737 }
const MIN_SCALE = 4
const MAX_SCALE = 20

export default function NearbyPage() {
  const { navHeight } = useSystemLayout()
  const [pets, setPets] = useState<NearbyPet[]>(mockNearbyPets)
  const [activeId, setActiveId] = useState(mockNearbyPets[0]?._id)
  const [filter, setFilter] = useState('all')
  const [center, setCenter] = useState<GeoPoint | null>(null)
  const [scale, setScale] = useState(15)
  const [query, setQuery] = useState('')
  const toast = useToast(480)

  // Resolve the user's real location once on mount.
  useEffect(() => {
    Taro.getLocation({ type: 'gcj02' })
      .then(res => setCenter({ latitude: res.latitude, longitude: res.longitude }))
      .catch(() => setCenter(DEFAULT_CENTER))
  }, [])

  const loadPets = (loc: GeoPoint) => {
    getNearbyPets(loc, filter).then(result => {
      setPets(result)
      setActiveId(current => current || result[0]?._id)
    })
  }

  // Load nearby pets relative to the resolved centre, re-loading on filter change.
  useEffect(() => {
    if (!center) return
    loadPets(center)
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [center, filter])

  const relocate = () => {
    Taro.getLocation({ type: 'gcj02' })
      .then(res => setCenter({ latitude: res.latitude, longitude: res.longitude }))
      .catch(() => {
        Taro.showModal({
          title: '需要位置权限',
          content: '请在右上角「···」→ 设置中允许获取位置后重试',
          showCancel: false
        })
      })
  }

  // Sync our scale only after a user pinch-zoom (causedBy 'scale'), so the
  // programmatic +/- buttons aren't reverted by a read-back race.
  const onRegionChange = (causedBy: string) => {
    if (causedBy !== 'scale') return
    try {
      Taro.createMapContext(NEARBY_MAP_ID).getScale({
        success: (r: any) => {
          if (r?.scale) setScale(Math.round(r.scale))
        }
      })
    } catch {
      /* map context not ready */
    }
  }

  const zoomIn = () => setScale(s => Math.min(MAX_SCALE, s + 1))
  const zoomOut = () => setScale(s => Math.max(MIN_SCALE, s - 1))
  const refresh = () => {
    if (center) loadPets(center)
    Taro.showToast({ title: '已刷新附近', icon: 'none' })
  }

  const likePet = async (id: string) => {
    toast.show()
    await likeNearbyPet(id)
  }

  const updateOwnerRelation = (
    ownerId: string,
    patch: Pick<NearbyPet, 'isFollowing' | 'isFriend'>
  ) => {
    setPets(current => current.map(pet => (pet.ownerId === ownerId ? { ...pet, ...patch } : pet)))
  }

  const openChatWithPet = (pet: NearbyPet) => {
    if (!pet.ownerId) return
    const title = pet.ownerName || pet.name
    Taro.navigateTo({
      url: `/pages/chat/index?targetUserId=${pet.ownerId}&title=${encodeURIComponent(title)}`
    })
  }

  const handleFriendAction = async (pet: NearbyPet) => {
    if (pet.isMine) {
      Taro.showToast({ title: '这是你自己的毛孩子', icon: 'none' })
      return
    }

    if (pet.isFriend) {
      openChatWithPet(pet)
      return
    }

    if (pet.isFollowing) {
      Taro.showToast({ title: '已关注，等对方回关', icon: 'none' })
      return
    }

    updateOwnerRelation(pet.ownerId, { isFollowing: true, isFriend: false })
    try {
      const result = await toggleFollow(pet.ownerId, true)
      updateOwnerRelation(pet.ownerId, { isFollowing: true, isFriend: result.mutual })
      Taro.showToast({
        title: result.mutual ? '已成为汪友' : '已关注，等对方回关',
        icon: 'none'
      })
    } catch {
      updateOwnerRelation(pet.ownerId, { isFollowing: false, isFriend: false })
      Taro.showToast({ title: '添加失败，请稍后再试', icon: 'none' })
    }
  }

  const q = query.trim().toLowerCase()
  const visiblePets = q
    ? pets.filter(p => p.name.toLowerCase().includes(q) || (p.breed || '').toLowerCase().includes(q))
    : pets

  return (
    <View className='nearby-page'>
      <NearbyMap
        pets={visiblePets}
        center={center || DEFAULT_CENTER}
        scale={scale}
        activeId={activeId}
        onSelect={setActiveId}
        onRegionChange={onRegionChange}
      />
      <CustomNavBar />
      <View className='nearby-page__search' style={{ top: `${navHeight + 6}px` }}>
        <Icon name='search' size={14} />
        <Input
          className='nearby-page__search-input'
          value={query}
          placeholder='搜索名字 / 品种'
          placeholderClass='nearby-page__search-ph'
          confirmType='search'
          onInput={e => setQuery(e.detail.value)}
        />
        {query ? (
          <View className='nearby-page__search-clear' onClick={() => setQuery('')}>
            <Icon name='close' size={14} />
          </View>
        ) : null}
      </View>
      <MapControls onRefresh={refresh} onZoomIn={zoomIn} onZoomOut={zoomOut} onLocate={relocate} />
      <NearbySheet
        pets={visiblePets}
        activeId={activeId}
        filter={filter}
        onFilterChange={setFilter}
        onSelect={setActiveId}
        onFriendAction={handleFriendAction}
        onLike={likePet}
      />
      <ToastOverlay visible={toast.visible} />
      <BottomTabBar active='nearby' />
    </View>
  )
}
