import { Dispatch, bindActionCreators } from 'redux';
import { FormEditorAction, setProperty } from './types';
import { PktAddressEditor } from './PktEl';
import { connect } from 'react-redux';
import React, { useState, useCallback } from 'react';

// Simple debounce function to delay API calls
function debounce(func, delay) {
  let timeout;
  return function(...args) {
    const context = this;
    clearTimeout(timeout);
    timeout = setTimeout(() => func.apply(context, args), delay);
  };
}

type AddressElProps = ReturnType<typeof mapDispatchToProps> & {
  el: PktAddressEditor;
  path: (string | number)[];
  children: React.ReactNode;
};

const AddressEl: React.FC<AddressElProps> = (props) => {
  const { el, path, children, setProperty } = props;
  const [suggestions, setSuggestions] = useState([]);
  const [inputValue, setInputValue] = useState(el.d?.inp ?? '');

  const fetchSuggestions = async (query: string) => {
    if (!query) {
      setSuggestions([]);
      return;
    }
    try {
      const response = await fetch(`https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(query)}`);
      const data = await response.json();
      setSuggestions(data);
    } catch (error) {
      console.error('Error fetching address suggestions:', error);
      alert('Could not connect to the address service. Please check your network connection or firewall settings.');
    }
  };

  const debouncedFetch = useCallback(debounce(fetchSuggestions, 300), []);

  const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const value = e.target.value;
    setInputValue(value);
    debouncedFetch(value);
  };

  const handleSuggestionClick = (suggestion) => {
    const displayName = suggestion.display_name;
    setInputValue(displayName);
    setSuggestions([]);
    // Immediately geocode on selection
    handleGeocode(displayName);
  };

  const handleGeocode = async (address: string) => {
    if (!address) return;
    try {
      const response = await fetch(`https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(address)}&limit=1`);
      const data = await response.json();
      if (data.length > 0) {
        const { lat, lon } = data[0];
        setProperty(path, 'd', { inp: address, lat: parseFloat(lat), lng: parseFloat(lon) });
      } else {
        // Clear coordinates if address is not found
        setProperty(path, 'd', { inp: address, lat: undefined, lng: undefined });
        alert('Coordinates for this address could not be found.');
      }
    } catch (error) {
      console.error('Error geocoding address:', error);
      alert('Could not connect to the address service. Please check your network connection or firewall settings.');
    }
  };

  return (
    <div className='pkt-el pkt-address'>
      {children && <div className='children'>{children}</div>}
      <div style={{ display: 'flex', alignItems: 'center', position: 'relative' }}>
        <input
          type="text"
          className="form-control"
          value={inputValue}
          onChange={handleInputChange}
          placeholder="Enter address..."
          disabled={!el.editing}
        />
        <button 
          onClick={() => handleGeocode(inputValue)} 
          className="btn btn-primary btn-sm" 
          style={{ marginLeft: '8px' }} 
          disabled={!el.editing}
        >
          Get Coordinates
        </button>
      </div>
      {suggestions.length > 0 && (
        <ul className="list-group" style={{ position: 'absolute', zIndex: 1000, width: 'calc(100% - 150px)' }}>
          {suggestions.map((s) => (
            <li 
              key={s.place_id} 
              className="list-group-item list-group-item-action" 
              onClick={() => handleSuggestionClick(s)}
              style={{ cursor: 'pointer' }}
            >
              {s.display_name}
            </li>
          ))}
        </ul>
      )}
      {el.d?.lat && el.d?.lng && (
        <div style={{ marginTop: '8px', fontSize: '0.9em', color: '#555' }}>
          Lat: {el.d.lat}, Lng: {el.d.lng}
        </div>
      )}
    </div>
  );
};

const mapStateToProps = (state) => ({});

function mapDispatchToProps(dispatch: Dispatch<FormEditorAction>) {
  return bindActionCreators({ setProperty }, dispatch);
}

export default connect(mapStateToProps, mapDispatchToProps)(AddressEl);