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 {
  RecoilRoot,
  atom,
  selector,
  useRecoilState,
  useRecoilValue,
} from "recoil";

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 { commonGridContainerProps, SQLProps } from "@/components/CodeBlock/SQL";
import { executeSql, executeSqlByCollection } from "@/utils";
import { API_QUERY_COLLECTION } from "@/constants/api";
import { useSession } from "@/utils/hook";
import { sessionState, foreignKeyDataState } from "@/recoil/atoms";
import { ExplainEngines } from "@/components/CodeBlock/SQLDiff";
export interface ForeignKeySQLProps
  extends Omit<
    SQLProps,
    "alternativeSql" | "switchBtnLabel" | "defaultChecked"
  > {
  requiredField?: string[];
}

export interface SQLTransactionResultType {
  params: any[];
  connectionId: string;
  multipleLines: boolean;
  sql: string;
  resultSetHeader: {
    fieldCount: number;
    affectedRows: number;
    insertId: string;
    info: string;
    serverStatus: number;
    warningStatus: number;
  }[];
}

// TODO refactor this with SQLDiff
export default function ForeignKeySQL(props: ForeignKeySQLProps) {
  const {
    sql,
    hideStatus,
    showExecutionPlan,
    disableRun,
    option,
    requiredField,
  } = props;
  const [sqlResult, setsqlResult] = React.useState<
    SQLResultType | SQLTransactionResultType | null
  >(null);
  const [sqlLoading, setsqlLoading] = React.useState(false);
  const [errorMsg, setErrorMsg] = React.useState("");

  const [sessionUser, setSessionUser] = useRecoilState(sessionState);
  const [foreignKeyData, setForeignKeyData] =
    useRecoilState(foreignKeyDataState);

  const sqlMemo = React.useMemo(() => {
    if (sessionUser) {
      let result = sql.replaceAll(`<user_id>`, `${sessionUser?.userId}`);
      foreignKeyData?.order_id &&
        (result = result.replaceAll(`<order_id>`, foreignKeyData.order_id));
      return result;
    }
    return sql;
  }, [sql, sessionUser, foreignKeyData]);

  const { enqueueSnackbar } = useSnackbar();

  const handleSql1Click = async () => {
    setsqlLoading(true);
    setsqlResult(null);
    setErrorMsg("");
    try {
      if (option) {
        const data = await executeSqlByCollection(
          option.collection,
          option.name
        );
        setsqlResult(data);
        if (option.name === "create-new-order-with-products") {
          const { resultSetHeader } = data as SQLTransactionResultType;
          const firstResult = resultSetHeader[0];
          const orderId = firstResult && firstResult.insertId;
          orderId &&
            setForeignKeyData({
              ...foreignKeyData,
              order_id: orderId,
            });
        }
        return;
      }
      const data = await executeSql(sqlMemo);
      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}>
        <Grid xs={12}>
          <SQLCard
            disableRun={disableRun || !sessionUser}
            disabled={requiredField?.every(
              (i) =>
                !(
                  foreignKeyData &&
                  foreignKeyData[i as keyof typeof foreignKeyData]
                )
            )}
            sql={sqlMemo}
            onClick={handleSql1Click}
            loading={sqlLoading}
            errorMsg={errorMsg}
          />
        </Grid>

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

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

        {(sqlResult as SQLResultType)?.fields && (
          <Grid xs={12}>
            <SQLResultPreviewCard
              fields={(sqlResult as SQLResultType).fields || []}
              rows={(sqlResult as SQLResultType).rows || []}
            />
          </Grid>
        )}
        {(sqlResult as SQLTransactionResultType)?.resultSetHeader && (
          <Grid xs={12}>
            <SQLResultPreviewCard
              type="code"
              text={`Success!\nOrderId: ${foreignKeyData?.order_id}`}
            />
          </Grid>
        )}
      </Grid>
    </>
  );
}
