import {
  AboutAptosConnect,
  type AboutAptosConnectEducationScreen,
  type AdapterNotDetectedWallet,
  type AdapterWallet,
  AptosPrivacyPolicy,
  groupAndSortWallets,
  isInstallRequired,
  useWallet,
  WalletItem,
  type WalletSortingOptions,
} from "@aptos-labs/wallet-adapter-react";
// reported bug with loading mui icons with esm, therefore need to import like this https://github.com/mui/material-ui/issues/35233
import {
  ArrowBack,
  ArrowForward,
  Close as CloseIcon,
  ExpandMore,
  LanOutlined as LanOutlinedIcon,
} from "@mui/icons-material";
import {
  Box,
  Button,
  Collapse,
  Dialog,
  Divider,
  IconButton,
  ListItem,
  ListItemText,
  Stack,
  Tab,
  Tabs,
  Typography,
  useTheme,
} from "@mui/material";
import { type SyntheticEvent, useState } from "react";
import { grey } from "./aptosColorPalette";
import type { WalletConnectorProps } from "./types";

interface WalletsModalProps
  extends Pick<WalletConnectorProps, "networkSupport" | "modalMaxWidth">,
    WalletSortingOptions {
  handleClose: () => void;
  modalOpen: boolean;
  // Make crossChainWallets optional - if not provided, shows single list
  crossChainWallets?: {
    evm: boolean;
    solana: boolean;
  };
}

export default function WalletsModal({
  handleClose,
  modalOpen,
  networkSupport,
  modalMaxWidth,
  crossChainWallets,
  ...walletSortingOptions
}: WalletsModalProps): JSX.Element {
  const theme = useTheme();
  const [expanded, setExpanded] = useState(false);
  const [tabValue, setTabValue] = useState<number>(0);

  const handleTabChange = (_event: SyntheticEvent, newValue: number) => {
    setTabValue(newValue);
  };

  const { wallets = [], notDetectedWallets = [] } = useWallet();

  const { aptosConnectWallets, availableWallets, installableWallets } =
    groupAndSortWallets(
      [...wallets, ...notDetectedWallets],
      walletSortingOptions,
    );

  const hasAptosConnectWallets = !!aptosConnectWallets.length;

  // Determine if we should show tabs (cross-chain mode)
  const crossChainMode =
    crossChainWallets && (crossChainWallets.evm || crossChainWallets.solana);

  // Group wallets by chain if in cross-chain mode
  const { evmWallets, solanaWallets, aptosWallets } = crossChainMode
    ? availableWallets.reduce<{
        evmWallets: AdapterWallet[];
        solanaWallets: AdapterWallet[];
        aptosWallets: AdapterWallet[];
      }>(
        (acc, wallet) => {
          if (wallet.name.includes("Ethereum")) {
            acc.evmWallets.push(wallet);
          } else if (wallet.name.includes("Solana")) {
            acc.solanaWallets.push(wallet);
          } else {
            acc.aptosWallets.push(wallet);
          }
          return acc;
        },
        { evmWallets: [], solanaWallets: [], aptosWallets: [] },
      )
    : { evmWallets: [], solanaWallets: [], aptosWallets: availableWallets };

  const {
    evmInstallableWallets,
    solanaInstallableWallets,
    aptosInstallableWallets,
  } = crossChainMode
    ? installableWallets.reduce<{
        evmInstallableWallets: AdapterNotDetectedWallet[];
        solanaInstallableWallets: AdapterNotDetectedWallet[];
        aptosInstallableWallets: AdapterNotDetectedWallet[];
      }>(
        (acc, wallet) => {
          if (wallet.name.includes("Ethereum")) {
            acc.evmInstallableWallets.push(wallet);
          } else if (wallet.name.includes("Solana")) {
            acc.solanaInstallableWallets.push(wallet);
          } else {
            acc.aptosInstallableWallets.push(wallet);
          }
          return acc;
        },
        {
          evmInstallableWallets: [],
          solanaInstallableWallets: [],
          aptosInstallableWallets: [],
        },
      )
    : {
        evmInstallableWallets: [],
        solanaInstallableWallets: [],
        aptosInstallableWallets: installableWallets,
      };

  // Calculate dynamic indices for tabs
  const tabsConfig = crossChainMode
    ? [
        { key: "aptos", label: "Aptos", enabled: true },
        { key: "solana", label: "Solana", enabled: crossChainWallets!.solana },
        { key: "evm", label: "Ethereum", enabled: crossChainWallets!.evm },
      ].filter((tab) => tab.enabled)
    : [];

  const getTabIndex = (key: string) =>
    tabsConfig.findIndex((tab) => tab.key === key);

  // Render wallet list for a specific chain
  const renderWalletList = (
    wallets: AdapterWallet[],
    installableWallets: AdapterNotDetectedWallet[],
  ) => (
    <>
      {wallets.map((wallet) => (
        <WalletRow key={wallet.name} wallet={wallet} onConnect={handleClose} />
      ))}
      {!!installableWallets.length && (
        <>
          <Button
            variant="text"
            size="small"
            onClick={() => setExpanded((prev) => !prev)}
            endIcon={<ExpandMore sx={{ height: "20px", width: "20px" }} />}
          >
            More Wallets
          </Button>
          <Collapse in={expanded} timeout="auto" unmountOnExit>
            <Stack sx={{ gap: 1 }}>
              {installableWallets.map((wallet) => (
                <WalletRow
                  key={wallet.name}
                  wallet={wallet}
                  onConnect={handleClose}
                />
              ))}
            </Stack>
          </Collapse>
        </>
      )}
    </>
  );

  return (
    <Dialog
      open={modalOpen}
      onClose={handleClose}
      aria-label="wallet selector modal"
      sx={{ borderRadius: `${theme.shape.borderRadius}px` }}
      maxWidth={modalMaxWidth ?? "xs"}
      fullWidth
    >
      <Stack
        sx={{
          top: "50%",
          left: "50%",
          bgcolor: "background.paper",
          boxShadow: 24,
          p: 3,
          gap: 2,
        }}
      >
        <IconButton
          onClick={handleClose}
          sx={{
            position: "absolute",
            right: 12,
            top: 12,
            color: grey[450],
          }}
        >
          <CloseIcon />
        </IconButton>

        <AboutAptosConnect renderEducationScreen={renderEducationScreen}>
          <Typography
            align="center"
            variant="h5"
            component="h2"
            pt={2}
            sx={{
              display: "flex",
              flexDirection: "column",
            }}
          >
            {hasAptosConnectWallets ? (
              <>
                <span>Log in or sign up</span>
                <span>with Social + Petra Web</span>
              </>
            ) : (
              "Connect Wallet"
            )}
          </Typography>

          {networkSupport && (
            <Box
              sx={{
                display: "flex",
                gap: 0.5,
                alignItems: "center",
                justifyContent: "center",
              }}
            >
              <LanOutlinedIcon
                sx={{
                  fontSize: "0.9rem",
                  color: grey[400],
                }}
              />
              <Typography
                sx={{
                  display: "inline-flex",
                  fontSize: "0.9rem",
                  color: grey[400],
                }}
                align="center"
              >
                {networkSupport} only
              </Typography>
            </Box>
          )}

          {hasAptosConnectWallets && (
            <Stack gap={1}>
              {aptosConnectWallets.map((wallet) => (
                <AptosConnectWalletRow
                  key={wallet.name}
                  wallet={wallet}
                  onConnect={handleClose}
                />
              ))}
              <Typography
                component="p"
                fontSize="14px"
                sx={{
                  display: "flex",
                  gap: 0.5,
                  justifyContent: "center",
                  alignItems: "center",
                  color: grey[400],
                }}
              >
                Learn more about{" "}
                <Box
                  component={AboutAptosConnect.Trigger}
                  sx={{
                    background: "none",
                    border: "none",
                    fontFamily: "inherit",
                    fontSize: "inherit",
                    cursor: "pointer",
                    display: "flex",
                    gap: 0.5,
                    px: 0,
                    py: 1.5,
                    alignItems: "center",
                    color: theme.palette.text.primary,
                    appearance: "none",
                  }}
                >
                  Petra Web <ArrowForward sx={{ height: 16, width: 16 }} />
                </Box>
              </Typography>

              <Stack
                component={AptosPrivacyPolicy}
                alignItems="center"
                py={0.5}
              >
                <Typography component="p" fontSize="12px" lineHeight="20px">
                  <AptosPrivacyPolicy.Disclaimer />{" "}
                  <Box
                    component={AptosPrivacyPolicy.Link}
                    sx={{
                      color: grey[400],
                      textDecoration: "underline",
                      textUnderlineOffset: "4px",
                    }}
                  />
                  <span>.</span>
                </Typography>
                <Box
                  component={AptosPrivacyPolicy.PoweredBy}
                  sx={{
                    display: "flex",
                    alignItems: "center",
                    gap: 0.75,
                    fontSize: "12px",
                    lineHeight: "20px",
                    color: grey[400],
                  }}
                />
              </Stack>
              <Divider sx={{ color: grey[400], pt: 2 }}>Or</Divider>
            </Stack>
          )}

          {/* Conditional rendering: Tabs for cross-chain, simple list for single-chain */}
          {crossChainMode ? (
            <>
              <Tabs
                value={tabValue}
                onChange={handleTabChange}
                textColor="secondary"
                indicatorColor="secondary"
                variant="fullWidth"
                aria-label="cross chain wallets tabs"
              >
                {tabsConfig.map((tab, index) => (
                  <Tab key={tab.key} label={tab.label} {...a11yProps(index)} />
                ))}
              </Tabs>

              <TabPanel value={tabValue} index={getTabIndex("aptos")}>
                {renderWalletList(aptosWallets, aptosInstallableWallets)}
              </TabPanel>

              {crossChainWallets!.solana && (
                <TabPanel value={tabValue} index={getTabIndex("solana")}>
                  {renderWalletList(solanaWallets, solanaInstallableWallets)}
                </TabPanel>
              )}

              {crossChainWallets!.evm && (
                <TabPanel value={tabValue} index={getTabIndex("evm")}>
                  {renderWalletList(evmWallets, evmInstallableWallets)}
                </TabPanel>
              )}
            </>
          ) : (
            // Simple list mode (original WalletModel behavior)
            <Stack sx={{ gap: 1 }}>
              {renderWalletList(availableWallets, installableWallets)}
            </Stack>
          )}
        </AboutAptosConnect>
      </Stack>
    </Dialog>
  );
}

interface WalletRowProps {
  wallet: AdapterWallet | AdapterNotDetectedWallet;
  onConnect?: () => void;
}

function WalletRow({ wallet, onConnect }: WalletRowProps) {
  const theme = useTheme();
  return (
    <WalletItem wallet={wallet} onConnect={onConnect} asChild>
      <ListItem disablePadding>
        <Box
          sx={{
            display: "flex",
            alignItems: "center",
            width: "100%",
            px: 2,
            py: 1.5,
            gap: 2,
            border: "solid 1px",
            borderColor: theme.palette.mode === "dark" ? grey[700] : grey[200],
            borderRadius: `${theme.shape.borderRadius}px`,
          }}
        >
          <Box component={WalletItem.Icon} sx={{ width: 32, height: 32 }} />
          <ListItemText
            primary={wallet.name}
            primaryTypographyProps={{ fontSize: "1.125rem" }}
          />
          {isInstallRequired(wallet) ? (
            <WalletItem.InstallLink asChild>
              <Button
                LinkComponent={"a"}
                size="small"
                className="wallet-connect-install"
              >
                Install
              </Button>
            </WalletItem.InstallLink>
          ) : (
            <WalletItem.ConnectButton asChild>
              <Button
                variant="contained"
                size="small"
                className="wallet-connect-button"
              >
                Connect
              </Button>
            </WalletItem.ConnectButton>
          )}
        </Box>
      </ListItem>
    </WalletItem>
  );
}

function AptosConnectWalletRow({ wallet, onConnect }: WalletRowProps) {
  return (
    <WalletItem wallet={wallet} onConnect={onConnect} asChild>
      <WalletItem.ConnectButton asChild>
        <Button
          size="large"
          variant="outlined"
          sx={{ display: "flex", alignItems: "center", gap: 1.5 }}
        >
          <Box component={WalletItem.Icon} sx={{ width: 20, height: 20 }} />
          <WalletItem.Name />
        </Button>
      </WalletItem.ConnectButton>
    </WalletItem>
  );
}

function renderEducationScreen(screen: AboutAptosConnectEducationScreen) {
  return (
    <>
      <Box
        sx={{
          display: "grid",
          gridTemplateColumns: "1fr 4fr 1fr",
          alignItems: "center",
          justifyItems: "start",
        }}
      >
        <IconButton onClick={screen.cancel}>
          <ArrowBack />
        </IconButton>
        <Typography variant="body1" component="h2" width="100%" align="center">
          About Petra Web
        </Typography>
      </Box>

      <Box
        sx={{
          display: "flex",
          pb: 1.5,
          alignItems: "end",
          justifyContent: "center",
          height: "162px",
        }}
      >
        <screen.Graphic />
      </Box>
      <Stack sx={{ gap: 1, textAlign: "center", pb: 2 }}>
        <Typography component={screen.Title} variant="h6" />
        <Typography
          component={screen.Description}
          variant="body2"
          color={(theme) => theme.palette.text.secondary}
          sx={{
            "&>a": {
              color: (theme) => theme.palette.text.primary,
              textDecoration: "underline",
              textUnderlineOffset: "4px",
            },
          }}
        />
      </Stack>

      <Box
        sx={{
          display: "grid",
          gridTemplateColumns: "repeat(3, minmax(0, 1fr))",
          alignItems: "center",
        }}
      >
        <Button
          size="small"
          variant="text"
          onClick={screen.back}
          sx={{ justifySelf: "start" }}
        >
          Back
        </Button>
        <Box
          sx={{
            display: "flex",
            alignItems: "center",
            gap: 1,
            placeSelf: "center",
          }}
        >
          {screen.screenIndicators.map((ScreenIndicator, i) => (
            <Box
              key={i}
              component={ScreenIndicator}
              sx={{
                px: 0,
                py: 2,
                background: "none",
                border: "none",
                cursor: "pointer",
              }}
            >
              <Box
                sx={{
                  height: "2px",
                  width: "24px",
                  bgcolor: (theme) => theme.palette.text.disabled,
                  "[data-active]>&": {
                    bgcolor: (theme) => theme.palette.text.primary,
                  },
                }}
              />
            </Box>
          ))}
        </Box>
        <Button
          size="small"
          variant="text"
          onClick={screen.next}
          sx={{ justifySelf: "end" }}
          endIcon={<ArrowForward sx={{ height: 16, width: 16 }} />}
        >
          {screen.screenIndex === screen.totalScreens - 1 ? "Finish" : "Next"}
        </Button>
      </Box>
    </>
  );
}

interface TabPanelProps {
  children?: React.ReactNode;
  index: number;
  value: number;
}

function TabPanel(props: TabPanelProps) {
  const { children, value, index, ...other } = props;

  return (
    <div
      role="tabpanel"
      hidden={value !== index}
      id={`simple-tabpanel-${index}`}
      aria-labelledby={`simple-tab-${index}`}
      {...other}
    >
      {value === index && <Stack sx={{ gap: 1 }}>{children}</Stack>}
    </div>
  );
}

function a11yProps(index: number) {
  return {
    id: `simple-tab-${index}`,
    "aria-controls": `simple-tabpanel-${index}`,
  };
}
