import React, {
  useCallback,
  useContext,
  useEffect,
  useRef,
  useState,
} from 'react';
import {
  Avatar,
  Box,
  Button,
  ButtonBase,
  Collapse,
  Dialog,
  DialogActions,
  DialogContent,
  DialogContentText,
  DialogTitle,
  MenuItem,
  Popover,
  Select,
  TextField,
  Typography,
} from '@mui/material';
import { LoadingButton } from '@mui/lab';
import LockIcon from '@mui/icons-material/Lock';
import NoEncryptionGmailerrorredIcon from '@mui/icons-material/NoEncryptionGmailerrorred';
import {
  MyContext,
  getArbitraryEndpointReact,
  getBaseApiReact,
} from '../../App';
import { Spacer } from '../../common/Spacer';
import { CustomLoader } from '../../common/CustomLoader';
import { RequestQueueWithPromise } from '../../utils/queue/queue';
import { useRecoilState } from 'recoil';
import {
  myGroupsWhereIAmAdminAtom,
  promotionTimeIntervalAtom,
  promotionsAtom,
} from '../../atoms/global';
import { Label } from './AddGroup';
import ShortUniqueId from 'short-unique-id';
import { CustomizedSnackbars } from '../Snackbar/Snackbar';
import { getGroupNames } from './UserListOfInvites';
import { useVirtualizer } from '@tanstack/react-virtual';
import ErrorBoundary from '../../common/ErrorBoundary';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import ExpandLessIcon from '@mui/icons-material/ExpandLess';
export const requestQueuePromos = new RequestQueueWithPromise(20);

export function utf8ToBase64(inputString: string): string {
  // Encode the string as UTF-8
  const utf8String = encodeURIComponent(inputString).replace(
    /%([0-9A-F]{2})/g,
    (match, p1) => String.fromCharCode(Number('0x' + p1))
  );

  // Convert the UTF-8 encoded string to base64
  const base64String = btoa(utf8String);
  return base64String;
}

const uid = new ShortUniqueId({ length: 8 });

export function getGroupId(str) {
  const match = str.match(/group-(\d+)-/);
  return match ? match[1] : null;
}
const THIRTY_MINUTES = 30 * 60 * 1000; // 30 minutes in milliseconds
export const ListOfGroupPromotions = () => {
  const [popoverAnchor, setPopoverAnchor] = useState(null);
  const [openPopoverIndex, setOpenPopoverIndex] = useState(null);
  const [selectedGroup, setSelectedGroup] = useState(null);
  const [loading, setLoading] = useState(false);
  const [isShowModal, setIsShowModal] = useState(false);
  const [text, setText] = useState('');
  const [myGroupsWhereIAmAdmin, setMyGroupsWhereIAmAdmin] = useRecoilState(
    myGroupsWhereIAmAdminAtom
  );
  const [promotions, setPromotions] = useRecoilState(promotionsAtom);
  const [promotionTimeInterval, setPromotionTimeInterval] = useRecoilState(
    promotionTimeIntervalAtom
  );
  const [isExpanded, setIsExpanded] = React.useState(false);

  const [openSnack, setOpenSnack] = useState(false);
  const [infoSnack, setInfoSnack] = useState(null);
  const [fee, setFee] = useState(null);
  const [isLoadingJoinGroup, setIsLoadingJoinGroup] = useState(false);
  const [isLoadingPublish, setIsLoadingPublish] = useState(false);
  const { show, setTxList } = useContext(MyContext);

  const listRef = useRef();
  const rowVirtualizer = useVirtualizer({
    count: promotions.length,
    getItemKey: React.useCallback(
      (index) => promotions[index]?.identifier,
      [promotions]
    ),
    getScrollElement: () => listRef.current,
    estimateSize: () => 80, // Provide an estimated height of items, adjust this as needed
    overscan: 10, // Number of items to render outside the visible area to improve smoothness
  });

  useEffect(() => {
    try {
      (async () => {
        const feeRes = await getFee('ARBITRARY');
        setFee(feeRes?.fee);
      })();
    } catch (error) {
      console.log(error);
    }
  }, []);
  const getPromotions = useCallback(async () => {
    try {
      setPromotionTimeInterval(Date.now());
      const identifier = `group-promotions-ui24-`;
      const url = `${getBaseApiReact()}${getArbitraryEndpointReact()}?mode=ALL&service=DOCUMENT&identifier=${identifier}&limit=100&includemetadata=false&reverse=true&prefix=true`;
      const response = await fetch(url, {
        method: 'GET',
        headers: {
          'Content-Type': 'application/json',
        },
      });
      const responseData = await response.json();
      let data: any[] = [];
      const uniqueGroupIds = new Set();
      const oneWeekAgo = Date.now() - 7 * 24 * 60 * 60 * 1000;
      const getPromos = responseData?.map(async (promo: any) => {
        if (promo?.size < 200 && promo.created > oneWeekAgo) {
          const name = await requestQueuePromos.enqueue(async () => {
            const url = `${getBaseApiReact()}/arbitrary/${promo.service}/${
              promo.name
            }/${promo.identifier}`;
            const response = await fetch(url, {
              method: 'GET',
            });

            try {
              const responseData = await response.text();
              if (responseData) {
                const groupId = getGroupId(promo.identifier);

                // Check if this groupId has already been processed
                if (!uniqueGroupIds.has(groupId)) {
                  // Add the groupId to the set
                  uniqueGroupIds.add(groupId);

                  // Push the item to data
                  data.push({
                    data: responseData,
                    groupId,
                    ...promo,
                  });
                }
              }
            } catch (error) {
              console.error('Error fetching promo:', error);
            }
          });
        }

        return true;
      });

      await Promise.all(getPromos);
      const groupWithInfo = await getGroupNames(
        data.sort((a, b) => b.created - a.created)
      );
      setPromotions(groupWithInfo);
    } catch (error) {
      console.error(error);
    }
  }, []);

  useEffect(() => {
    const now = Date.now();

    const timeSinceLastFetch = now - promotionTimeInterval;
    const initialDelay =
      timeSinceLastFetch >= THIRTY_MINUTES
        ? 0
        : THIRTY_MINUTES - timeSinceLastFetch;
    const initialTimeout = setTimeout(() => {
      getPromotions();

      // Start a 30-minute interval
      const interval = setInterval(() => {
        getPromotions();
      }, THIRTY_MINUTES);

      return () => clearInterval(interval);
    }, initialDelay);

    return () => clearTimeout(initialTimeout);
  }, [getPromotions, promotionTimeInterval]);

  const handlePopoverOpen = (event, index) => {
    setPopoverAnchor(event.currentTarget);
    setOpenPopoverIndex(index);
  };

  const handlePopoverClose = () => {
    setPopoverAnchor(null);
    setOpenPopoverIndex(null);
  };
  const publishPromo = async () => {
    try {
      setIsLoadingPublish(true);

      const data = utf8ToBase64(text);
      const identifier = `group-promotions-ui24-group-${selectedGroup}-${uid.rnd()}`;

      await new Promise((res, rej) => {
        window
          .sendMessage('publishOnQDN', {
            data: data,
            identifier: identifier,
            service: 'DOCUMENT',
          })
          .then((response) => {
            if (!response?.error) {
              res(response);
              return;
            }
            rej(response.error);
          })
          .catch((error) => {
            rej(error.message || 'An error occurred');
          });
      }); // TODO translate
      setInfoSnack({
        type: 'success',
        message:
          'Successfully published promotion. It may take a couple of minutes for the promotion to appear',
      });
      setOpenSnack(true);
      setText('');
      setSelectedGroup(null);
      setIsShowModal(false);
    } catch (error) {
      setInfoSnack({
        type: 'error',
        message:
          error?.message || 'Error publishing the promotion. Please try again',
      });
      setOpenSnack(true);
    } finally {
      setIsLoadingPublish(false);
    }
  };

  const handleJoinGroup = async (group, isOpen) => {
    try {
      const groupId = group.groupId;
      const fee = await getFee('JOIN_GROUP');
      await show({
        message: 'Would you like to perform an JOIN_GROUP transaction?',
        publishFee: fee.fee + ' QORT',
      });
      setIsLoadingJoinGroup(true);
      await new Promise((res, rej) => {
        window
          .sendMessage('joinGroup', {
            groupId,
          })
          .then((response) => {
            if (!response?.error) {
              setInfoSnack({
                type: 'success',
                message:
                  'Successfully requested to join group. It may take a couple of minutes for the changes to propagate',
              });

              if (isOpen) {
                setTxList((prev) => [
                  {
                    ...response,
                    type: 'joined-group',
                    label: `Joined Group ${group?.groupName}: awaiting confirmation`,
                    labelDone: `Joined Group ${group?.groupName}: success!`,
                    done: false,
                    groupId,
                  },
                  ...prev,
                ]);
              } else {
                setTxList((prev) => [
                  {
                    ...response,
                    type: 'joined-group-request',
                    label: `Requested to join Group ${group?.groupName}: awaiting confirmation`,
                    labelDone: `Requested to join Group ${group?.groupName}: success!`,
                    done: false,
                    groupId,
                  },
                  ...prev,
                ]);
              }

              setOpenSnack(true);
              handlePopoverClose();
              res(response);
              return;
            } else {
              setInfoSnack({
                type: 'error',
                message: response?.error,
              });
              setOpenSnack(true);
              rej(response.error);
            }
          })
          .catch((error) => {
            setInfoSnack({
              type: 'error',
              message: error.message || 'An error occurred',
            });
            setOpenSnack(true);
            rej(error);
          });
      });
      setIsLoadingJoinGroup(false);
    } catch (error) {
    } finally {
      setIsLoadingJoinGroup(false);
    }
  };

  return (
    <Box
      sx={{
        width: '100%',
        display: 'flex',
        marginTop: '20px',
        flexDirection: 'column',
        alignItems: 'center',
        justifyContent: 'center',
      }}
    >
      <Box
        sx={{
          display: 'flex',
          gap: '20px',
          width: '100%',
          justifyContent: 'space-between',
        }}
      >
        <ButtonBase
          sx={{
            display: 'flex',
            flexDirection: 'row',
            padding: `0px ${isExpanded ? '24px' : '20px'}`,
            gap: '10px',
            justifyContent: 'flex-start',
            alignSelf: isExpanded && 'flex-start',
          }}
          onClick={() => setIsExpanded((prev) => !prev)}
        >
          <Typography
            sx={{
              fontSize: '1rem',
            }}
          >
            Group promotions{' '}
            {promotions.length > 0 && ` (${promotions.length})`}
          </Typography>
          {isExpanded ? (
            <ExpandLessIcon
              sx={{
                marginLeft: 'auto',
              }}
            />
          ) : (
            <ExpandMoreIcon
              sx={{
                marginLeft: 'auto',
              }}
            />
          )}
        </ButtonBase>

        <Box
          style={{
            width: '330px',
          }}
        />
      </Box>

      <Collapse in={isExpanded} timeout="auto" unmountOnExit>
        <>
          <Box
            sx={{
              width: '750px',
              maxWidth: '90%',
              display: 'flex',
              flexDirection: 'column',
              padding: '0px 20px',
            }}
          >
            <Box
              sx={{
                width: '100%',
                display: 'flex',
                justifyContent: 'space-between',
                alignItems: 'center',
              }}
            >
              <Typography
                sx={{
                  fontSize: '13px',
                  fontWeight: 600,
                }}
              ></Typography>

              <Button
                variant="contained"
                onClick={() => setIsShowModal(true)}
                sx={{
                  fontSize: '12px',
                }}
              >
                Add Promotion
              </Button>
            </Box>

            <Spacer height="10px" />
          </Box>
          <Box
            sx={{
              bgcolor: 'background.paper',
              borderRadius: '19px',
              display: 'flex',
              flexDirection: 'column',
              maxHeight: '700px',
              maxWidth: '90%',
              padding: '20px 0px',
              width: '750px',
            }}
          >
            {loading && promotions.length === 0 && (
              <Box
                sx={{
                  width: '100%',
                  display: 'flex',
                  justifyContent: 'center',
                }}
              >
                <CustomLoader />
              </Box>
            )}
            {!loading && promotions.length === 0 && (
              <Box
                sx={{
                  width: '100%',
                  display: 'flex',
                  justifyContent: 'center',
                  alignItems: 'center',
                  height: '100%',
                }}
              >
                <Typography
                  sx={{
                    fontSize: '11px',
                    fontWeight: 400,
                    color: 'rgba(255, 255, 255, 0.2)',
                  }}
                >
                  Nothing to display
                </Typography>
              </Box>
            )}
            <div
              style={{
                height: '600px',
                position: 'relative',
                display: 'flex',
                flexDirection: 'column',
                width: '100%',
              }}
            >
              <div
                ref={listRef}
                className="scrollable-container"
                style={{
                  flexGrow: 1,
                  overflow: 'auto',
                  position: 'relative',
                  display: 'flex',
                  height: '0px',
                }}
              >
                <div
                  style={{
                    height: rowVirtualizer.getTotalSize(),
                    width: '100%',
                  }}
                >
                  <div
                    style={{
                      position: 'absolute',
                      top: 0,
                      left: 0,
                      width: '100%',
                    }}
                  >
                    {rowVirtualizer.getVirtualItems().map((virtualRow) => {
                      const index = virtualRow.index;
                      const promotion = promotions[index];
                      return (
                        <div
                          data-index={virtualRow.index} //needed for dynamic row height measurement
                          ref={rowVirtualizer.measureElement} //measure dynamic row height
                          key={promotion?.identifier}
                          style={{
                            position: 'absolute',
                            top: 0,
                            left: '50%', // Move to the center horizontally
                            transform: `translateY(${virtualRow.start}px) translateX(-50%)`, // Adjust for centering
                            width: '100%', // Control width (90% of the parent)
                            padding: '10px 0',
                            display: 'flex',
                            alignItems: 'center',
                            overscrollBehavior: 'none',
                            flexDirection: 'column',
                            gap: '5px',
                          }}
                        >
                          <ErrorBoundary
                            fallback={
                              <Typography>
                                Error loading content: Invalid Data
                              </Typography>
                            }
                          >
                            <Box
                              sx={{
                                display: 'flex',
                                flexDirection: 'column',
                                width: '100%',
                                padding: '0px 20px',
                              }}
                            >
                              <Popover
                                open={openPopoverIndex === promotion?.groupId}
                                anchorEl={popoverAnchor}
                                onClose={(event, reason) => {
                                  if (reason === 'backdropClick') {
                                    // Prevent closing on backdrop click
                                    return;
                                  }
                                  handlePopoverClose(); // Close only on other events like Esc key press
                                }}
                                anchorOrigin={{
                                  vertical: 'top',
                                  horizontal: 'center',
                                }}
                                transformOrigin={{
                                  vertical: 'bottom',
                                  horizontal: 'center',
                                }}
                                style={{ marginTop: '8px' }}
                              >
                                <Box
                                  sx={{
                                    width: '325px',
                                    height: 'auto',
                                    maxHeight: '400px',
                                    display: 'flex',
                                    flexDirection: 'column',
                                    alignItems: 'center',
                                    gap: '10px',
                                    padding: '10px',
                                  }}
                                >
                                  <Typography
                                    sx={{
                                      fontSize: '13px',
                                      fontWeight: 600,
                                    }}
                                  >
                                    Group name: {` ${promotion?.groupName}`}
                                  </Typography>

                                  <Typography
                                    sx={{
                                      fontSize: '13px',
                                      fontWeight: 600,
                                    }}
                                  >
                                    Number of members:{' '}
                                    {` ${promotion?.memberCount}`}
                                  </Typography>

                                  {promotion?.description && (
                                    <Typography
                                      sx={{
                                        fontSize: '13px',
                                        fontWeight: 600,
                                      }}
                                    >
                                      {promotion?.description}
                                    </Typography>
                                  )}

                                  {promotion?.isOpen === false && (
                                    <Typography
                                      sx={{
                                        fontSize: '13px',
                                        fontWeight: 600,
                                      }}
                                    >
                                      *This is a closed/private group, so you
                                      will need to wait until an admin accepts
                                      your request
                                    </Typography>
                                  )}

                                  <Spacer height="5px" />

                                  <Box
                                    sx={{
                                      display: 'flex',
                                      gap: '20px',
                                      alignItems: 'center',
                                      width: '100%',
                                      justifyContent: 'center',
                                    }}
                                  >
                                    <LoadingButton
                                      loading={isLoadingJoinGroup}
                                      loadingPosition="start"
                                      variant="contained"
                                      onClick={handlePopoverClose}
                                    >
                                      Close
                                    </LoadingButton>

                                    <LoadingButton
                                      loading={isLoadingJoinGroup}
                                      loadingPosition="start"
                                      variant="contained"
                                      onClick={() =>
                                        handleJoinGroup(
                                          promotion,
                                          promotion?.isOpen
                                        )
                                      }
                                    >
                                      Join
                                    </LoadingButton>
                                  </Box>
                                </Box>
                              </Popover>

                              <Box
                                sx={{
                                  display: 'flex',
                                  alignItems: 'center',
                                  justifyContent: 'space-between',
                                  width: '100%',
                                }}
                              >
                                <Box
                                  sx={{
                                    display: 'flex',
                                    alignItems: 'center',
                                    gap: '15px',
                                  }}
                                >
                                  <Avatar
                                    sx={{
                                      backgroundColor: '#27282c',
                                      color: 'white',
                                    }}
                                    alt={promotion?.name}
                                    src={`${getBaseApiReact()}/arbitrary/THUMBNAIL/${
                                      promotion?.name
                                    }/qortal_avatar?async=true`}
                                  >
                                    {promotion?.name?.charAt(0)}
                                  </Avatar>

                                  <Typography
                                    sx={{
                                      fontWight: 600,
                                      fontFamily: 'Inter',
                                      color: 'cadetBlue',
                                    }}
                                  >
                                    {promotion?.name}
                                  </Typography>
                                </Box>

                                <Typography
                                  sx={{
                                    fontWight: 600,
                                    fontFamily: 'Inter',
                                    color: 'cadetBlue',
                                  }}
                                >
                                  {promotion?.groupName}
                                </Typography>
                              </Box>

                              <Spacer height="20px" />

                              <Box
                                sx={{
                                  display: 'flex',
                                  gap: '20px',
                                  alignItems: 'center',
                                }}
                              >
                                {promotion?.isOpen === false && (
                                  <LockIcon
                                    sx={{
                                      color: 'var(--green)',
                                    }}
                                  />
                                )}
                                {promotion?.isOpen === true && (
                                  <NoEncryptionGmailerrorredIcon
                                    sx={{
                                      color: 'var(--danger)',
                                    }}
                                  />
                                )}
                                <Typography
                                  sx={{
                                    fontSize: '15px',
                                    fontWeight: 600,
                                  }}
                                >
                                  {promotion?.isOpen
                                    ? 'Public group'
                                    : 'Private group'}
                                </Typography>
                              </Box>

                              <Spacer height="20px" />

                              <Typography
                                sx={{
                                  fontWight: 600,
                                  fontFamily: 'Inter',
                                  color: 'cadetBlue',
                                }}
                              >
                                {promotion?.data}
                              </Typography>

                              <Spacer height="20px" />

                              <Box
                                sx={{
                                  display: 'flex',
                                  justifyContent: 'center',
                                  width: '100%',
                                }}
                              >
                                <Button
                                  // variant="contained"
                                  onClick={(event) =>
                                    handlePopoverOpen(event, promotion?.groupId)
                                  }
                                  sx={{
                                    fontSize: '12px',
                                    color: 'white',
                                  }}
                                >
                                  Join Group: {` ${promotion?.groupName}`}
                                </Button>
                              </Box>
                            </Box>

                            <Spacer height="50px" />
                          </ErrorBoundary>
                        </div>
                      );
                    })}
                  </div>
                </div>
              </div>
            </div>
          </Box>
        </>
      </Collapse>

      <Spacer height="20px" />

      {isShowModal && (
        <Dialog
          open={isShowModal}
          aria-labelledby="alert-dialog-title"
          aria-describedby="alert-dialog-description"
        >
          <DialogTitle id="alert-dialog-title">
            {'Promote your group to non-members'}
          </DialogTitle>
          <DialogContent>
            <DialogContentText id="alert-dialog-description">
              Only the latest promotion from the week will be shown for your
              group.
            </DialogContentText>
            <DialogContentText id="alert-dialog-description2">
              Max 200 characters. Publish Fee: {fee && fee} {' QORT'}
            </DialogContentText>
            <Spacer height="20px" />
            <Box
              sx={{
                display: 'flex',
                flexDirection: 'column',
                gap: '5px',
              }}
            >
              <Label>Select a group</Label>
              <Label>Only groups where you are an admin will be shown</Label>
              <Select
                labelId="demo-simple-select-label"
                id="demo-simple-select"
                value={selectedGroup}
                label="Groups where you are an admin"
                onChange={(e) => setSelectedGroup(e.target.value)}
                variant="outlined"
              >
                {myGroupsWhereIAmAdmin?.map((group) => {
                  return (
                    <MenuItem key={group?.groupId} value={group?.groupId}>
                      {group?.groupName}
                    </MenuItem>
                  );
                })}
              </Select>
            </Box>
            <Spacer height="20px" />
            <TextField
              label="Promotion text"
              variant="filled"
              fullWidth
              value={text}
              onChange={(e) => setText(e.target.value)}
              inputProps={{
                maxLength: 200,
              }}
              multiline={true}
              sx={{
                '& .MuiFormLabel-root': {
                  color: 'white',
                },
                '& .MuiFormLabel-root.Mui-focused': {
                  color: 'white',
                },
              }}
            />
          </DialogContent>
          <DialogActions>
            <Button
              disabled={isLoadingPublish}
              variant="contained"
              onClick={() => setIsShowModal(false)}
            >
              Close
            </Button>
            <Button
              disabled={!text.trim() || !selectedGroup || isLoadingPublish}
              variant="contained"
              onClick={publishPromo}
              autoFocus
            >
              Publish
            </Button>
          </DialogActions>
        </Dialog>
      )}
      <CustomizedSnackbars
        open={openSnack}
        setOpen={setOpenSnack}
        info={infoSnack}
        setInfo={setInfoSnack}
      />
    </Box>
  );
};