import * as React from "react";
import Box from "@mui/material/Box";
import Grid, { Grid2Props } from "@mui/material/Unstable_Grid2"; // Grid version 2
import { styled } from "@mui/material/styles";
import FormGroup from "@mui/material/FormGroup";
import FormControlLabel from "@mui/material/FormControlLabel";
import Switch, { SwitchProps } from "@mui/material/Switch";
import Stack from "@mui/material/Stack";
import Typography from "@mui/material/Typography";
import { SnackbarProvider, VariantType, useSnackbar } from "notistack";

import CodeBlock from "@/components/CodeBlock";
import TableSchemaButton from "@/components/Button/TableSchemaButton";
import SQLCard, {
  SQLStatusCard,
  SQLResultPreviewCard,
  SQLExecutionPlanCard,
} from "@/components/Card/SQLCard";
import { IndexTip } from "@/components/Status/SQLStatus";
import type { SQLResult as SQLResultType } from "@/pages/api/sql/run";
import { executeSql, executeSqlByCollection } from "@/utils";
import { API_QUERY_COLLECTION } from "@/constants/api";
import { useSession } from "@/utils/hook";
import { ExplainEngines } from "@/components/CodeBlock/SQLDiff";

export interface SQLProps {
  sql: string;
  alternativeSql?: string;
  switchBtnLabel?: string;
  defaultChecked?: boolean;
  hideStatus?: boolean;
  showExecutionPlan?: boolean;
  disableRun?: boolean;
  option?: {
    collection: keyof typeof API_QUERY_COLLECTION;
    // name: keyof typeof API_QUERY_COLLECTION[keyof typeof API_QUERY_COLLECTION];
    name: string;
  };
}

export const commonGridContainerProps: Grid2Props = {
  spacing: 2,
  minWidth: "600px",
  sx: {
    mb: (theme) => theme.spacing(2),
  },
};

// TODO refactor this with SQLDiff
export default function SQL(props: SQLProps) {
  const {
    sql,
    alternativeSql,
    switchBtnLabel,
    defaultChecked,
    hideStatus,
    showExecutionPlan,
    disableRun,
    option,
  } = props;
  const [sqlResult, setsqlResult] = React.useState<SQLResultType | null>(null);
  const [sqlLoading, setsqlLoading] = React.useState(false);
  const [checked, setChecked] = React.useState(!!defaultChecked);
  const [errorMsg, setErrorMsg] = React.useState("");

  const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setChecked(event.target.checked);
  };

  const { enqueueSnackbar } = useSnackbar();

  const handleSql1Click = async () => {
    setsqlLoading(true);
    setsqlResult(null);
    setErrorMsg("");
    try {
      if (option) {
        const data = await executeSqlByCollection(
          option.collection,
          option.name
        );
        setsqlResult(data);
        return;
      }
      const data = await executeSql(checked ? (alternativeSql as string) : sql);
      setsqlResult(data);
    } catch (error: any) {
      console.error(error);
      setErrorMsg(`${error?.message} ${error?.sqlMessage}`);
      enqueueSnackbar(`${error?.message}`, {
        variant: "error",
      });
    } finally {
      setsqlLoading(false);
    }
  };

  return (
    <>
      <Grid container {...commonGridContainerProps}>
        {alternativeSql && (
          <Grid xs={12}>
            <FormControlLabel
              control={
                <IOSSwitch
                  sx={{ m: 1 }}
                  checked={checked}
                  onChange={handleChange}
                />
              }
              label={
                switchBtnLabel &&
                (checked ? `${switchBtnLabel} ON` : `${switchBtnLabel} OFF`)
              }
            />
          </Grid>
        )}

        <Grid xs={12}>
          <SQLCard
            disableRun={disableRun}
            sql={checked ? (alternativeSql as string) : sql?.trim()}
            onClick={handleSql1Click}
            loading={sqlLoading}
            errorMsg={errorMsg}
          />
        </Grid>

        {!hideStatus && (
          <Grid xs={12}>
            {sqlResult?.plan && (
              <SQLStatusCard
                status={[
                  {
                    status: "success",
                    label: "Processed",
                    content: `${sqlResult.plan.maxRowsScanned.toLocaleString()} rows`,
                  },
                  {
                    status: "success",
                    label: "Elapsed",
                    content: sqlResult.plan.databaseCostTime,
                  },
                  {
                    status: "success",
                    label: "Engines",
                    content: (
                      <ExplainEngines engines={sqlResult.plan.usedEngines} />
                    ),
                    hidden: sqlResult.plan.usedEngines?.length <= 0,
                  },
                ]}
                data={sqlResult.plan.steps}
              />
            )}
          </Grid>
        )}

        {showExecutionPlan && sqlResult?.plan && (
          <Grid xs={12}>
            <SQLExecutionPlanCard data={sqlResult.plan.steps} />
          </Grid>
        )}

        {sqlResult && (
          <Grid xs={12}>
            <SQLResultPreviewCard
              fields={sqlResult?.fields || []}
              rows={sqlResult?.rows || []}
            />
          </Grid>
        )}
      </Grid>
    </>
  );
}

export function TableCodeBlock(props: {
  children?: React.ReactNode;
  sql: string;
  showLineNumbers?: boolean;
}) {
  const { sql, showLineNumbers, children } = props;

  return (
    <Box
      sx={{
        minWidth: "fit-content",
        width: "auto",
      }}
    >
      <CodeBlock
        language="sql"
        text={sql}
        showLineNumbers={showLineNumbers}
        CustomContent={TableSchemaButton}
      />
    </Box>
  );
}

const IOSSwitch = styled((props: SwitchProps) => (
  <Switch focusVisibleClassName=".Mui-focusVisible" disableRipple {...props} />
))(({ theme, checked }) => ({
  // width: 42,
  width: 70,
  // height: 26,
  height: 32,
  padding: 0,
  "& .MuiSwitch-switchBase": {
    padding: 0,
    margin: 2,
    transitionDuration: "300ms",
    "&.Mui-checked": {
      transform: "translateX(38px)",
      color: "#fff",
      "& + .MuiSwitch-track": {
        // backgroundColor: theme.palette.mode === "dark" ? "#2ECA45" : "#09D698",
        backgroundColor: "#09D698",
        opacity: 1,
        border: 0,
      },
      "&.Mui-disabled + .MuiSwitch-track": {
        opacity: 0.5,
      },
    },
    "&.Mui-focusVisible .MuiSwitch-thumb": {
      color: "#33cf4d",
      border: "6px solid #fff",
    },
    "&.Mui-disabled .MuiSwitch-thumb": {
      // color:
      //   theme.palette.mode === "light"
      //     ? theme.palette.grey[100]
      //     : theme.palette.grey[600],
      color: theme.palette.grey[100],
    },
    "&.Mui-disabled + .MuiSwitch-track": {
      // opacity: theme.palette.mode === "light" ? 0.7 : 0.3,
      opacity: 0.7,
    },
  },
  "& .MuiSwitch-thumb": {
    boxSizing: "border-box",
    // width: 22,
    // height: 22,
    height: 28,
    width: 28,
  },
  "& .MuiSwitch-track": {
    // borderRadius: 26 / 2,
    borderRadius: 32 / 2,
    // backgroundColor: theme.palette.mode === "light" ? "#8F8F8F" : "#39393D",
    backgroundColor: "#8F8F8F",
    opacity: 1,
    transition: theme.transitions.create(["background-color"], {
      duration: 500,
    }),
    "&:before, &:after": {
      content: '""',
      position: "absolute",
      top: "50%",
      transform: "translateY(-50%)",
      color: "#fff",
      // width: 16,
      // height: 16,
    },
    "&:before": {
      content: checked ? '"ON"' : '""',
      left: 8,
    },
    "&:after": {
      content: checked ? '""' : '"OFF"',
      right: 8,
    },
  },
}));
