import React, {useEffect, useState} from 'react';
import Select from 'react-select';

interface Link {
    rel: string;
    href: string;
    type: string;
    title?: string;
}

interface Person {
    id: number;
    nameFull: string;
    reference: string;
    nameWithReference: string;
    links: Link[]; // Add links to represent HATEOAS navigation
}

interface PersonPickerProps {
    fetchPeople: () => Promise<Person[]>; // Function to fetch people data
    onSelect?: (person: Person) => void; // Callback when a person is selected
    value?: any;
}

export function PersonPicker({ fetchPeople, onSelect, value }: PersonPickerProps) {
    const [options, setOptions] = useState<{
        value: number;
        label: string;
        reference: string;
        nameFull: string;
        links: Link[];
    }[]>([]);
    const [loading, setLoading] = useState(true);
    const [dataFetched, setDataFetched] = useState(false); // Track if data has been fetched
    const [isFetchingInitialData, setIsFetchingInitialData] = useState(false);

    // Fetch people only if data hasn't been fetched yet
    useEffect(() => {
        const loadPeople = async () => {
            if (dataFetched) return; // Skip if data already fetched
            if (!fetchPeople || isFetchingInitialData) return; // Skip if already fetching data or no function provided.
            setIsFetchingInitialData(true);

            try {
                const people = await fetchPeople(); // Fetch the data
                const mappedOptions = people.map((person) => ({
                    value: person.id,
                    label: person.nameWithReference,
                    reference: person.reference,
                    nameFull: person.nameFull,
                    links: person.links,
                }));
                setOptions(mappedOptions);
                setDataFetched(true); // Mark data as fetched
            } catch (error) {
                console.error('Error fetching people:', error);
            } finally {
                setLoading(false); // Stop loading spinner
                setIsFetchingInitialData(false);
            }
        };

        loadPeople();
    }, []);

    // Default behaviour for onSelect if none is provided
    const logSelectionToConsole = (person: Person) => {
        console.log('Selected person details: ', person);
    };

    // Ensure we always have a valid onSelect function
    const effectiveOnSelect = onSelect || logSelectionToConsole;

    // Ensures we always use a valid callback
    const handleSelect = (selectedOption: any) => {
        if (!selectedOption) return; // Gracefully handle null or undefined selection
        const person = {
            id: selectedOption.value,
            nameFull: selectedOption.nameFull,
            reference: selectedOption.reference,
            nameWithReference: selectedOption.nameWithReference,
            links: selectedOption.links,
        };
        effectiveOnSelect(person); // Always call a valid function
    };

    // Custom filter function
    const filterOption = (option: any, inputValue: string) => {
        // Only filter by label (name) and reference, not by value (ID)
        return (
            option.label.toLowerCase().includes(inputValue.toLowerCase()) ||
            option.data.reference.toLowerCase().includes(inputValue.toLowerCase())
        );
    };

    return <>
        <div style={{ maxWidth: '400px' }}>
            <Select
                classNamePrefix="react_element_select"
                options={options} // Static list of options
                value={value || null} // Bind value
                onChange={handleSelect}
                isLoading={loading} // Show loading spinner while fetching
                placeholder="Search for a person...."
                isSearchable
                filterOption={filterOption} // Use custom filter
                styles={{
                    control: (base) => ({
                        ...base,
                        borderColor: '#ced4da', // Bootstrap-like border colour
                        boxShadow: 'none',
                        '&:hover': { borderColor: '#86b7fe', cursor: 'text'},
                    }),
                }}
            />
        </div>
    </>
}
