import { useQuery } from "@apollo/client";
import {
  Button,
  Card,
  Col,
  notification,
  Result,
  Row,
  Select,
  Space,
} from "antd";
import queryString from "query-string";
import React, { useEffect, useRef, useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { useHistory, useLocation, Link } from "react-router-dom";
import { createStructuredSelector } from "reselect";
import SocketIO from "socket.io-client";
import AlertComponent from "../../components/alert/alert.component";
import DmsAllocationsSummary from "../../components/dms-allocations-summary/dms-allocations-summary.component";
import DmsCustomerSelector from "../../components/dms-customer-selector/dms-customer-selector.component";
import DmsLogEvents from "../../components/dms-log-events/dms-log-events.component";
import DmsPostForm from "../../components/dms-post-form/dms-post-form.component";
import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component";
import { auth } from "../../firebase/firebase.utils";
import { QUERY_JOB_EXPORT_DMS } from "../../graphql/jobs.queries";
import {
  setBreadcrumbs,
  setSelectedHeader,
} from "../../redux/application/application.actions";
import { selectBodyshop } from "../../redux/user/user.selectors";
import { OwnerNameDisplayFunction } from "../../components/owner-name-display/owner-name-display.component";

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

const mapDispatchToProps = (dispatch) => ({
  setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)),
  setSelectedHeader: (key) => dispatch(setSelectedHeader(key)),
});

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

export const socket = SocketIO(
  process.env.NODE_ENV === "production"
    ? process.env.REACT_APP_AXIOS_BASE_API_URL
    : window.location.origin,
  {
    path: "/ws",
    withCredentials: true,
    auth: async (callback) => {
      const token = auth.currentUser && (await auth.currentUser.getIdToken());
      callback({ token });
    },
  }
);

export function DmsContainer({ bodyshop, setBreadcrumbs, setSelectedHeader }) {
  const { t } = useTranslation();
  const [logLevel, setLogLevel] = useState("DEBUG");
  const history = useHistory();
  const [logs, setLogs] = useState([]);
  const search = queryString.parse(useLocation().search);
  const { jobId } = search;

  const { loading, error, data } = useQuery(QUERY_JOB_EXPORT_DMS, {
    variables: { id: jobId },
    skip: !jobId,
    fetchPolicy: "network-only",
    nextFetchPolicy: "network-only",
  });
  const logsRef = useRef(null);

  useEffect(() => {
    document.title = t("titles.dms");
    setSelectedHeader("dms");
    setBreadcrumbs([
      {
        link: "/manage/accounting/receivables",
        label: t("titles.bc.accounting-receivables"),
      },
      {
        link: "/manage/dms",
        label: t("titles.bc.dms"),
      },
    ]);
  }, [t, setBreadcrumbs, setSelectedHeader]);

  useEffect(() => {
    socket.on("connect", () => socket.emit("set-log-level", logLevel));
    socket.on("reconnect", () => {
      setLogs((logs) => {
        return [
          ...logs,
          {
            timestamp: new Date(),
            level: "WARNING",
            message: "Reconnected to CDK Export Service",
          },
        ];
      });
    });

    socket.on("log-event", (payload) => {
      setLogs((logs) => {
        return [...logs, payload];
      });
    });
    socket.on("export-success", (payload) => {
      notification.success({
        message: t("jobs.successes.exported"),
      });
      history.push("/manage/accounting/receivables");
    });

    if (socket.disconnected) socket.connect();
    return () => {
      socket.removeAllListeners();
      socket.disconnect();
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  if (loading) return <LoadingSpinner />;
  if (error) return <AlertComponent message={error.message} type="error" />;

  if (
    !jobId ||
    !(bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber) ||
    !(data && data.jobs_by_pk)
  )
    return <Result status="404" title={t("general.errors.notfound")} />;

  if (data.jobs_by_pk && data.jobs_by_pk.date_exported)
    return <Result status="warning" title={t("dms.errors.alreadyexported")} />;

  return (
    <div>
      <Row gutter={[16, 16]}>
        <Col md={24} lg={10}>
          <DmsAllocationsSummary
            title={
              <span>
                <Link to={`/manage/jobs/${data && data.jobs_by_pk.id}`}>{`${
                  data && data.jobs_by_pk && data.jobs_by_pk.ro_number
                }`}</Link>
                {` | ${OwnerNameDisplayFunction(data.jobs_by_pk)} | ${
                  data.jobs_by_pk.v_model_yr || ""
                } ${data.jobs_by_pk.v_make_desc || ""} ${
                  data.jobs_by_pk.v_model_desc || ""
                }`}
              </span>
            }
            socket={socket}
            jobId={jobId}
          />
        </Col>
        <Col md={24} lg={14}>
          <DmsPostForm
            socket={socket}
            jobId={jobId}
            job={data && data.jobs_by_pk}
            logsRef={logsRef}
          />
        </Col>

        <DmsCustomerSelector />

        <Col span={24}>
          <div ref={logsRef}>
            <Card
              title={t("jobs.labels.dms.logs")}
              extra={
                <Space wrap>
                  <Select
                    placeholder="Log Level"
                    value={logLevel}
                    onChange={(value) => {
                      setLogLevel(value);
                      socket.emit("set-log-level", value);
                    }}
                  >
                    <Select.Option key="TRACE">TRACE</Select.Option>
                    <Select.Option key="DEBUG">DEBUG</Select.Option>
                    <Select.Option key="INFO">INFO</Select.Option>
                    <Select.Option key="WARNING">WARNING</Select.Option>
                    <Select.Option key="ERROR">ERROR</Select.Option>
                  </Select>
                  <Button onClick={() => setLogs([])}>Clear Logs</Button>
                  <Button
                    onClick={() => {
                      setLogs([]);
                      socket.disconnect();
                      socket.connect();
                    }}
                  >
                    Reconnect
                  </Button>
                </Space>
              }
            >
              <DmsLogEvents socket={socket} logs={logs} />
            </Card>
          </div>
        </Col>
      </Row>
    </div>
  );
}

export const determineDmsType = (bodyshop) => {
  if (bodyshop.cdk_dealerid) return "cdk";
  else {
    return "pbs";
  }
};
