import { Card, Col, Row } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import _ from "lodash";
import dayjs from "../../utils/day";
import { useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { onlyUnique } from "../../utils/arrayHelper";
import { alphaSort } from "../../utils/sorters";
import { TemplateList } from "../../utils/TemplateConstants";
import PrintWrapperComponent from "../print-wrapper/print-wrapper.component";
import Dinero from "dinero.js";
import InstanceRenderManager from "../../utils/instanceRenderMgr";

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

export function TimeTicketsSummaryEmployees({ loading, timetickets, startDate, endDate }) {
  //Group everything by employee
  //Then sum the individual time TimeTicketsSummary.

  //Calculate job based tickets.
  const jobTicketsByEmployee = {};
  timetickets
    .filter((i) => i.cost_center !== "timetickets.labels.shift")
    .map((tt) => {
      if (!jobTicketsByEmployee[tt.employeeid]) {
        jobTicketsByEmployee[tt.employeeid] = [];
      }
      jobTicketsByEmployee[tt.employeeid].push(tt);
      return null;
    });
  const jobTickets = Object.keys(jobTicketsByEmployee).map(function (key) {
    return {
      jobKey: key,
      employee: jobTicketsByEmployee[key][0].employee,
      tickets: jobTicketsByEmployee[key]
    };
  });

  //Calculate shift based tickets.
  const shiftTicketsByEmployee = {};
  timetickets
    .filter((i) => i.cost_center === "timetickets.labels.shift")
    .map((tt) => {
      if (!shiftTicketsByEmployee[tt.employeeid]) {
        shiftTicketsByEmployee[tt.employeeid] = [];
      }
      shiftTicketsByEmployee[tt.employeeid].push(tt);
      return null;
    });
  const shiftTickets = Object.keys(shiftTicketsByEmployee).map(function (key) {
    return {
      employee: shiftTicketsByEmployee[key][0].employee,
      tickets: shiftTicketsByEmployee[key]
    };
  });

  return (
    <Row gutter={[16, 16]}>
      <Col span={24}>
        <JobRelatedTicketsTable loading={loading} jobTickets={jobTickets} startDate={startDate} endDate={endDate} />
      </Col>
      <Col span={24}>
        <ShiftRelatedTicketsTable
          loading={loading}
          shiftTickets={shiftTickets}
          startDate={startDate}
          endDate={endDate}
        />
      </Col>
    </Row>
  );
}

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

const JobRelatedTicketsTable = ({ loading, jobTickets, startDate, endDate }) => {
  const Templates = TemplateList();
  const { t } = useTranslation();
  const [state, setState] = useState({
    sortedInfo: {}
  });
  const data = useMemo(() => {
    return _.flatten(
      jobTickets.map((item) => {
        const employeeCostCenters = item.tickets.map((i) => i.cost_center).filter(onlyUnique);

        return employeeCostCenters.map((costCenter) => {
          const actHrs = item.tickets
            .filter((ticket) => ticket.cost_center === costCenter)
            .reduce((acc, val) => acc + val.actualhrs, 0);

          const prodHrs = item.tickets
            .filter((ticket) => ticket.cost_center === costCenter)
            .reduce((acc, val) => acc + val.productivehrs, 0);

          const clockHrs = item.tickets
            .filter((ticket) => ticket.cost_center === costCenter)
            .reduce((acc, val) => {
              if (!!val.clockoff && !!val.clockon)
                return acc + dayjs(val.clockoff).diff(dayjs(val.clockon), "hour", true);
              return acc;
            }, 0);

          const pay = item.tickets
            .filter((ticket) => ticket.cost_center === costCenter)
            .reduce((acc, val) => {
              return acc.add(
                Dinero({ amount: Math.round(val.rate * 100) }).multiply(
                  val.flat_rate ? val.productivehrs : val.actualhrs
                )
              );
            }, Dinero());

          return {
            id: `${item.jobKey}${costCenter}`,
            costCenter,
            item,
            actHrs: actHrs.toFixed(1),
            prodHrs: prodHrs.toFixed(1),
            clockHrs,
            ...InstanceRenderManager({ imex: {}, rome: { pay } })
          };
        });
      })
    );
  }, [jobTickets]);

  const columns = [
    {
      title: t("employees.labels.name"),
      dataIndex: "empname",
      key: "empname",
      sorter: (a, b) => alphaSort(a.item.employee.last_name, b.item.employee.last_name),
      sortOrder: state.sortedInfo.columnKey === "empname" && state.sortedInfo.order,
      render: (text, record) =>
        `${record.item.employee.first_name} ${record.item.employee.last_name} ${
          record.costCenter ? `(${record.costCenter})` : ""
        }`.trim()
    },
    {
      title: t("timetickets.fields.actualhrs"),
      dataIndex: "actHrs",
      key: "actHrs",
      sorter: (a, b) => a.actHrs - b.actHrs,
      sortOrder: state.sortedInfo.columnKey === "actHrs" && state.sortedInfo.order
    },
    {
      title: t("timetickets.fields.productivehrs"),
      dataIndex: "prodHrs",
      key: "prodHrs",
      sorter: (a, b) => a.prodHrs - b.prodHrs,
      sortOrder: state.sortedInfo.columnKey === "prodHrs" && state.sortedInfo.order
    },
    {
      title: t("timetickets.fields.efficiency"),
      dataIndex: "total",
      key: "total",
      sorter: (a, b) =>
        (a.actHrs === 0 || !a.actHrs ? 0 : (a.prodHrs / a.actHrs) * 100) -
        (b.actHrs === 0 || !b.actHrs ? 0 : (b.prodHrs / b.actHrs) * 100),
      sortOrder: state.sortedInfo.columnKey === "total" && state.sortedInfo.order,
      render: (text, record) =>
        record.actHrs === 0 || !record.actHrs ? "∞" : ((record.prodHrs / record.actHrs) * 100).toFixed(2)
    },
    {
      title: t("timetickets.fields.clockhours"),
      dataIndex: "clockHrs",
      key: "clockHrs",
      sorter: (a, b) => a.clockHrs - b.clockHrs,
      sortOrder: state.sortedInfo.columnKey === "clockHrs" && state.sortedInfo.order,
      render: (text, record) => record.clockHrs.toFixed(2)
    },
    ...InstanceRenderManager({
      imex: [],
      rome: [
        {
          title: "Pay",
          dataIndex: "Pay",
          key: "Pay",
          sorter: (a, b) => a.clockHrs - b.clockHrs,
          sortOrder: state.sortedInfo.columnKey === "clockHrs" && state.sortedInfo.order,
          render: (text, record) => record.pay.toFormat("$0.00")
        }
      ]
    }),
    {
      title: t("general.labels.actions"),
      dataIndex: "actions",
      key: "actions",
      render: (text, record) => (
        <PrintWrapperComponent
          templateObject={{
            name: Templates.timetickets_employee.key,
            variables: {
              id: record.item.employee.id,
              start: startDate,
              end: endDate
            }
          }}
          messageObject={{ subject: Templates.timetickets_employee.subject }}
        />
      )
    }
  ];

  const handleTableChange = (pagination, filters, sorter) => {
    setState({ ...state, filteredInfo: filters, sortedInfo: sorter });
  };

  return (
    <Card title={t("timetickets.labels.jobhours")}>
      <ResponsiveTable
        loading={loading}
        scroll={{
          x: true // y: "50rem"
        }}
        columns={columns}
        mobileColumnKeys={["total", "actions", "empname", "actHrs"]}
        rowKey="id"
        dataSource={data}
        onChange={handleTableChange}
      />
    </Card>
  );
};

const ShiftRelatedTicketsTable = ({ loading, shiftTickets, startDate, endDate }) => {
  const Templates = TemplateList();
  const { t } = useTranslation();
  const [state, setState] = useState({
    sortedInfo: {}
  });
  const data = useMemo(() => {
    return shiftTickets.map((item) => {
      const clockHrs = item.tickets.reduce((acc, val) => {
        if (!!val.clockoff && !!val.clockon) return acc + dayjs(val.clockoff).diff(dayjs(val.clockon), "hour", true);
        return acc;
      }, 0);

      return { id: item.employee.id, item, clockHrs };
    });
  }, [shiftTickets]);

  const columns = [
    {
      title: t("employees.labels.name"),
      dataIndex: "empname",
      key: "empname",
      sorter: (a, b) => alphaSort(a.empname, b.empname),
      sortOrder: state.sortedInfo.columnKey === "empname" && state.sortedInfo.order,
      render: (text, record) => `${record.item.employee.first_name} ${record.item.employee.last_name}`
    },

    {
      title: t("timetickets.fields.clockhours"),
      dataIndex: "clockHrs",
      key: "clockHrs",
      sorter: (a, b) => a.clockHrs - b.clockHrs,
      sortOrder: state.sortedInfo.columnKey === "clockHrs" && state.sortedInfo.order,
      render: (text, record) => record.clockHrs.toFixed(2)
    },
    {
      title: t("general.labels.actions"),
      dataIndex: "actions",
      key: "actions",
      render: (text, record) => (
        <PrintWrapperComponent
          templateObject={{
            name: Templates.attendance_employee.key,
            variables: {
              id: record.item.employee.id,
              start: startDate,
              end: endDate
            }
          }}
          messageObject={{ subject: Templates.attendance_employee.subject }}
        />
      )
    }
  ];

  const handleTableChange = (pagination, filters, sorter) => {
    setState({ ...state, filteredInfo: filters, sortedInfo: sorter });
  };

  return (
    <Card title={t("timetickets.labels.clockhours")}>
      <ResponsiveTable
        loading={loading}
        scroll={{
          x: true // y: "50rem"
        }}
        columns={columns}
        mobileColumnKeys={["total", "actions", "empname", "actHrs"]}
        rowKey="id"
        dataSource={data}
        onChange={handleTableChange}
      />
    </Card>
  );
};
