import * as React from 'react';
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 {Contact, ContactCreate, ContactsService, ContactUpdate} from '../../openapi';


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

// Extend the generated Contact type
interface ContactWithPgroups extends Contact {
  associatedPgroups: string[]; // Dynamically added pgroups
}

const ContactsManager: React.FC<ContactsManagerProps> = ({ pgroups, activePgroup }) => {
  const [contacts, setContacts] = React.useState<ContactWithPgroups[]>([]);
  const [newContact, setNewContact] = React.useState<Partial<Contact>>({
    pgroups: activePgroup,
    firstname: '',
    lastname: '',
    phone_number: '',
    email: '',
  });
  const [editContactId, setEditContactId] = React.useState<number | null>(null);
  const [errorMessage, setErrorMessage] = React.useState<string | null>(null);
  const [dialogOpen, setDialogOpen] = React.useState(false);
  const [selectedContact, setSelectedContact] = React.useState<ContactWithPgroups | null>(null);

  React.useEffect(() => {
    const fetchContacts = async () => {
      try {
        const response = await ContactsService.getAllContactsProtectedContactsAllGet();

        // Preprocess: Add associated and unassociated pgroups
        const transformedContacts = response.map((contact) => {
          const contactPgroups = contact.pgroups?.split(',').map((p) => p.trim()) || [];
          const associatedPgroups = pgroups.filter((pgroup) => contactPgroups.includes(pgroup));
          return {
            ...contact,
            associatedPgroups: associatedPgroups || [], // Ensure associatedPgroups is always an array
          };
        });

        setContacts(transformedContacts);
      } catch (error) {
        console.error('Failed to fetch contacts', error);
        setErrorMessage('Failed to load contacts. Please try again later.');
      }
    };

    fetchContacts();
  }, [pgroups]);

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

  const handleAddOrUpdateContact = async () => {
    try {
      if (editContactId !== null) {
        // Update contact
        await ContactsService.updateContactProtectedContactsContactIdPut(editContactId, newContact as ContactUpdate);
        setContacts(
          contacts.map((contact) =>
            contact.id === editContactId ? { ...contact, ...newContact } : contact
          )
        );
        setEditContactId(null);
      } else {
        // Add new contact
        const response = await ContactsService.createContactProtectedContactsPost(newContact as ContactCreate);
        setContacts([...contacts, response]);
      }
      setNewContact({ firstname: '', lastname: '', phone_number: '', email: '' });
      setErrorMessage(null);
    } catch (error) {
      console.error('Failed to add/update contact', error);
      setErrorMessage('Failed to add/update contact. Please try again later.');
    }
  };

  const handleDeleteContact = async (id: number) => {
    try {
      await ContactsService.deleteContactProtectedContactsContactIdDelete(id);
      setContacts(contacts.filter((contact) => contact.id !== id));
    } catch (error) {
      console.error('Failed to delete contact', error);
      setErrorMessage('Failed to delete contact. Please try again later.');
    }
  };

  const handleEditContact = (contact: Contact) => {
    setEditContactId(contact.id);
    setNewContact(contact);
  };

  const openDialog = (contact: ContactWithPgroups) => {
    setSelectedContact(contact);
    setDialogOpen(true);
  };

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

  const confirmDelete = async () => {
    if (selectedContact) {
      await handleDeleteContact(selectedContact.id);
      closeDialog();
    }
  };

  const togglePgroupAssociation = async (contactId: number, pgroup: string) => {
    try {
      const contact = contacts.find((c) => c.id === contactId);
      if (!contact) return;

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

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

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

      // Update the backend
      await ContactsService.updateContactProtectedContactsContactIdPut(contactId, {
        ...contact,
        pgroups: updatedPgroups.join(','), // Sync updated pgroups
      });

      // Update contact in local state
      setContacts((prevContacts) =>
        prevContacts.map((c) =>
          c.id === contactId ? { ...c, associatedPgroups: updatedPgroups } : c
        )
      );
    } catch (error) {
      console.error('Failed to add pgroup association', error);
      setErrorMessage('Failed to add pgroup association. Please try again.');
    }
  };

  const renderPgroupChips = (contact: ContactWithPgroups) => {
    return pgroups.map((pgroup) => {
      const isAssociated = (contact.associatedPgroups ?? []).includes(pgroup); // Ensure default empty array
      return (
          <Chip
              key={pgroup}
              label={pgroup}
              onClick={
                !isAssociated
                    ? () => togglePgroupAssociation(contact.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>
        Contacts Management
      </Typography>
      <Box mb={3} display="flex" justifyContent="center" alignItems="center">
        <TextField
            label="pgroup"
            name="pgroup"
            value={newContact.pgroups || ''}
            disabled
            sx={{ width: '120px' }} // Small fixed-size for non-editable field
        />
        <TextField
          label="First Name"
          name="firstname"
          value={newContact.firstname || ''}
          onChange={handleInputChange}
        />
        <TextField
          label="Last Name"
          name="lastname"
          value={newContact.lastname || ''}
          onChange={handleInputChange}
        />
        <TextField
          label="Phone Number"
          name="phone_number"
          value={newContact.phone_number || ''}
          onChange={handleInputChange}
        />
        <TextField
          label="Email"
          name="email"
          value={newContact.email || ''}
          onChange={handleInputChange}
        />
        <IconButton color="primary" onClick={handleAddOrUpdateContact}>
          {editContactId !== null ? <SaveIcon /> : <AddIcon />}
        </IconButton>
      </Box>
      {errorMessage && <Typography color="error">{errorMessage}</Typography>}
      <List>
        {contacts.length > 0 ? (
            contacts.map((contact) => (
                <ListItem key={contact.id} button>
                  <ListItemText
                      primary={`${contact.firstname} ${contact.lastname}`}
                      secondary={
                        <Box display="flex" flexWrap="wrap">
                          {contact.associatedPgroups
                              ? renderPgroupChips(contact) // Render chips only if associatedPgroups exists
                              : null}
                        </Box>
                      }
                  />
                  <ListItemSecondaryAction>
                    <IconButton edge="end" color="primary" onClick={() => handleEditContact(contact)}>
                      <EditIcon />
                    </IconButton>
                    <IconButton edge="end" color="secondary" onClick={() => openDialog(contact)}>
                      <DeleteIcon />
                    </IconButton>
                  </ListItemSecondaryAction>
                </ListItem>
            ))
        ) : (
            <Typography>No contacts 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 contact?
          </DialogContentText>
        </DialogContent>
        <DialogActions>
          <Button onClick={closeDialog} color="primary">
            Cancel
          </Button>
          <Button onClick={confirmDelete} color="secondary" autoFocus>
            Delete
          </Button>
        </DialogActions>
      </Dialog>
    </Container>
  );
};

export default ContactsManager;