import { useQuery } from "@apollo/client/react";
import { Col, Row } from "antd";
import _ from "lodash";
import queryString from "query-string";
import { useMemo } from "react";
import { useLocation } from "react-router-dom";
import { QUERY_TIME_TICKETS_IN_RANGE_SB } from "../../graphql/timetickets.queries";
import dayjs from "../../utils/day";
import AlertComponent from "../alert/alert.component";
import LoadingSpinner from "../loading-spinner/loading-spinner.component";
import * as Utils from "../scoreboard-targets-table/scoreboard-targets-table.util";
import ScoreboardTicketsBar from "./scoreboard-timetickets.bar.component";
import ScoreboardTicketsStats from "./scoreboard-timetickets.stats.component";

export default function ScoreboardTimeTickets() {
  const searchParams = queryString.parse(useLocation().search);
  const { start, end } = searchParams;
  const startDate = start ? dayjs(start) : dayjs().startOf("week").subtract(7, "day");
  const endDate = end ? dayjs(end) : dayjs().endOf("week");

  const fixedPeriods = useMemo(() => {
    const endOfThisMonth = dayjs().endOf("month");
    const startofthisMonth = dayjs().startOf("month");

    const endOfLastmonth = dayjs().subtract(1, "month").endOf("month");
    const startOfLastmonth = dayjs().subtract(1, "month").startOf("month");

    const endOfThisWeek = dayjs().endOf("week");
    const startOfThisWeek = dayjs().startOf("week");

    const endOfLastWeek = dayjs().subtract(1, "week").endOf("week");
    const startOfLastWeek = dayjs().subtract(1, "week").startOf("week");

    const allDates = [
      endOfThisMonth,
      startofthisMonth,
      endOfLastmonth,
      startOfLastmonth,
      endOfThisWeek,
      startOfThisWeek,
      endOfLastWeek,
      startOfLastWeek
    ];
    const start = dayjs.min(allDates);
    const end = dayjs.max(allDates);
    return {
      start,
      end,
      endOfThisMonth,
      startofthisMonth,
      endOfLastmonth,
      startOfLastmonth,
      endOfThisWeek,
      startOfThisWeek,
      endOfLastWeek,
      startOfLastWeek
    };
  }, []);

  const { loading, error, data } = useQuery(QUERY_TIME_TICKETS_IN_RANGE_SB, {
    variables: {
      start: startDate.format("YYYY-MM-DD"),
      end: endDate.format("YYYY-MM-DD"),
      fixedStart: fixedPeriods.start.format("YYYY-MM-DD"),
      fixedEnd: fixedPeriods.end.format("YYYY-MM-DD"),
      jobStart: startDate,
      jobEnd: endDate
    },
    fetchPolicy: "network-only",
    nextFetchPolicy: "network-only",
    pollInterval: 60000 * 5,
    skip: !fixedPeriods
  });

  const calculatedData = useMemo(() => {
    if (!data) return [];
    const ret = {
      totalThisWeek: 0,
      totalLastWeek: 0,
      totalThisMonth: 0,
      totalLastMonth: 0,
      totalOverPeriod: 0,
      actualTotalOverPeriod: 0,
      totalEffieciencyOverPeriod: 0,
      employees: {}
    };
    data.fixedperiod.forEach((ticket) => {
      const ticketDate = dayjs(ticket.date);

      if (!ret.employees[ticket.employee.employee_number]) {
        ret.employees[ticket.employee.employee_number] = {
          totalThisWeek: 0,
          totalLastWeek: 0,
          totalThisMonth: 0,
          totalLastMonth: 0,
          totalOverPeriod: 0,
          actualTotalOverPeriod: 0,
          totalEffieciencyOverPeriod: 0
        };
      }

      if (ticketDate.isBetween(fixedPeriods.startOfThisWeek, fixedPeriods.endOfThisWeek, undefined, "[]")) {
        ret.totalThisWeek = ret.totalThisWeek + ticket.productivehrs;
        ret.employees[ticket.employee.employee_number].totalThisWeek =
          ret.employees[ticket.employee.employee_number].totalThisWeek + ticket.productivehrs;
      } else if (ticketDate.isBetween(fixedPeriods.startOfLastWeek, fixedPeriods.endOfLastWeek, undefined, "[]")) {
        ret.totalLastWeek = ret.totalLastWeek + ticket.productivehrs;
        ret.employees[ticket.employee.employee_number].totalLastWeek =
          ret.employees[ticket.employee.employee_number].totalLastWeek + ticket.productivehrs;
      }
      if (ticketDate.isBetween(fixedPeriods.startofthisMonth, fixedPeriods.endOfThisMonth, undefined, "[]")) {
        ret.totalThisMonth = ret.totalThisMonth + ticket.productivehrs;
        ret.employees[ticket.employee.employee_number].totalThisMonth =
          ret.employees[ticket.employee.employee_number].totalThisMonth + ticket.productivehrs;
      } else if (ticketDate.isBetween(fixedPeriods.startOfLastmonth, fixedPeriods.endOfLastmonth, undefined, "[]")) {
        ret.totalLastMonth = ret.totalLastMonth + ticket.productivehrs;
        ret.employees[ticket.employee.employee_number].totalLastMonth =
          ret.employees[ticket.employee.employee_number].totalLastMonth + ticket.productivehrs;
      }
    });

    const ticketsGroupedByDate = _.groupBy(data.timetickets, "date");
    const listOfDays = Utils.ListDaysBetween({
      start: startDate,
      end: endDate
    });

    const employees = [];
    const ret2 = [];
    let totals = {
      totalproductive: 0,
      totalactual: 0,
      employees: {}
    };

    listOfDays.forEach((day) => {
      const r = {
        date: dayjs(day).format("MM/DD"),
        actualtotal: 0,
        productivetotal: 0,
        employees: {}
      };

      if (ticketsGroupedByDate[day]) {
        ticketsGroupedByDate[day].forEach((ticket) => {
          r.actualtotal = r.actualtotal + ticket.actualhrs;
          r.productivetotal = r.productivetotal + ticket.productivehrs;
          totals.totalactual = totals.totalactual + ticket.actualhrs;
          totals.totalproductive = totals.totalproductive + ticket.productivehrs;

          employees.push(ticket.employee.employee_number);
          //Add to table data.
          ret.employees[ticket.employee.employee_number].totalOverPeriod =
            ret.employees[ticket.employee.employee_number].totalOverPeriod + ticket.productivehrs;
          ret.employees[ticket.employee.employee_number].actualTotalOverPeriod =
            ret.employees[ticket.employee.employee_number].actualTotalOverPeriod + (ticket.actualhrs || 0);

          if (!totals.employees[ticket.employee.employee_number])
            totals.employees[ticket.employee.employee_number] = {
              totalactual: 0,
              totalproductive: 0
            };

          if (!r.employees[ticket.employee.employee_number])
            r.employees[ticket.employee.employee_number] = {
              actual: 0,
              productive: 0
            };

          //Add to totals.
          totals.employees[ticket.employee.employee_number].totalproductive =
            totals.employees[ticket.employee.employee_number].totalproductive + ticket.productivehrs;

          totals.employees[ticket.employee.employee_number].totalactual =
            totals.employees[ticket.employee.employee_number].totalactual + ticket.actualhrs;
          //Add to dailys.
          r.employees[ticket.employee.employee_number].productive =
            r.employees[ticket.employee.employee_number].productive + ticket.productivehrs;

          r.employees[ticket.employee.employee_number].actual =
            r.employees[ticket.employee.employee_number].actual + ticket.actualhrs;
        });
      }

      ret2.push(r);
    });

    // Add total efficiency of employees
    const totalActualAndProductive = Object.keys(ret.employees)
      .map((key) => {
        return { employee_number: key, ...ret.employees[key] };
      })
      .reduce(
        (acc, e) => {
          return {
            totalOverPeriod: acc.totalOverPeriod + e.totalOverPeriod,
            actualTotalOverPeriod: acc.actualTotalOverPeriod + e.actualTotalOverPeriod
          };
        },
        { totalOverPeriod: 0, actualTotalOverPeriod: 0 }
      );

    ret.totalEffieciencyOverPeriod = totalActualAndProductive.actualTotalOverPeriod
      ? (totalActualAndProductive.totalOverPeriod / totalActualAndProductive.actualTotalOverPeriod) * 100
      : 0;

    roundObject(ret);
    roundObject(totals);
    roundObject(ret2);

    return {
      fixed: ret,
      timeperiod: {
        totals,
        chartData: ret2,
        employees: _.uniq(employees),
        colors: getColorArray(employees.length)
      }
    };
  }, [fixedPeriods, data, startDate, endDate]);

  if (error) return <AlertComponent title={error.message} type="error" />;
  if (loading) return <LoadingSpinner />;
  return (
    <Row gutter={[16, 16]}>
      <Col span={24}>
        <ScoreboardTicketsStats data={calculatedData.fixed} />
      </Col>
      <Col span={24}>
        <ScoreboardTicketsBar start={startDate} end={endDate} data={calculatedData.timeperiod} />
      </Col>
    </Row>
  );
}

//Include a filter by employee.

//Hours produced today.
//Hours produced in last 7 days
//Hours produced for time period by day
//Hours produced by employee by day for time period.

function getColorArray() {
  return [
    "#3366cc",
    "#dc3912",
    "#ff9900",
    "#109618",
    "#990099",
    "#0099c6",
    "#dd4477",
    "#66aa00",
    "#b82e2e",
    "#316395",
    "#3366cc",
    "#994499",
    "#22aa99",
    "#aaaa11",
    "#6633cc",
    "#e67300",
    "#8b0707",
    "#651067",
    "#329262",
    "#5574a6",
    "#3b3eac",
    "#b77322",
    "#16d620",
    "#b91383",
    "#f4359e",
    "#9c5935",
    "#a9c413",
    "#2a778d",
    "#668d1c",
    "#bea413",
    "#0c5922",
    "#743411"
  ];
  // var result = [];
  // for (var i = 0; i < num; i += 1) {
  //   var letters = "0123456789ABCDEF".split("");
  //   var color = "#";
  //   for (var j = 0; j < 6; j += 1) {
  //     color += letters[Math.floor(Math.random() * 16)];
  //   }
  //   result.push(color);
  // }
  // return result;
}

function roundObject(inputObj) {
  for (var key of Object.keys(inputObj)) {
    if (typeof inputObj[key] === "number" && inputObj[key] !== 0) {
      inputObj[key] = inputObj[key] && inputObj[key].toFixed ? inputObj[key].toFixed(1) : inputObj[key]; //Math.round(inputObj[key] * 100) / 100;
    } else if (Array.isArray(inputObj[key])) {
      inputObj[key].forEach((item) => roundObject(item));
    } else if (typeof inputObj[key] === "object") {
      roundObject(inputObj[key]);
    }
  }
}
