import { useQuery } from "@apollo/client/react";
import { gql } from "@apollo/client";
import { Badge, Card, Space, Tag } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import axios from "axios";
import { isEmpty } from "lodash";
import { useCallback, useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { logImEXEvent } from "../../firebase/firebase.utils";
import { selectBodyshop } from "../../redux/user/user.selectors";
import { DateTimeFormatterFunction } from "../../utils/DateFormatter";
import dayjs from "../../utils/day";
import BlurWrapperComponent from "../feature-wrapper/blur-wrapper.component";
import { HasFeatureAccess } from "../feature-wrapper/feature-wrapper.component";
import UpsellComponent, { upsellEnum } from "../upsell/upsell.component";
import "./job-lifecycle.styles.scss";

const mapStateToProps = createStructuredSelector({
  bodyshop: selectBodyshop
});

const mapDispatchToProps = () => ({
  //setUserLanguage: language => dispatch(setUserLanguage(language))
});

// show text on bar if text can fit
export function JobLifecycleComponent({ bodyshop, job, statuses }) {
  const [loading, setLoading] = useState(true);
  const [lifecycleData, setLifecycleData] = useState(null);
  const { t } = useTranslation(); // Used for tracking external state changes.
  const hasLifeCycleAccess = HasFeatureAccess({ bodyshop, featureName: "lifecycle" });
  const { data } = useQuery(
    gql`
      query get_job_test($id: uuid!) {
        jobs_by_pk(id: $id) {
          id
          status
        }
      }
    `,
    {
      variables: {
        id: job.id
      },
      fetchPolicy: "cache-only"
    }
  );

  /**
   * Gets the lifecycle data for the job.
   * @returns {Promise<void>}
   */
  const getLifecycleData = useCallback(async () => {
    if (job && job.id && statuses && statuses.statuses) {
      try {
        setLoading(true);
        const response = await axios.post("/job/lifecycle", {
          jobids: job.id,
          statuses: statuses.statuses
        });
        logImEXEvent("jobs_lifecycle_data", {});
        const data = response.data.transition[job.id];
        setLifecycleData(data);
      } catch (err) {
        console.error(`${t("job_lifecycle.errors.fetch")}: ${err.message}`);
      } finally {
        setLoading(false);
      }
    }
  }, [job, statuses, t]);

  useEffect(() => {
    if (!data) return;
    setTimeout(() => {
      getLifecycleData().catch((err) => console.error(`${t("job_lifecycle.errors.fetch")}: ${err.message}`));
    }, 500);
  }, [data, getLifecycleData, t]);

  const columns = [
    {
      title: t("job_lifecycle.columns.value"),
      dataIndex: "value",
      key: "value",
      render: (text) => (
        <BlurWrapperComponent
          featureName="lifecycle"
          bypass
          valueProp="children"
          overrideValueFunction="RandomSmallString:2"
        >
          <span>{text}</span>
        </BlurWrapperComponent>
      )
    },
    {
      title: t("job_lifecycle.columns.start"),
      dataIndex: "start",
      key: "start",
      sorter: (a, b) => dayjs(a.start).unix() - dayjs(b.start).unix(),
      render: (text) => (
        <BlurWrapperComponent featureName="lifecycle" bypass valueProp="children" overrideValueFunction="RandomDate">
          <span>{DateTimeFormatterFunction(text)}</span>
        </BlurWrapperComponent>
      )
    },
    {
      title: t("job_lifecycle.columns.relative_start"),
      dataIndex: "start_readable",
      key: "start_readable"
    },
    {
      title: t("job_lifecycle.columns.end"),
      dataIndex: "end",
      key: "end",
      sorter: (a, b) => {
        if (isEmpty(a.end) || isEmpty(b.end)) {
          if (isEmpty(a.end) && isEmpty(b.end)) {
            return 0;
          }
          return isEmpty(a.end) ? 1 : -1;
        }
        return dayjs(a.end).unix() - dayjs(b.end).unix();
      },
      render: (text) => (
        <BlurWrapperComponent featureName="lifecycle" bypass valueProp="children" overrideValueFunction="RandomDate">
          <span>{isEmpty(text) ? t("job_lifecycle.content.not_available") : DateTimeFormatterFunction(text)}</span>
        </BlurWrapperComponent>
      )
    },
    {
      title: t("job_lifecycle.columns.relative_end"),
      dataIndex: "end_readable",
      key: "end_readable"
    },
    {
      title: t("job_lifecycle.columns.duration"),
      dataIndex: "duration_readable",
      key: "duration_readable",
      sorter: (a, b) => a.duration - b.duration
    }
  ];

  return (
    <Card loading={loading} title={t("job_lifecycle.content.title")}>
      {!loading ? (
        lifecycleData && lifecycleData.lifecycle && lifecycleData.durations ? (
          <Space orientation="vertical" style={{ width: "100%" }}>
            <Card
              type="inner"
              title={
                <Space orientation="horizontal" size="small">
                  <Badge status="processing" count={lifecycleData.durations.totalStatuses} />
                  {t("job_lifecycle.content.title_durations")}
                </Space>
              }
              style={{ width: "100%" }}
            >
              {!hasLifeCycleAccess && (
                <Card type="inner" style={{ marginTop: "10px" }}>
                  <UpsellComponent upsell={upsellEnum().lifecycle.general} />
                </Card>
              )}
              <BlurWrapperComponent featureName="lifecycle" bypass>
                <div
                  id="bar-container"
                  style={{
                    display: "flex",
                    width: "100%",
                    height: "100px",
                    textAlign: "center",
                    borderRadius: "5px",
                    borderWidth: "5px",
                    borderStyle: "solid",
                    borderColor: "var(--bar-border-color)",
                    margin: 0,
                    padding: 0
                  }}
                >
                  {lifecycleData.durations.summations.map((key, index, array) => {
                    const isFirst = index === 0;
                    const isLast = index === array.length - 1;
                    return (
                      <div
                        key={key.status}
                        style={{
                          overflow: "hidden",
                          display: "flex",
                          flexDirection: "column",
                          justifyContent: "center",
                          alignItems: "center",
                          margin: 0,
                          padding: 0,
                          borderTop: "1px solid var(--bar-border-color)",
                          borderBottom: "1px solid var(--bar-border-color)",
                          borderLeft: isFirst ? "1px solid var(--bar-border-color)" : undefined,
                          borderRight: isLast ? "1px solid var(--bar-border-color)" : undefined,
                          backgroundColor: key.color,
                          width: `${key.percentage}%`
                        }}
                        aria-label={`${key.status} | ${key.roundedPercentage} | ${key.humanReadable}`}
                        title={`${key.status} | ${key.roundedPercentage} | ${key.humanReadable}`}
                      >
                        {key.percentage > 15 ? (
                          <>
                            <div>{key.roundedPercentage}</div>
                            <div
                              style={{
                                backgroundColor: "var(--tag-wrapper-bg)",
                                borderRadius: "5px",
                                paddingRight: "2px",
                                paddingLeft: "2px",
                                fontSize: "0.8rem"
                              }}
                            >
                              {key.status}
                            </div>
                          </>
                        ) : null}
                      </div>
                    );
                  })}
                </div>
              </BlurWrapperComponent>
              <Card type="inner" title={t("job_lifecycle.content.legend_title")} style={{ marginTop: "10px" }}>
                <div
                  style={{
                    display: "flex",
                    flexWrap: "wrap",
                    gap: 8
                  }}
                >
                  {lifecycleData.durations.summations.map((key) => (
                    <Tag
                      key={key.status}
                      color={key.color}
                      style={{
                        // let the tag grow with its content
                        width: "auto",
                        padding: 0,
                        margin: 0,
                        display: "inline-flex",
                        alignItems: "center",
                        justifyContent: "center",
                        boxSizing: "border-box"
                      }}
                    >
                      <div
                        aria-label={`${key.status} | ${key.roundedPercentage} | ${key.humanReadable}`}
                        title={`${key.status} | ${key.roundedPercentage} | ${key.humanReadable}`}
                        style={{
                          backgroundColor: "var(--tag-wrapper-bg)",
                          color: "var(--tag-wrapper-text)",
                          padding: "4px 8px",
                          textAlign: "center",
                          whiteSpace: "nowrap" // single line; tag gets wider instead of text escaping
                        }}
                      >
                        {key.status} (
                        <BlurWrapperComponent
                          featureName="lifecycle"
                          bypass
                          overrideValueFunction="RandomAmount"
                          valueProp="children"
                        >
                          <span>{key.roundedPercentage}</span>
                        </BlurWrapperComponent>
                        )
                      </div>
                    </Tag>
                  ))}
                </div>
              </Card>
              {lifecycleData?.durations?.humanReadableTotal ||
              (lifecycleData.lifecycle[0] &&
                lifecycleData.lifecycle[0].value &&
                lifecycleData?.durations?.totalCurrentStatusDuration?.humanReadable) ? (
                <Card style={{ marginTop: "10px" }}>
                  <ul>
                    {lifecycleData.durations && lifecycleData.durations.humanReadableTotal && (
                      <li>
                        <span style={{ fontWeight: "bold" }}>
                          {t("job_lifecycle.content.previous_status_accumulated_time")}:
                        </span>{" "}
                        {lifecycleData.durations.humanReadableTotal}
                      </li>
                    )}
                    {lifecycleData.lifecycle[0] &&
                      lifecycleData.lifecycle[0].value &&
                      lifecycleData?.durations?.totalCurrentStatusDuration?.humanReadable && (
                        <li>
                          <span style={{ fontWeight: "bold" }}>
                            {t("job_lifecycle.content.current_status_accumulated_time")} (
                            {lifecycleData.lifecycle[0].value}):
                          </span>
                          {lifecycleData.durations.totalCurrentStatusDuration.humanReadable}
                        </li>
                      )}
                  </ul>
                </Card>
              ) : null}
            </Card>
            <Card
              type="inner"
              title={
                <>
                  <Space orientation="horizontal" size="small">
                    <Badge status="processing" count={lifecycleData.lifecycle.length} />
                    {t("job_lifecycle.content.title_transitions")}
                  </Space>
                </>
              }
            >
              <ResponsiveTable
                style={{
                  overflow: "auto",
                  width: "100%"
                }}
                columns={columns}
                mobileColumnKeys={["value", "start", "start_readable", "end"]}
                dataSource={lifecycleData.lifecycle}
                rowKey="start"
              />
            </Card>
          </Space>
        ) : (
          <Card type="inner" style={{ textAlign: "center" }}>
            {t("job_lifecycle.content.data_unavailable")}
          </Card>
        )
      ) : (
        <Card type="inner" title={t("job_lifecycle.content.title_loading")}>
          {t("job_lifecycle.content.loading")}
        </Card>
      )}
    </Card>
  );
}

export default connect(mapStateToProps, mapDispatchToProps)(JobLifecycleComponent);
