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 { 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,
  ConclusionSpikyTiDB,
  ConclusionSpikyMySQL,
} 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 {
  PlayContentTemplate,
  AnimationVerticleWrapper,
  BlinkButtonSx,
  ProgressAlert,
  CfgModification,
  Conclusions,
  commonOption,
  VersusEle,
  AnimationServerlessAutoScaledOut,
  AddMysqlNode,
} from "@/components/Sections/Scalable/EasyScaleContent_v2/Common";

const workloadSpikyLoadMeta = {
  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:
  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: [1, 2, ...new Array(54).fill(0).map((_, i) => i + 6)],
    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)",
    ],
  },
};

function randomData(min = 0, max = 100) {
  return Math.round(Math.random() * (max - min) + min);
}

const workloadSpikyLoadChartMysqlData = [
  ...new Array(39).fill(0).map((_, i) => ({
    name: i,
    value: 60 + randomData(0, 10) - 5,
  })),
  ...new Array(5).fill(0).map((_, i) => ({
    name: i + 40,
    value: 80 + (i + 39 - 45) / 30 + randomData(0, 10) - 5,
  })),
  ...new Array(5).fill(0).map((_, i) => ({
    name: i + 45,
    value: 80 + (50 - i - 45) / 30 + randomData(0, 10) - 5,
  })),
  ...new Array(5).fill(0).map((_, i) => ({
    name: i + 50,
    value: 150 + (i + 50 - 49) / 80 + randomData(0, 10) - 5,
  })),
  ...new Array(5).fill(0).map((_, i) => ({
    name: i + 55,
    value: 150 + (59 - i - 55) / 80 + randomData(0, 10) - 5,
  })),
  ...new Array(46).fill(0).map((_, i) => ({
    name: i + 60,
    value: 50 + randomData(5, 10) - 5,
  })),
];

const workloadSpikyLoadChartTiDBData = [
  ...new Array(50).fill(0).map((_, i) => ({
    name: i,
    value: randomData(30, 40),
  })),
  ...new Array(10).fill(0).map((_, i) => ({
    name: i + 50,
    value: randomData(45, 60),
  })),
  ...new Array(40).fill(0).map((_, i) => ({
    name: i + 60,
    value: randomData(30, 40),
  })),
];

const WorkloadSpikyLoad = (props: {
  progress: number;
  isPlaying?: boolean;
  handleCompleteActions: (actions: string[]) => void;
}) => {
  const { progress, isPlaying, handleCompleteActions } = props;

  const [hasAddedBucket, setHasAddedBucket] = React.useState(false);
  const [hasCheckCfg, setHasCheckCfg] = React.useState(false);
  const [completedActions, setCompletedActions] = React.useState<string[]>([]);

  const [chartDataMysqlMemo, chartDataTiDBMemo] = React.useMemo(() => {
    let result1: any[] = [];
    let result2: any[] = [];
    const result1Tmp = workloadSpikyLoadChartMysqlData.filter(
      (i) => i.name <= progress
    );
    const result2Tmp = workloadSpikyLoadChartTiDBData.filter(
      (i) => i.name <= progress
    );
    if (result1Tmp.length < 100) {
      result1 = [
        ...new Array(100 - result1Tmp.length).fill(null),
        ...result1Tmp,
      ];
    } else {
      result1 = result1Tmp;
    }
    if (result2Tmp.length < 100) {
      result2 = [
        ...new Array(100 - result2Tmp.length).fill(null),
        ...result2Tmp,
      ];
    } else {
      result2 = result2Tmp;
    }
    return [result1, result2];
  }, [progress]);

  return (
    <>
      <Grid xs={6}>
        <PlayContentTemplate
          title="MySQL RDS"
          configFile={
            hasCheckCfg
              ? workloadSpikyLoadMeta.mysql.modifiedCfg
              : workloadSpikyLoadMeta.mysql.cfg
          }
          codeProps={{
            ADDED: hasCheckCfg ? workloadSpikyLoadMeta.mysql.added : [],
          }}
          animationEle={
            <>
              {progress < 49 && isPlaying && (
                <>
                  <DefaultBucketAnimation />
                </>
              )}
              {progress >= 49 && progress < 100 && (
                <>
                  <Box
                    display="flex"
                    alignItems="center"
                    justifyContent="center"
                    flexDirection="column"
                    gap={2}
                  >
                    {/* <DangerBucketAnimation warning /> */}
                    {/* <Box position="relative">
                      <Button
                        variant="contained"
                        disabled={hasAddedBucket}
                        endIcon={
                          hasAddedBucket && <CheckIcon fontSize="inherit" />
                        }
                        onClick={() => {
                          setHasAddedBucket(true);
                          handleCompleteActions(["mysql-add-nodes"]);
                        }}
                        sx={{
                          position: "relative",
                          ...(!hasAddedBucket && BlinkButtonSx),
                          ...(hasAddedBucket && {
                            display: "none",
                          }),
                        }}
                      >
                        Click to add nodes
                      </Button>
                      {!hasAddedBucket && <ClickArrowAnimation />}
                    </Box> */}
                    {
                      <Box display="flex" flexDirection="row">
                        <AddMysqlNode
                          items={[
                            {
                              id: "buy-hardware",
                              title: "Buy & add hardware",
                              unit: 2,
                            },
                            {
                              id: "add-sharding-tool-stack",
                              title: "Add Sharding Tool Stack",
                              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={() => {
                            setHasAddedBucket(true);
                            handleCompleteActions(["mysql-add-nodes"]);
                          }}
                          finishedActions={completedActions}
                        />
                      </Box>
                    }
                  </Box>
                </>
              )}
              {/* {hasAddedBucket && !hasCheckCfg && (
                <AnimationVerticleWrapper
                  title="Waiting for changing configuration"
                  status="loading"
                >
                  <Stack direction="row" spacing={2} alignItems="center">
                    <DangerBucketAnimation warning />
                    <AddIcon />
                    <EmptyBucketIcon
                      sx={{
                        color: "transparent",
                        width: "24px",
                        height: "auto",
                      }}
                    />
                  </Stack>
                </AnimationVerticleWrapper>
              )} */}
              {/* {hasCheckCfg && progress < 100 && (
                <AnimationVerticleWrapper
                  title="Manually scaled out"
                  status="success"
                >
                  <Stack direction="row" spacing={2} alignItems="center">
                    <DefaultBucketAnimation />
                    <AddIcon />
                    <DefaultBucketAnimation />
                  </Stack>
                </AnimationVerticleWrapper>
              )} */}
              {progress >= 100 && (
                <ConclusionSpikyMySQL
                  sx={{
                    width: "75%",
                    height: "auto",
                    color: "transparent",
                  }}
                />
              )}
            </>
          }
          configFileChildren={
            <>
              {hasAddedBucket && (
                <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);
                        handleCompleteActions(["mysql-check-cfg"]);
                        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={
            progress >= 100 && (
              <Conclusions
                type="mysql"
                items={[
                  <>
                    <b>Higher</b> cost(hardware & human resource)
                  </>,
                  <>
                    <b>Manual</b> data relocation(weeks)
                  </>,
                  <>
                    <b>Complex</b> code & toolkits
                  </>,
                  null,
                ]}
              />
            )
          }
          chartEle={
            <ReactEcharts
              option={{
                ...commonOption,
                series: [
                  {
                    name: "Fake Data",
                    type: "line",
                    showSymbol: false,
                    data: chartDataMysqlMemo,
                    // markPoint: progress >= 100 && {
                    //   silent: true,
                    //   label: {
                    //     show: true,
                    //     position: "insideBottom",
                    //   },
                    //   itemStyle: {
                    //     color: "transparent",
                    //   },
                    //   animationDelay: 3000,
                    //   data: [
                    //     {
                    //       name: "peak load",
                    //       value: "⚠️",
                    //       yAxis:
                    //         workloadSpikyLoadChartMysqlData.find(
                    //           (i) => i.name === 49
                    //         )?.value || 0,
                    //       xAxis: 49,
                    //     },
                    //   ],
                    // },
                    markLine: progress >= 100 && {
                      silent: true,
                      showSymbol: false,
                      symbol: "none",
                      data: [
                        {
                          name: "50%",
                          xAxis: 49,
                          label: {
                            formatter: "Workload peak",
                            position: "insideEnd",
                            rotate: 0,
                          },
                        },
                        {
                          name: "55%",
                          xAxis: 55,
                          label: {
                            formatter: "Low load",
                            position: "insideEnd",
                            rotate: 0,
                            offset: [60, 0],
                          },
                        },
                      ],
                    },
                  },
                  progress >= 49 && {
                    name: "line",
                    type: "line",
                    stack: "all",
                    showSymbol: false,
                    markLine: {
                      symbol: "none",
                      silent: true,
                      label: {
                        position: "start",
                      },
                      data: [
                        {
                          name: "Horizontal line with Y value at 100",
                          yAxis: 100,
                        },
                      ],
                    },
                  },
                ],
              }}
            />
          }
        />
      </Grid>
      <Grid xs={6}>
        <PlayContentTemplate
          title="TiDB Cloud Starter"
          type="tidb"
          configFile={workloadSpikyLoadMeta.tidb.cfg}
          configFileChildren={
            <>
              {hasCheckCfg && (
                <Box
                  sx={{
                    position: "absolute",
                    top: "8px",
                    right: "8px",
                  }}
                >
                  <CfgModification noChange />
                </Box>
              )}
            </>
          }
          animationEle={
            <>
              {progress < 49 && isPlaying && (
                <>
                  <DefaultBucketAnimation />
                </>
              )}
              {progress <= 55 && progress >= 49 && (
                <AnimationServerlessAutoScaledOut />
              )}
              {progress > 55 && progress < 100 && (
                <AnimationServerlessAutoScaledOut reverse />
              )}
              {progress >= 100 && (
                <ConclusionSpikyTiDB
                  sx={{
                    width: "75%",
                    height: "auto",
                    color: "transparent",
                  }}
                />
              )}
            </>
          }
          conclusionsEle={
            progress >= 100 && (
              <Conclusions
                type="tidb"
                items={[
                  <>
                    <b>Lower</b> cost(pay as you go)
                  </>,
                  <>
                    <b>Automatic</b> data relocation, zero down time
                  </>,
                  <>
                    <b>Simple</b> code
                  </>,
                  <>
                    <b>Auto</b> scaling out/in
                  </>,
                ]}
              />
            )
          }
          chartEle={
            <ReactEcharts
              option={{
                ...commonOption,
                series: [
                  {
                    name: "Fake Data",
                    type: "line",
                    showSymbol: false,
                    data: chartDataTiDBMemo,
                    // markPoint: progress >= 100 && {
                    //   silent: true,
                    //   label: {
                    //     show: true,
                    //     position: "insideBottom",
                    //   },
                    //   itemStyle: {
                    //     color: "transparent",
                    //   },
                    //   animationDelay: 3000,
                    //   data: [
                    //     {
                    //       name: "peak load",
                    //       value: "⚠️",
                    //       yAxis:
                    //         workloadSpikyLoadChartTiDBData.find(
                    //           (i) => i.name === 49
                    //         )?.value || 0,
                    //       xAxis: 49,
                    //     },
                    //   ],
                    // },
                    markLine: progress >= 100 && {
                      silent: true,
                      showSymbol: false,
                      symbol: "none",
                      data: [
                        {
                          name: "50%",
                          xAxis: 49,
                          label: {
                            formatter: "Workload peak",
                            position: "insideEnd",
                            rotate: 0,
                          },
                        },
                        {
                          name: "55%",
                          xAxis: 55,
                          label: {
                            formatter: "Low load",
                            position: "insideEnd",
                            rotate: 0,
                            offset: [60, 0],
                          },
                        },
                      ],
                    },
                  },
                  progress >= 49 && {
                    name: "line",
                    type: "line",
                    stack: "all",
                    showSymbol: false,
                    markLine: {
                      symbol: "none",
                      silent: true,
                      label: {
                        position: "start",
                      },
                      data: [
                        {
                          name: "Horizontal line with Y value at 100",
                          yAxis: 100,
                        },
                      ],
                    },
                  },
                ],
              }}
            />
          }
        />
      </Grid>
      <VersusEle />
    </>
  );
};

export default WorkloadSpikyLoad;
