import { useEffect, useRef, useState } from "react";
import { useSWRConfig } from "swr";
import { Virtuoso } from "react-virtuoso";
import {
  Box,
  Collapse,
  Divider,
  IconButton,
  List,
  ListItem,
  ListItemText,
} from "@mui/material";
import {
  SendRounded,
  ExpandLessRounded,
  ExpandMoreRounded,
  MyLocationRounded,
  NetworkCheckRounded,
} from "@mui/icons-material";
import { ApiType } from "../../services/types";
import { updateProxy } from "../../services/api";
import { getProfiles, patchProfile } from "../../services/cmds";
import delayManager from "../../services/delay";
import ProxyItem from "./proxy-item";

interface Props {
  group: ApiType.ProxyGroupItem;
}

const ProxyGroup = ({ group }: Props) => {
  const { mutate } = useSWRConfig();
  const [open, setOpen] = useState(false);
  const [now, setNow] = useState(group.now);

  const virtuosoRef = useRef<any>();
  const proxies = group.all ?? [];

  const selectLockRef = useRef(false);
  const onSelect = async (name: string) => {
    // Todo: support another proxy group type
    if (group.type !== "Selector") return;

    if (selectLockRef.current) return;
    selectLockRef.current = true;

    const oldValue = now;
    try {
      setNow(name);
      await updateProxy(group.name, name);
    } catch {
      setNow(oldValue);
      return; // do not update profile
    } finally {
      selectLockRef.current = false;
    }

    try {
      const profiles = await getProfiles();
      const profile = profiles.items![profiles.current!]!;
      if (!profile) return;
      if (!profile.selected) profile.selected = [];

      const index = profile.selected.findIndex(
        (item) => item.name === group.name
      );

      if (index < 0) {
        profile.selected.push({ name: group.name, now: name });
      } else {
        profile.selected[index] = { name: group.name, now: name };
      }
      await patchProfile(profiles.current!, profile);
    } catch (err) {
      console.error(err);
    }
  };

  const onLocation = (smooth = true) => {
    const index = proxies.findIndex((p) => p.name === now);

    if (index >= 0) {
      virtuosoRef.current?.scrollToIndex?.({
        index,
        align: "center",
        behavior: smooth ? "smooth" : "auto",
      });
    }
  };

  const checkLockRef = useRef(false);
  const onCheckAll = async () => {
    if (checkLockRef.current) return;
    checkLockRef.current = true;

    // rerender quickly
    if (proxies.length) setTimeout(() => mutate("getProxies"), 500);

    let names = proxies.map((p) => p.name);
    while (names.length) {
      const list = names.slice(0, 8);
      names = names.slice(8);

      await Promise.all(
        list.map((n) => delayManager.checkDelay(n, group.name))
      );

      mutate("getProxies");
    }

    checkLockRef.current = false;
  };

  // auto scroll to current index
  useEffect(() => {
    if (open) {
      setTimeout(() => onLocation(false), 5);
    }
  }, [open]);

  return (
    <>
      <ListItem button onClick={() => setOpen(!open)} dense>
        <ListItemText
          primary={group.name}
          secondary={
            <>
              <SendRounded color="primary" sx={{ mr: 1, fontSize: 14 }} />
              <span>{now}</span>
            </>
          }
          secondaryTypographyProps={{
            sx: { display: "flex", alignItems: "center" },
          }}
        />

        {open ? <ExpandLessRounded /> : <ExpandMoreRounded />}
      </ListItem>

      <Collapse in={open} timeout="auto" unmountOnExit>
        <Box sx={{ pl: 4, pr: 3, my: 0.5 }}>
          <IconButton
            size="small"
            title="location"
            onClick={() => onLocation(true)}
          >
            <MyLocationRounded />
          </IconButton>
          <IconButton size="small" title="check" onClick={onCheckAll}>
            <NetworkCheckRounded />
          </IconButton>
        </Box>

        {proxies.length >= 10 ? (
          <Virtuoso
            ref={virtuosoRef}
            style={{ height: "320px", marginBottom: "4px" }}
            totalCount={proxies.length}
            itemContent={(index) => (
              <ProxyItem
                groupName={group.name}
                proxy={proxies[index]}
                selected={proxies[index].name === now}
                sx={{ py: 0, pl: 4 }}
                onClick={onSelect}
              />
            )}
          />
        ) : (
          <List
            component="div"
            disablePadding
            sx={{ maxHeight: "320px", overflow: "auto", mb: "4px" }}
          >
            {proxies.map((proxy) => (
              <ProxyItem
                key={proxy.name}
                groupName={group.name}
                proxy={proxy}
                selected={proxy.name === now}
                sx={{ py: 0, pl: 4 }}
                onClick={onSelect}
              />
            ))}
          </List>
        )}

        <Divider variant="middle" />
      </Collapse>
    </>
  );
};

export default ProxyGroup;