/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import {
  Stack,
  Table,
  TableBody,
  TableCell,
  TableContainer,
  TableHead,
  TableRow,
  Typography
} from "@mui/material";
import {
  Accordion,
  AccordionDetails,
  AccordionSummary
} from "@components/muiComponents";
import { numberFormatWithComma } from "@utils/Helper";
import { useMemo, useState } from "react";
import { useAppSelector } from "@hooks/reducerHook";
import { isEmpty } from "@utils/Utils";
import { stats } from "@utils/Enum";
import { getStatsValue } from "./Statistics";

const ServerStats = ({ selectedValue, currentMetricsData }: any) => {
  const { metricsData }: any = useAppSelector((state: any) => state.metrics);
  const { label } = selectedValue;
  const { metrics } = currentMetricsData;
  const selectedMetricsData = label == "Current" ? metricsData : metrics;
  const { general } = selectedMetricsData?.data || {};
  let statsData = general?.stats || {};

  const generateStatusData = (stateObject: any) => {
    let stats: any = {};

    for (let key in stateObject) {
      let keys: string[] = key.split(":");
      key = keys[0];
      let subKey = keys[1];
      if (stats[key]) {
        stats[key][subKey] = stateObject[`${key}:${subKey}`];
      } else {
        stats[key] = {};
        stats[key][subKey] = stateObject[`${key}:${subKey}`];
      }
    }

    return stats;
  };

  let serverData = generateStatusData(statsData);

  const offsetTableColumn = (obj: {
    [x: string]: any;
    hasOwnProperty: (arg0: string) => any;
  }) => {
    var returnObj = [];
    for (var key in obj) {
      if (Object.prototype.hasOwnProperty.call(obj, key)) {
        returnObj.push({ label: key, dataValue: obj[key] });
      }
    }
    return returnObj;
  };

  let offSetTabelData = offsetTableColumn(
    serverData?.Notification?.topicDetails
  );

  const [topicSort, setTopicSort] = useState<{
    key: string;
    order: "asc" | "desc";
  }>({ key: "label", order: "asc" });

  const handleSort = (key: string) => {
    setTopicSort((prev) => {
      const nextOrder = prev.key === key && prev.order === "asc" ? "desc" : "asc";
      return { key, order: nextOrder };
    });
  };

  const sortedOffsetTableData = useMemo(() => {
    const list = Array.isArray(offSetTabelData) ? [...offSetTabelData] : [];
    const { key, order } = topicSort;
    const dir = order === "asc" ? 1 : -1;
    return list.sort((a: any, b: any) => {
      if (key === "label") {
        const av = String(a.label || "").toLowerCase();
        const bv = String(b.label || "").toLowerCase();
        if (av < bv) return -1 * dir;
        if (av > bv) return 1 * dir;
        return 0;
      }
      const aTopic = serverData?.Notification?.topicDetails?.[a.label] || {};
      const bTopic = serverData?.Notification?.topicDetails?.[b.label] || {};
      const av = Number(aTopic?.[key] ?? 0);
      const bv = Number(bTopic?.[key] ?? 0);
      if (av < bv) return -1 * dir;
      if (av > bv) return 1 * dir;
      return 0;
    });
  }, [JSON.stringify(offSetTabelData), JSON.stringify(serverData?.Notification?.topicDetails), topicSort]);

  let notificationTableHeader = [
    "Count",
    "Avg",
    "Time (ms)",
    "Creates",
    "Updates",
    "Deletes"
    // "Failed"
  ];

  let topciOffsetTableHeader = [
    "offsetStart",
    "offsetCurrent",
    "processedMessageCount",
    "failedMessageCount",
    "lastMessageProcessedTime",
    "avgProcessingTime"
  ];

  let tableCol = [
    {
      label:
        "Total from " +
        getStatsValue({
          value: serverData?.Server?.["startTimeStamp"],
          type: stats?.Server?.["startTimeStamp"]
        }),
      key: "total"
    },
    {
      label:
        "Current Hour from " +
        getStatsValue({
          value: serverData?.Notification?.["currentHourStartTime"],
          type: stats.Notification?.["currentHourStartTime"]
        }),
      key: "currentHour"
    },
    { label: "Previous Hour", key: "previousHour" },
    {
      label:
        "Current Day from " +
        getStatsValue({
          value: serverData?.Notification?.["currentDayStartTime"],
          type: stats?.Notification?.["currentDayStartTime"]
        }),
      key: "currentDay"
    },
    { label: "Previous Day", key: "previousDay" }
  ];

  let tableHeader = [
    "count",
    "AvgTime",
    "EntityCreates",
    "EntityUpdates",
    "EntityDeletes",
    "Failed"
  ];

  const getTmplValue = (
    argument: { label?: string; key: any },
    args: string
  ) => {
    let pickValueFrom = argument.key.concat(args);
    if (argument.key == "total" && args == "EntityCreates") {
      pickValueFrom = "totalCreates";
    } else if (argument.key == "total" && args == "EntityUpdates") {
      pickValueFrom = "totalUpdates";
    } else if (argument.key == "total" && args == "EntityDeletes") {
      pickValueFrom = "totalDeletes";
    } else if (args == "count") {
      pickValueFrom = argument.key;
    }
    let returnVal = serverData?.Notification?.[pickValueFrom];
    return returnVal ? numberFormatWithComma(returnVal) : 0;
  };
  return (
    <Accordion
      sx={{
        width: "100%",
        borderBottom: "1px solid rgba(0, 0, 0, 0.12) !important",
        boxShadow: "none"
      }}
      defaultExpanded
    >
      <AccordionSummary
        aria-controls="technical-properties-content"
        id="technical-properties-header"
      >
        <Stack direction="row" alignItems="center" flex="1">
          <div className="properties-panel-name">
            <Typography fontWeight="600" className="text-color-green">
              Server Statistics
            </Typography>
          </div>
        </Stack>
      </AccordionSummary>
      <AccordionDetails>
        <Stack gap={"2rem"}>
          <TableContainer>
            <Table className="classificationTable" size="small">
              <TableHead>
                <TableRow>
                  <TableCell>
                    <Typography fontWeight="600">Server Details</Typography>
                  </TableCell>
                  <TableCell align="right">
                    <Typography fontWeight="600"></Typography>
                  </TableCell>
                </TableRow>
              </TableHead>
              <TableBody>
                {isEmpty(serverData?.Server) ? (
                  <TableRow className="empty text-center">
                    <TableCell colSpan={2} align="center">
                      <span>No records found!</span>
                    </TableCell>
                  </TableRow>
                ) : (
                  Object.entries(serverData?.Server)?.map(
                    ([key, value]: any) => (
                      <TableRow key={key}>
                        <TableCell>{key}</TableCell>
                        <TableCell align="right">
                          {getStatsValue({
                            value: value,
                            type: {
                              ...stats.Server,
                              ...stats.ConnectionStatus,
                              ...stats.generalData
                            }[key]
                          })}
                        </TableCell>
                      </TableRow>
                    )
                  )
                )}
              </TableBody>
            </Table>
          </TableContainer>
          <Stack gap={"2rem"}>
            <Typography fontWeight="600">Notification Table</Typography>
            <TableContainer>
              <Table className="classificationTable" size="small">
                <TableHead>
                  <TableRow>
                    <TableCell align="left" onClick={() => handleSort("label")} sx={{ cursor: "pointer" }}>
                      <Typography fontWeight="600">
                        Kafka Topic-Partition{topicSort.key === "label" ? (topicSort.order === "asc" ? " ▲" : " ▼") : ""}
                      </Typography>
                    </TableCell>
                    {topciOffsetTableHeader.map((key) => (
                      <TableCell key={key} align="left" onClick={() => handleSort(key)} sx={{ cursor: "pointer" }}>
                        <Typography fontWeight="600">
                          {(
                            {
                              offsetStart: "Start Offset",
                              offsetCurrent: "Current Offset",
                              processedMessageCount: "Processed",
                              failedMessageCount: "Failed",
                              lastMessageProcessedTime: "Last Message Processed Time",
                              avgProcessingTime: "Average message processing time"
                            } as any
                          )[key]}
                          {topicSort.key === key ? (topicSort.order === "asc" ? " ▲" : " ▼") : ""}
                        </Typography>
                      </TableCell>
                    ))}
                  </TableRow>
                </TableHead>
                <TableBody>
                  {isEmpty(offSetTabelData) ? (
                    <TableRow className="empty text-center">
                      <TableCell colSpan={2} align="center">
                        <span>No records found!</span>
                      </TableCell>
                    </TableRow>
                  ) : (
                    sortedOffsetTableData?.map((obj, index) => (
                      <TableRow key={index}>
                        <TableCell>{obj.label}</TableCell>
                        {topciOffsetTableHeader.map((header) => {
                          let returnVal =
                            serverData?.Notification?.topicDetails?.[obj.label]?.[header];
                          const typeForKey =
                            header === "avgProcessingTime"
                              ? stats.Notification["lastMessageProcessedTime"]
                              : stats.Notification[header];
                          return (
                            <TableCell align="left">
                              {returnVal
                                ? getStatsValue({
                                    value: returnVal,
                                    type: typeForKey
                                  })
                                : 0}
                            </TableCell>
                          );
                        })}
                      </TableRow>
                    ))
                  )}
                </TableBody>
              </Table>
            </TableContainer>
            <TableContainer>
              <Table className="classificationTable" size="small">
                <TableHead>
                  <TableRow>
                    <TableCell>
                      <Typography fontWeight="600">Period</Typography>
                    </TableCell>
                    {notificationTableHeader.map((header) => {
                      return (
                        <>
                          <TableCell align="right">
                            <Typography fontWeight="600">{header}</Typography>
                          </TableCell>
                        </>
                      );
                    })}
                  </TableRow>
                </TableHead>
                <TableBody>
                  {isEmpty(tableCol) ? (
                    <TableRow className="empty text-center">
                      <TableCell colSpan={2} align="center">
                        <span>No records found!</span>
                      </TableCell>
                    </TableRow>
                  ) : (
                    tableCol?.map((obj, index) => (
                      <TableRow key={index}>
                        <TableCell>{obj.label}</TableCell>
                        {tableHeader.map((header) => (
                          <TableCell align="right">
                            {getTmplValue(obj, header)}
                          </TableCell>
                        ))}{" "}
                      </TableRow>
                    ))
                  )}
                </TableBody>
              </Table>
            </TableContainer>
          </Stack>
        </Stack>
      </AccordionDetails>
    </Accordion>
  );
};

export default ServerStats;
