import React from 'react';
import Fuse from 'fuse.js';
import { CountryList } from '../components/CountryList';
import {
    Container,
    Typography,
    List,
    ListItem,
    IconButton,
    TextField,
    Box,
    ListItemText,
    ListItemSecondaryAction,
    Dialog,
    DialogActions,
    DialogContent,
    DialogContentText,
    DialogTitle,
    Button,
    Chip
} from '@mui/material';
import DeleteIcon from '@mui/icons-material/Delete';
import EditIcon from '@mui/icons-material/Edit';
import SaveIcon from '@mui/icons-material/Save';
import AddIcon from '@mui/icons-material/Add';
import {Address, AddressCreate, AddressesService, AddressUpdate} from '../../openapi';


interface AddressManagerProps {
    pgroups: string[];
    activePgroup: string;
}


// Extend the generated Address type
interface AddressWithPgroups extends Address {
    associatedPgroups: string[]; // Dynamically added pgroups
}
   
const fuse = new Fuse(CountryList, {
    threshold: 0.3, // Lower threshold for stricter matches
    includeScore: true,
});

const AddressManager: React.FC<AddressManagerProps> = ({ pgroups, activePgroup }) => {
    // Use pgroups and activePgroup directly
    console.log('User pgroups:', pgroups);
    console.log('Active pgroup:', activePgroup);
    const [countrySuggestions, setCountrySuggestions] = React.useState<string[]>([]);
    const [addresses, setAddresses] = React.useState<Address[]>([]);
    const [newAddress, setNewAddress] = React.useState<Partial<Address>>({
        pgroups: activePgroup,
        house_number: '',
        street: '',
        city: '',
        state: '',
        zipcode: '',
        country: '',
    });
    const [editAddressId, setEditAddressId] = React.useState<number | null>(null);
    const [errorMessage, setErrorMessage] = React.useState<string | null>(null);
    const [dialogOpen, setDialogOpen] = React.useState(false);
    const [selectedAddress, setSelectedAddress] = React.useState<Address | null>(null);
    const handleCountryInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
        const { value } = event.target;

        // Update the corresponding field in `newAddress`
        setNewAddress({ ...newAddress, country: value });

        // Perform fuzzy search using Fuse.js
        if (value) {
            const suggestions = fuse.search(value).map((result) => result.item);
            setCountrySuggestions(suggestions); // Update suggestions state
        } else {
            setCountrySuggestions([]); // Clear suggestions if the input is empty
        }
    };

    React.useEffect(() => {
        const fetchAllData = async () => {
            try {
                const response = await AddressesService.getAllAddressesProtectedAddressesAllGet();

                // Preprocess: Add associated pgroups with a default value if not available
                const transformedAddresses = response.map((address) => {
                    const addressPgroups = address.pgroups?.split(',').map((p) => p.trim()) || [];
                    const associatedPgroups = pgroups.filter((pgroup) => addressPgroups.includes(pgroup));
                    return {
                        ...address,
                        associatedPgroups: associatedPgroups || [], // Ensure it's always an array
                    };
                });

                setAddresses(transformedAddresses);
            } catch (error) {
                console.error('Failed to fetch addresses', error);
                setErrorMessage('Failed to load addresses. Please try again.');
            }
        };
        fetchAllData();
    }, [pgroups]);

    const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
        const { name, value } = event.target;
        setNewAddress({ ...newAddress, [name]: value });
    };

    const handleAddOrUpdateAddress = async () => {
        try {
            if (editAddressId !== null) {
                // Update address (mark old one obsolete, create a new one)
                const updatedAddress = await AddressesService.updateReturnAddressProtectedAddressesAddressIdPut(
                    editAddressId,
                    newAddress as AddressUpdate
                );

                // Replace old address with the new one in the list
                setAddresses(addresses.map(address =>
                    address.id === editAddressId ? updatedAddress : address
                ).filter(address => address.status === "active")); // Keep only active addresses
                setEditAddressId(null);
            } else {
                // Add new address
                const response = await AddressesService.createReturnAddressProtectedAddressesPost(newAddress as AddressCreate);
                setAddresses([...addresses, response]);
            }
            setNewAddress({ house_number:'', street: '', city: '', state: '', zipcode: '', country: '' });
            setErrorMessage(null);
        } catch (error) {
            console.error('Failed to add/update address', error);
            setErrorMessage('Failed to add/update address. Please try again.');
        }
    };

    const handleDeleteAddress = async (id: number) => {
        try {
            // Delete (inactivate) the address
            await AddressesService.deleteReturnAddressProtectedAddressesAddressIdDelete(id);

            // Remove the obsolete address from the active list in the UI
            setAddresses(addresses.filter(address => address.id !== id && address.status === "active"));
        } catch (error) {
            console.error('Failed to delete address', error);
            setErrorMessage('Failed to delete address. Please try again.');
        }
    };

    const handleEditAddress = (address: Address) => {
        setEditAddressId(address.id);
        setNewAddress(address);
    };

    const openDialog = (address: Address) => {
        setSelectedAddress(address);
        setDialogOpen(true);
    };

    const closeDialog = () => {
        setDialogOpen(false);
        setSelectedAddress(null);
    };

    const confirmDelete = async () => {
        if (selectedAddress) {
            await handleDeleteAddress(selectedAddress.id);
            closeDialog();
        }
    };

    const togglePgroupAssociation = async (addressId: number, pgroup: string) => {
        try {
            const address = addresses.find((addr) => addr.id === addressId);
            if (!address) return;

            const isAssociated = address.associatedPgroups.includes(pgroup);

            // Only allow adding a pgroup
            if (isAssociated) {
                console.warn('Removing a pgroup is not allowed.');
                return;
            }

            const updatedPgroups = [...address.associatedPgroups, pgroup]; // Add the pgroup

            // Update the backend
            await AddressesService.updateReturnAddressProtectedAddressesAddressIdPut(addressId, {
                ...address,
                pgroups: updatedPgroups.join(','), // Sync updated pgroups
            });

            // Update address in local state
            setAddresses((prevAddresses) =>
                prevAddresses.map((addr) =>
                    addr.id === addressId
                        ? { ...addr, associatedPgroups: updatedPgroups }
                        : addr
                )
            );
        } catch (error) {
            console.error('Failed to add pgroup association', error);
            setErrorMessage('Failed to add pgroup association. Please try again.');
        }
    };

    const renderPgroupChips = (address: AddressWithPgroups) => {
        return pgroups.map((pgroup) => {
            const isAssociated = address.associatedPgroups.includes(pgroup);
            return (
                <Chip
                    key={pgroup}
                    label={pgroup}
                    onClick={
                        !isAssociated  // Only allow adding a new pgroup, no removal
                            ? () => togglePgroupAssociation(address.id, pgroup)
                            : undefined
                    }
                    sx={{
                        backgroundColor: isAssociated ? '#19d238' : '#b0b0b0',
                        color: 'white',
                        borderRadius: '8px',
                        fontWeight: 'bold',
                        height: '20px',
                        fontSize: '12px',
                        boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.2)',
                        cursor: isAssociated ? 'default' : 'pointer', // Disable pointer for associated chips
                        '&:hover': { opacity: isAssociated ? 1 : 0.8 }, // Disable hover effect for associated chips
                        mr: 1,
                        mb: 1,
                    }}
                />
            );
        });
    };

    return (
        <Container>
            <Typography variant="h4" gutterBottom>
                Addresses Management
            </Typography>
            <Box display="flex" justifyContent="center" alignItems="center" mb={3} gap={2}>
                <TextField
                    label="pgroup"
                    name="pgroup"
                    value={newAddress.pgroups || ''}
                    disabled
                    sx={{ width: '120px' }} // Small fixed-size for non-editable field
                />
                <TextField
                    label="Number"
                    name="house_number"
                    value={newAddress.house_number || ''}
                    onChange={handleInputChange}
                    sx={{ width: '100px' }} // Small size for Number field
                />
                <TextField
                    label="Street"
                    name="street"
                    value={newAddress.street || ''}
                    onChange={handleInputChange}
                    sx={{ flex: 1 }} // Street field takes the most space
                />
                <TextField
                    label="City"
                    name="city"
                    value={newAddress.city || ''}
                    onChange={handleInputChange}
                    sx={{ width: '150px' }} // Medium size for City
                />
                <TextField
                    label="State"
                    name="state"
                    value={newAddress.state || ''}
                    onChange={handleInputChange}
                    sx={{ width: '100px' }} // Small size
                />
                <TextField
                    label="Zipcode"
                    name="zipcode"
                    value={newAddress.zipcode || ''}
                    onChange={handleInputChange}
                    sx={{ width: '120px' }} // Medium size for Zipcode
                />
                <Box sx={{ position: 'relative', flex: 1 }}> {/* Country field dynamically takes available space */}
                    <TextField
                        label="Country"
                        name="country"
                        value={newAddress.country || ''}
                        onChange={handleCountryInputChange}
                        fullWidth
                        required
                        error={
                            !!((editAddressId !== null || newAddress.street || newAddress.city || newAddress.zipcode) && !newAddress.country)
                        }
                        helperText={
                            !!((editAddressId !== null || newAddress.street || newAddress.city || newAddress.zipcode) && !newAddress.country)
                                ? 'Country is required'
                                : ''
                        }
                    />
                    {/* Render suggestions dynamically */}
                    {countrySuggestions.length > 0 && (
                        <Box
                            sx={{
                                border: '1px solid #ccc',
                                borderRadius: '4px',
                                background: 'white',
                                position: 'absolute',
                                top: '100%', // Place below the TextField
                                left: 0,
                                zIndex: 10,
                                width: '100%', // Match the width of the TextField
                                marginTop: '4px', // Small spacing below the TextField
                            }}
                        >
                            {countrySuggestions.map((suggestion, index) => (
                                <Typography
                                    key={index}
                                    sx={{
                                        padding: '8px',
                                        cursor: 'pointer',
                                        '&:hover': { background: '#f5f5f5' },
                                    }}
                                    onClick={() => {
                                        setNewAddress({ ...newAddress, country: suggestion });
                                        setCountrySuggestions([]); // Clear suggestions
                                    }}
                                >
                                    {suggestion}
                                </Typography>
                            ))}
                        </Box>
                    )}
                </Box>
                <IconButton color="primary" onClick={handleAddOrUpdateAddress}>
                    {editAddressId !== null ? <SaveIcon /> : <AddIcon />}
                </IconButton>
            </Box>
            {errorMessage && <Typography color="error">{errorMessage}</Typography>}
            <List>
                {addresses.length > 0 ? (
                    addresses.map((address) => (
                        <ListItem key={address.id} button>
                            <ListItemText
                                primary={`${address.house_number}, ${address.street}, ${address.city}`}
                                secondary={
                                    <Box display="flex" flexWrap="wrap">
                                        {address.associatedPgroups
                                            ? renderPgroupChips(address) // Render chips if associatedPgroups is available
                                            : null}
                                    </Box>
                                }
                            />
                            <ListItemSecondaryAction>
                                <IconButton edge="end" color="primary" onClick={() => handleEditAddress(address)}>
                                    <EditIcon />
                                </IconButton>
                                <IconButton edge="end" color="secondary" onClick={() => handleDeleteAddress(address.id)}>
                                    <DeleteIcon />
                                </IconButton>
                            </ListItemSecondaryAction>
                        </ListItem>
                    ))
                ) : (
                    <Typography>No addresses found</Typography>
                )}
            </List>
            <Dialog
                open={dialogOpen}
                onClose={closeDialog}
                aria-labelledby="alert-dialog-title"
                aria-describedby="alert-dialog-description"
            >
                <DialogTitle id="alert-dialog-title">{"Confirm Delete"}</DialogTitle>
                <DialogContent>
                    <DialogContentText id="alert-dialog-description">
                        Are you sure you want to delete this address?
                    </DialogContentText>
                </DialogContent>
                <DialogActions>
                    <Button onClick={closeDialog} color="primary">
                        Cancel
                    </Button>
                    <Button onClick={confirmDelete} color="secondary" autoFocus>
                        Delete
                    </Button>
                </DialogActions>
            </Dialog>
        </Container>
    );
};

export default AddressManager;