import { SyncOutlined } from "@ant-design/icons";
import { useApolloClient } from "@apollo/client";
import Board, { moveCard } from "@asseinfo/react-kanban";
import { Button, Grid, notification, Space, Statistic } from "antd";
import { PageHeader } from "@ant-design/pro-layout";
import React, { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { Sticky, StickyContainer } from "react-sticky";
import { createStructuredSelector } from "reselect";
import styled from "styled-components";
import { logImEXEvent } from "../../firebase/firebase.utils";
import { generate_UPDATE_JOB_KANBAN } from "../../graphql/jobs.queries";
import { insertAuditTrail } from "../../redux/application/application.actions";
import { selectTechnician } from "../../redux/tech/tech.selectors";
import { selectBodyshop } from "../../redux/user/user.selectors";
import AuditTrailMapping from "../../utils/AuditTrailMappings";
import IndefiniteLoading from "../indefinite-loading/indefinite-loading.component";
import ProductionBoardFilters from "../production-board-filters/production-board-filters.component";
import ProductionBoardCard from "../production-board-kanban-card/production-board-kanban-card.component";
import ProductionListDetailComponent from "../production-list-detail/production-list-detail.component";
import ProductionBoardKanbanCardSettings from "./production-board-kanban.card-settings.component";
//import "@asseinfo/react-kanban/dist/styles.css";
import CardColorLegend from "../production-board-kanban-card/production-board-kanban-card-color-legend.component";
import "./production-board-kanban.styles.scss";
import { createBoardData } from "./production-board-kanban.utils.js";

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

const mapDispatchToProps = (dispatch) => ({
  insertAuditTrail: ({ jobid, operation, type }) => dispatch(insertAuditTrail({ jobid, operation, type }))
});

export function ProductionBoardKanbanComponent({
  data,
  bodyshop,
  refetch,
  technician,
  insertAuditTrail,
  associationSettings
}) {
  const [boardLanes, setBoardLanes] = useState({
    columns: [{ id: "Loading...", title: "Loading...", cards: [] }]
  });

  const [filter, setFilter] = useState({ search: "", employeeId: null });

  const [isMoving, setIsMoving] = useState(false);

  const { t } = useTranslation();
  useEffect(() => {
    const boardData = createBoardData(
      [...bodyshop.md_ro_statuses.production_statuses, ...(bodyshop.md_ro_statuses.additional_board_statuses || [])],
      data,
      filter
    );

    boardData.columns = boardData.columns.map((d) => {
      return { ...d, title: `${d.title} (${d.cards.length})` };
    });
    setBoardLanes(boardData);
    setIsMoving(false);
  }, [data, setBoardLanes, setIsMoving, bodyshop.md_ro_statuses, filter]);

  const client = useApolloClient();

  const handleDragEnd = async (card, source, destination) => {
    logImEXEvent("kanban_drag_end");

    setIsMoving(true);
    setBoardLanes(moveCard(boardLanes, source, destination));

    const sameColumnTransfer = source.fromColumnId === destination.toColumnId;
    const sourceColumn = boardLanes.columns.find((x) => x.id === source.fromColumnId);
    const destinationColumn = boardLanes.columns.find((x) => x.id === destination.toColumnId);

    const movedCardWillBeFirst = destination.toPosition === 0;

    const movedCardWillBeLast = destinationColumn.cards.length - destination.toPosition < 1;

    const lastCardInDestinationColumn = destinationColumn.cards[destinationColumn.cards.length - 1];

    const oldChildCard = sourceColumn.cards[source.fromPosition + 1];

    const newChildCard = movedCardWillBeLast
      ? null
      : destinationColumn.cards[
          sameColumnTransfer
            ? source.fromPosition - destination.toPosition > 0
              ? destination.toPosition
              : destination.toPosition + 1
            : destination.toPosition
        ];

    const oldChildCardNewParent = oldChildCard ? card.kanbanparent : null;

    let movedCardNewKanbanParent;
    if (movedCardWillBeFirst) {
      //console.log("==> New Card is first.");
      movedCardNewKanbanParent = "-1";
    } else if (movedCardWillBeLast) {
      // console.log("==> New Card is last.");
      movedCardNewKanbanParent = lastCardInDestinationColumn.id;
    } else if (!!newChildCard) {
      // console.log("==> New Card is somewhere in the middle");
      movedCardNewKanbanParent = newChildCard.kanbanparent;
    } else {
      console.log("==> !!!!!!Couldn't find a parent.!!!! <==");
    }
    const newChildCardNewParent = newChildCard ? card.id : null;
    const update = await client.mutate({
      mutation: generate_UPDATE_JOB_KANBAN(
        oldChildCard ? oldChildCard.id : null,
        oldChildCardNewParent,
        card.id,
        movedCardNewKanbanParent,
        destination.toColumnId,
        newChildCard ? newChildCard.id : null,
        newChildCardNewParent
      )
    });
    insertAuditTrail({
      jobid: card.id,
      operation: AuditTrailMapping.jobstatuschange(destination.toColumnId),
      type: "jobstatuschange"
    });

    if (update.errors) {
      notification["error"]({
        message: t("production.errors.boardupdate", {
          message: JSON.stringify(update.errors)
        })
      });
    }
  };

  const totalHrs = data
    .reduce(
      (acc, val) => acc + (val.labhrs?.aggregate?.sum?.mod_lb_hrs || 0) + (val.larhrs?.aggregate?.sum?.mod_lb_hrs || 0),
      0
    )
    .toFixed(1);
  const totalLAB = data.reduce((acc, val) => acc + (val.labhrs?.aggregate?.sum?.mod_lb_hrs || 0), 0).toFixed(1);
  const totalLAR = data.reduce((acc, val) => acc + (val.larhrs?.aggregate?.sum?.mod_lb_hrs || 0), 0).toFixed(1);
  const selectedBreakpoint = Object.entries(Grid.useBreakpoint())
    .filter((screen) => !!screen[1])
    .slice(-1)[0];

  const standardSizes = {
    xs: "250",
    sm: "250",
    md: "250",
    lg: "250",
    xl: "250",
    xxl: "250"
  };
  const compactSizes = {
    xs: "150",
    sm: "150",
    md: "150",
    lg: "150",
    xl: "155",
    xxl: "155"
  };

  const width = selectedBreakpoint
    ? associationSettings && associationSettings.kanban_settings && associationSettings.kanban_settings.compact
      ? compactSizes[selectedBreakpoint[0]]
      : standardSizes[selectedBreakpoint[0]]
    : "250";

  const stickyHeader = {
    renderColumnHeader: ({ title }) => (
      <Sticky>
        {({
          style,

          // the following are also available but unused in this example
          isSticky,
          wasSticky,
          distanceFromTop,
          distanceFromBottom,
          calculatedHeight
        }) => (
          <div className="react-kanban-column-header" style={{ ...style, zIndex: "99", backgroundColor: "#ddd" }}>
            {title}
          </div>
        )}
      </Sticky>
    )
  };

  const cardSettings =
    associationSettings &&
    associationSettings.kanban_settings &&
    Object.keys(associationSettings.kanban_settings).length > 0
      ? associationSettings.kanban_settings
      : {
          ats: true,
          clm_no: true,
          compact: false,
          ownr_nm: true,
          sublets: true,
          ins_co_nm: true,
          production_note: true,
          employeeassignments: true,
          scheduled_completion: true,
          stickyheader: false,
          cardcolor: false
        };

  return (
    <Container width={width}>
      <IndefiniteLoading loading={isMoving} />

      <PageHeader
        title={
          <Space>
            <Statistic title={t("dashboard.titles.productionhours")} value={totalHrs} />
            <Statistic title={t("dashboard.titles.labhours")} value={totalLAB} />
            <Statistic title={t("dashboard.titles.larhours")} value={totalLAR} />
            <Statistic title={t("appointments.labels.inproduction")} value={data && data.length} />
          </Space>
        }
        extra={
          <Space wrap>
            <Button onClick={() => refetch && refetch()}>
              <SyncOutlined />
            </Button>
            <ProductionBoardFilters filter={filter} setFilter={setFilter} loading={isMoving} />
            <ProductionBoardKanbanCardSettings associationSettings={associationSettings} />
          </Space>
        }
      />

      {cardSettings.cardcolor && <CardColorLegend cardSettings={cardSettings} bodyshop={bodyshop} />}

      <ProductionListDetailComponent jobs={data} />
      <StickyContainer>
        <Board
          style={{ height: "100%" }}
          children={boardLanes}
          disableCardDrag={isMoving}
          {...(cardSettings.stickyheader && stickyHeader)}
          renderCard={(card) => ProductionBoardCard(technician, card, bodyshop, cardSettings)}
          onCardDragEnd={handleDragEnd}
        />
      </StickyContainer>
    </Container>
  );
}

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

const Container = styled.div`
  .react-kanban-card-skeleton,
  .react-kanban-card,
  .react-kanban-card-adder-form {
    box-sizing: border-box;
    max-width: ${(props) => props.width}px;
    min-width: ${(props) => props.width}px;
  }
`;
