import * as React from "react";
import _ from "lodash";
import Box, { BoxProps } from "@mui/material/Box";
import ReactEcharts from "echarts-for-react";
import Switch from "@mui/material/Switch";
import Grid from "@mui/material/Unstable_Grid2"; // Grid version 2
import Card, { CardProps } from "@mui/material/Card";
import CardContent from "@mui/material/CardContent";
import Typography from "@mui/material/Typography";
import { styled } from "@mui/material/styles";
import CircularProgress, {
  circularProgressClasses,
  CircularProgressProps,
} from "@mui/material/CircularProgress";
import LinearProgress, {
  linearProgressClasses,
} from "@mui/material/LinearProgress";
import IconButton from "@mui/material/IconButton";
import PlayCircleIcon from "@mui/icons-material/PlayCircle";
import StopCircleIcon from "@mui/icons-material/StopCircle";
import PauseCircleIcon from "@mui/icons-material/PauseCircle";
import ReplayCircleFilledIcon from "@mui/icons-material/ReplayCircleFilled";
import WarningIcon from "@mui/icons-material/Warning";
import Button, { ButtonProps } from "@mui/material/Button";
import Collapse from "@mui/material/Collapse";
import Grow from "@mui/material/Grow";
import Stack from "@mui/material/Stack";
import CheckIcon from "@mui/icons-material/Check";
import type { SvgIconProps } from "@mui/material/SvgIcon";
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
import AddIcon from "@mui/icons-material/Add";
import CheckCircleIcon from "@mui/icons-material/CheckCircle";
import AccessTimeIcon from "@mui/icons-material/AccessTime";
import Slider from "@mui/material/Slider";
import TextField from "@mui/material/TextField";
import LoadingButton from "@mui/lab/LoadingButton";
import RemoveIcon from "@mui/icons-material/Remove";

import { cards as cardsCfg } from "@/components/Sections/Scalable/_config";
import { config as navCfg } from "@/components/Layout2/_config";
import SQL from "@/components/Sections/RealTimeAnalytics/SQL";
import ContentTemplate from "@/components/Sections/Common/ContentTemplate";
import ARTComparisonChart from "@/components/Sections/Scalable/ARTComparisonChart";
import ARTSwitchCard from "@/components/Sections/Scalable/ARTSwitchCard";
import {
  SteadilyGrowingIcon,
  SpikyWorkloadIcon,
  AnalyticalWorkloadIcon,
  SpikyWorkloadLine,
  NoCfgChangesRequiredIcon,
  SteadilyWorkloadLine,
  AnalyticalWorkloadLine,
  ClearIcon,
  APBucket,
  EmptyBucketIcon,
  DefaultBucket,
  CircleStack,
  VersusIcon,
} from "@/components/Sections/Scalable/Icons";
import {
  UnifiedCodeDiffHighlight,
  UnifiedCodeDiffHighlightProps,
} from "@/components/CodeBlock";
import {
  animationKeyframesProps,
  DefaultBucketAnimation,
  DangerBucketAnimation,
  ResourcePoolExtensionAnimation,
  ClickArrowAnimation,
} from "@/components/Sections/Scalable/Animation";
import CustomCollapse from "@/components/Transform/Collapse";
import YoutubePlayer from "@/components/Sections/Scalable/Player";
import { sleep } from "@/utils";

import {
  PlayContentTemplate,
  AnimationVerticleWrapper,
  BlinkButtonSx,
  ProgressAlert,
  CfgModification,
  Conclusions,
  commonOption,
  VersusEle,
  AddMysqlNode,
} from "@/components/Sections/Scalable/EasyScaleContent_v2/Common";
import { BrowserStyleTemplate } from "@/components/Sections/MysqlCompatible/Content/Select";

const steadilyWorkloadMeta = {
  mysql: {
    cfg: `spring:
  datasource:
    url: jdbc:mysql://localhost:4000/sharding_plan?username=root
    driver-class-name: com.mysql.cj.jdbc.Driver`,
    modifiedCfg: `# Add client-side middleware sharding lib, 
# Zookeeper(distributed synchronization service), an app sharding config file.

spring:
spring:
  datasource:
    # point to sharding config file and wrapper class
    url: jdbc:shardingsphere:classpath:shardingsphere-config.yml
    driver-class-name: org.apache.shardingsphere.driver.ShardingSphereDriver

# NEW sharding library which depends on Zookeeper
mode:
  type: Cluster
  repository:
    type: ZooKeeper
    props:
      namespace: governance
      server-lists: localhost:2181
      retryIntervalMilliseconds: 500
      timeToLiveSeconds: 60

dataSources:
  shardingsphere_0:
    dataSourceClassName: com.zaxxer.hikari.HikariDataSource
    driverClassName: com.mysql.jdbc.Driver
    jdbcUrl: jdbc:mysql://localhost:3306/shardingsphere_0?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
    username: root
    password: 123456
  shardingsphere_1:
    dataSourceClassName: com.zaxxer.hikari.HikariDataSource
    driverClassName: com.mysql.jdbc.Driver
    jdbcUrl: jdbc:mysql://localhost:3306/shardingsphere_1?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
    username: root
    password: 123456

rules:
  - !SHARDING
    # Shards manually, relocate hard
    tables:
      github_events:
        actualDataNodes: shardingsphere_\${0..1}.github_events
        databaseStrategy:
          standard:
            shardingColumn: repo_id
            shardingAlgorithmName: repo_id_sharding_inline
      github_repos:
        actualDataNodes: shardingsphere_\${0..1}.github_repos
        databaseStrategy:
          standard:
            shardingColumn: repo_id
            shardingAlgorithmName: repo_id_sharding_inline
    # Hard to change this algorithm
    shardingAlgorithms:
      repo_id_sharding_inline:
        type: INLINE
        props:
          algorithm-expression: shardingsphere_\${repo_id % 2}

props:
  sql-show: true`,
    added: [...new Array(54).fill(0).map((_, i) => i + 4)],
    conclusion: [
      "Manual data relocation",
      "Complex code & arch",
      "Higher cost(hardware & human resource)",
    ],
  },
  tidb: {
    cfg: `spring: 
  datasource: 
    url: jdbc:mysql://localhost:4000/tidb_plan 
    username: root 
    driver-class-name: com.mysql.cj.jdbc.Driver`,
    conclusion: [
      "Automatic data relocation and zero down time",
      "Simple code & arch",
      "Lower cost(pay as you go)",
    ],
  },
};

export default function SteadilyWorkload() {
  const [hasAddedMysqlBucket, setHasAddedMysqlBucket] = React.useState(false);
  const [hasCheckCfg, setHasCheckCfg] = React.useState(false);
  const [completedActions, setCompletedActions] = React.useState<string[]>([]);
  const [tidbFinished, setTidbFinished] = React.useState(false);

  return (
    <>
      <VersusEle />
      <Grid xs={6}>
        <PlayContentTemplate
          title="MySQL RDS"
          configFile={
            hasCheckCfg
              ? steadilyWorkloadMeta.mysql.modifiedCfg
              : steadilyWorkloadMeta.mysql.cfg
          }
          codeProps={{
            ADDED: hasCheckCfg ? steadilyWorkloadMeta.mysql.added : [],
          }}
          animationBoxSx={{
            height: "240px",
          }}
          animationEle={
            <AddMysqlNode
              items={[
                {
                  id: "buy-hardware",
                  title: "Buy hardware",
                  unit: 2,
                },
                {
                  id: "add-node",
                  title: "Add new node to cluster",
                  unit: 2,
                },
                {
                  id: "rebalance-data",
                  title: "Re-balance data",
                  unit: 10,
                },
              ]}
              postAddNode={[
                {
                  id: "check-cfg",
                  title: "Waiting for changing app config",
                  requiredActions: ["mysql-check-cfg"],
                },
              ]}
              postFinishItems={() => {
                setHasAddedMysqlBucket(true);
              }}
              finishedActions={completedActions}
            />
          }
          configFileChildren={
            <>
              {hasAddedMysqlBucket && (
                <Box
                  sx={{
                    position: "absolute",
                    top: "8px",
                    right: "8px",

                    ...(hasCheckCfg && {
                      display: "none",
                    }),
                  }}
                >
                  <Box position="relative">
                    <Button
                      variant="contained"
                      disabled={hasCheckCfg}
                      endIcon={hasCheckCfg && <CheckIcon fontSize="inherit" />}
                      onClick={() => {
                        setHasCheckCfg(true);
                        setCompletedActions(["mysql-check-cfg"]);
                      }}
                      sx={{
                        ...(!hasCheckCfg && BlinkButtonSx),
                      }}
                    >
                      Modify app config
                    </Button>
                    {!hasCheckCfg && <ClickArrowAnimation />}
                  </Box>
                </Box>
              )}
              {hasCheckCfg && (
                <Box
                  sx={{
                    position: "absolute",
                    top: "8px",
                    right: "8px",
                  }}
                >
                  <CfgModification addedLines={55} deletedLines={2} />
                </Box>
              )}
            </>
          }
          conclusionsEle={
            completedActions.includes("mysql-check-cfg") && (
              <Conclusions
                type="mysql"
                items={[
                  <>
                    <b>Manual</b> data relocation(weeks)
                  </>,
                  <>
                    <b>Complex</b> code & toolkits
                  </>,
                  <>
                    <b>Higher</b> cost(Maintenance & human resource)
                  </>,
                ]}
              />
            )
          }
        />
      </Grid>
      <Grid xs={6}>
        <PlayContentTemplate
          title="TiDB Cloud Dedicated"
          type="tidb"
          configFile={steadilyWorkloadMeta.tidb.cfg}
          configFileChildren={
            <>
              {hasCheckCfg && (
                <Box
                  sx={{
                    position: "absolute",
                    top: "8px",
                    right: "8px",
                  }}
                >
                  <CfgModification noChange />
                </Box>
              )}
            </>
          }
          animationBoxSx={{
            height: "240px",
          }}
          animationEle={
            <>
              <AddTidbNode
                postCompleted={() => {
                  setTidbFinished(true);
                }}
              />
              {/* <AddMysqlNode
                items={[
                  {
                    id: "add-node",
                    title: "Add a node after a few clicks",
                    unit: 5,
                  },
                ]}
                postFinishItems={() => {
                  setTidbFinished(true);
                }}
                unitLabel="min"
                unitDuration={500}
              /> */}
            </>
          }
          conclusionsEle={
            tidbFinished && (
              <Conclusions
                type="tidb"
                items={[
                  <>
                    <b>A few clicks</b> to scaling, zero down time
                  </>,
                  <>
                    <b>Simple</b> code
                  </>,
                  <>
                    <b>Lower</b> maintenance cost
                  </>,
                ]}
              />
            )
          }
        />
      </Grid>
    </>
  );
}

function AddTidbNode(props: { postCompleted?: () => void }) {
  const { postCompleted } = props;

  const targetStep = 5;
  const unitDuration = 500;

  const [hasAddedBucketClick, setHasAddedBucketClick] = React.useState(false);
  const [hasAddedBucket, setHasAddedBucket] = React.useState(false);
  const [loading, setLoading] = React.useState(false);
  const [step, setStep] = React.useState(0);

  React.useEffect(() => {
    if (hasAddedBucket) {
      postCompleted && postCompleted();
    }
  }, [hasAddedBucket, postCompleted]);

  React.useEffect(() => {
    if (loading) {
      const timer = setTimeout(() => {
        if (step === targetStep) {
          setHasAddedBucket(true);
          setLoading(false);
          return;
        }
        setStep((prev) => prev + 1);
      }, unitDuration);
      return () => clearTimeout(timer);
    }
  }, [loading, step]);

  const handleBtnClick = async () => {
    setLoading(true);
    setHasAddedBucketClick(true);
    // await sleep(targetStep * unitDuration);
    // setLoading(false);
    // setHasAddedBucket(true);
  };

  return (
    <Box
      display="flex"
      flexDirection={hasAddedBucketClick ? "row" : "column"}
      justifyContent="center"
      alignItems="center"
      gap={2}
    >
      <Box
        display="flex"
        alignItems="center"
        justifyContent="center"
        flexDirection="column"
        gap={2}
      >
        <Stack spacing={2} direction="row">
          <DefaultBucketAnimation />
          {hasAddedBucket && <DefaultBucketAnimation />}
        </Stack>
        {hasAddedBucketClick && (
          <Typography
            fontWeight={600}
            fontSize={16}
            display="inline-flex"
            alignItems="center"
            gap={0.5}
          >
            <AccessTimeIcon />
            {step} mins
          </Typography>
        )}
      </Box>

      {hasAddedBucketClick && (
        <Box display="inline-flex" alignItems="center" gap={1}>
          {loading ? (
            <CircularProgress size={18} />
          ) : (
            <CheckIcon fontSize="small" />
          )}
          <Typography variant="body2" component="div">
            {`Add a new node(5mins)`}
          </Typography>
        </Box>
      )}

      {!hasAddedBucketClick && (
        <BrowserStyleTemplate>
          <Box display="flex" gap={1} alignItems="center">
            <Typography component="span" variant="body2" fontWeight="bold">
              Add nodes
            </Typography>
            <IconButton size="small" disabled>
              <RemoveIcon />
            </IconButton>
            <TextField
              variant="standard"
              value={1}
              disabled
              sx={{
                width: "16px",
              }}
            ></TextField>
            <IconButton size="small" disabled>
              <AddIcon />
            </IconButton>

            <Box position="relative">
              <LoadingButton
                variant="contained"
                size="small"
                onClick={handleBtnClick}
                loading={loading}
              >
                Confirm
              </LoadingButton>
              {!hasAddedBucketClick && <ClickArrowAnimation />}
            </Box>
          </Box>
        </BrowserStyleTemplate>
      )}
    </Box>
  );
}
