import { useEffect, useRef, useState } from 'react';
import { Button, Empty, Input, List, Modal, Space, Spin, Typography, message } from 'antd';
import { request } from '../lib/api';
import {
  placeToPicked,
  type LbsPlaceItem,
  type TencentPickedLocation,
} from '../lib/tencentLocPicker';

type Props = {
  open: boolean;
  onClose: () => void;
  onPick: (loc: TencentPickedLocation) => void;
  latitude?: number | null;
  longitude?: number | null;
  /** 城市名，提升搜索相关性 */
  region?: string | null;
};

function hasCoords(lat: unknown, lng: unknown): lat is number {
  const a = typeof lat === 'number' ? lat : Number(lat);
  const b = typeof lng === 'number' ? lng : Number(lng);
  return Number.isFinite(a) && Number.isFinite(b) && !(a === 0 && b === 0);
}

export default function TencentLocPickerModal({
  open,
  onClose,
  onPick,
  latitude,
  longitude,
  region,
}: Props) {
  const [keyword, setKeyword] = useState('');
  const [items, setItems] = useState<LbsPlaceItem[]>([]);
  const [loading, setLoading] = useState(false);
  const [pending, setPending] = useState<TencentPickedLocation | null>(null);
  const [hint, setHint] = useState('输入地点名称搜索，或加载附近地点');
  const seqRef = useRef(0);

  useEffect(() => {
    if (!open) {
      setKeyword('');
      setItems([]);
      setPending(null);
      setHint('输入地点名称搜索，或加载附近地点');
      return;
    }
    const lat = latitude != null ? Number(latitude) : NaN;
    const lng = longitude != null ? Number(longitude) : NaN;
    if (hasCoords(lat, lng)) {
      void loadNearby(lat, lng);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [open]);

  async function loadNearby(lat: number, lng: number) {
    const seq = ++seqRef.current;
    setLoading(true);
    setHint('正在加载附近地点…');
    try {
      const res = await request<{ items: LbsPlaceItem[] }>(
        `/common/lbs/nearby?lat=${encodeURIComponent(String(lat))}&lng=${encodeURIComponent(String(lng))}`,
      );
      if (seq !== seqRef.current) return;
      setItems(res.items ?? []);
      setHint(res.items?.length ? `附近 ${res.items.length} 个地点，点击选择` : '附近暂无地点，请搜索');
    } catch (e) {
      if (seq !== seqRef.current) return;
      const msg = e instanceof Error ? e.message : '加载附近地点失败';
      setItems([]);
      setHint(msg);
      message.error(msg);
    } finally {
      if (seq === seqRef.current) setLoading(false);
    }
  }

  async function runSearch(q: string) {
    const trimmed = q.trim();
    if (!trimmed) {
      message.warning('请输入搜索关键词');
      return;
    }
    const seq = ++seqRef.current;
    setLoading(true);
    setHint('搜索中…');
    try {
      const params = new URLSearchParams({ keyword: trimmed });
      if (region?.trim()) params.set('region', region.trim());
      const lat = latitude != null ? Number(latitude) : NaN;
      const lng = longitude != null ? Number(longitude) : NaN;
      if (Number.isFinite(lat) && Number.isFinite(lng)) {
        params.set('lat', String(lat));
        params.set('lng', String(lng));
      }
      const res = await request<{ items: LbsPlaceItem[] }>(`/common/lbs/suggest?${params.toString()}`);
      if (seq !== seqRef.current) return;
      setItems(res.items ?? []);
      setHint(res.items?.length ? `找到 ${res.items.length} 个结果，点击选择` : '无匹配结果，换个关键词试试');
    } catch (e) {
      if (seq !== seqRef.current) return;
      const msg = e instanceof Error ? e.message : '搜索失败';
      setItems([]);
      setHint(msg);
      message.error(msg);
    } finally {
      if (seq === seqRef.current) setLoading(false);
    }
  }

  function useBrowserLocation() {
    if (!navigator.geolocation) {
      message.error('当前浏览器不支持定位');
      return;
    }
    setLoading(true);
    navigator.geolocation.getCurrentPosition(
      (pos) => {
        const lat = pos.coords.latitude;
        const lng = pos.coords.longitude;
        setPending({ latitude: lat, longitude: lng, name: '当前位置' });
        void loadNearby(lat, lng);
      },
      () => {
        setLoading(false);
        message.error('定位失败，请检查浏览器定位权限');
      },
      { enableHighAccuracy: true, timeout: 12000 },
    );
  }

  function confirmPick() {
    if (!pending) {
      message.warning('请先从列表中选择一个地点');
      return;
    }
    onPick(pending);
    onClose();
  }

  return (
    <Modal
      title="地图选点（腾讯位置服务）"
      open={open}
      onCancel={onClose}
      width={720}
      destroyOnClose
      footer={
        <Space style={{ width: '100%', justifyContent: 'space-between' }}>
          <Typography.Text type="secondary" style={{ maxWidth: 420 }} ellipsis>
            {pending
              ? `${pending.latitude.toFixed(6)}, ${pending.longitude.toFixed(6)}${
                  pending.name ? ` · ${pending.name}` : ''
                }`
              : '搜索或选择附近地点后确认'}
          </Typography.Text>
          <Space>
            <Button onClick={onClose}>取消</Button>
            <Button type="primary" disabled={!pending} onClick={confirmPick}>
              确认选点
            </Button>
          </Space>
        </Space>
      }
    >
      <Space direction="vertical" style={{ width: '100%' }} size="middle">
        <Space.Compact style={{ width: '100%' }}>
          <Input
            allowClear
            placeholder="输入小区 / 写字楼 / 门店名称"
            value={keyword}
            onChange={(e) => setKeyword(e.target.value)}
            onPressEnter={() => void runSearch(keyword)}
          />
          <Button type="primary" loading={loading} onClick={() => void runSearch(keyword)}>
            搜索
          </Button>
        </Space.Compact>
        <Space wrap>
          <Button onClick={useBrowserLocation} disabled={loading}>
            定位当前位置
          </Button>
          <Typography.Text type="secondary">{hint}</Typography.Text>
        </Space>
        <div style={{ height: 420, overflow: 'auto', border: '1px solid #f0f0f0', borderRadius: 8 }}>
          {loading && !items.length ? (
            <div style={{ height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
              <Spin tip="加载中…" />
            </div>
          ) : items.length ? (
            <List
              size="small"
              dataSource={items}
              renderItem={(item) => {
                const active =
                  pending?.latitude === item.latitude && pending?.longitude === item.longitude;
                return (
                  <List.Item
                    style={{
                      cursor: 'pointer',
                      background: active ? 'rgba(22, 119, 255, 0.08)' : undefined,
                      paddingInline: 12,
                    }}
                    onClick={() => setPending(placeToPicked(item))}
                  >
                    <List.Item.Meta
                      title={item.title}
                      description={
                        <span>
                          {item.address}
                          <br />
                          <Typography.Text type="secondary" style={{ fontSize: 12 }}>
                            {item.latitude.toFixed(6)}, {item.longitude.toFixed(6)}
                          </Typography.Text>
                        </span>
                      }
                    />
                  </List.Item>
                );
              }}
            />
          ) : (
            <Empty style={{ marginTop: 80 }} description={hint} />
          )}
        </div>
      </Space>
    </Modal>
  );
}
