import { SyncOutlined } from "@ant-design/icons";
import { useQuery } from "@apollo/client/react";
import { Button, Card, Checkbox, Input, Space, Typography } from "antd";
import _ from "lodash";
import queryString from "query-string";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { Link, useLocation, useNavigate } from "react-router-dom";
import { createStructuredSelector } from "reselect";
import AlertComponent from "../../components/alert/alert.component";
import ResponsiveTable from "../../components/responsive-table/responsive-table.component";
import { QUERY_EXPORT_LOG_PAGINATED } from "../../graphql/accounting.queries";
import { DateTimeFormatter } from "../../utils/DateFormatter";
import { pageLimit } from "../../utils/config";
import { alphaSort, dateSort } from "./../../utils/sorters";

const mapStateToProps = createStructuredSelector({});

export function ExportLogsPageComponent() {
  const searchParams = queryString.parse(useLocation().search);
  const { page, sortcolumn, sortorder, search, pageSize } = searchParams;
  const history = useNavigate();

  const currentPage = Number.parseInt(page || "1", 10);
  const parsedPageSize = Number.parseInt(pageSize || String(pageLimit), 10);
  const currentPageSize = Number.isNaN(parsedPageSize) ? pageLimit : parsedPageSize;

  const { loading, error, data, refetch } = useQuery(QUERY_EXPORT_LOG_PAGINATED, {
    fetchPolicy: "network-only",
    nextFetchPolicy: "network-only",
    variables: {
      search: search || "",
      offset: (currentPage - 1) * currentPageSize,
      limit: currentPageSize,
      order: [
        {
          ...(sortcolumn === "ro_number"
            ? {
                job: {
                  [sortcolumn || "created_at"]: sortorder ? (sortorder === "descend" ? "desc" : "asc") : "desc"
                }
              }
            : sortcolumn === "invoice_number"
              ? {
                  bill: {
                    [sortcolumn || "created_at"]: sortorder ? (sortorder === "descend" ? "desc" : "asc") : "desc"
                  }
                }
              : sortcolumn === "paymentnum"
                ? {
                    payment: {
                      [sortcolumn || "created_at"]: sortorder ? (sortorder === "descend" ? "desc" : "asc") : "desc"
                    }
                  }
                : {
                    [sortcolumn || "created_at"]: sortorder ? (sortorder === "descend" ? "desc" : "asc") : "desc"
                  })
        }
      ]
    }
  });

  const { t } = useTranslation();

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

  const handleTableChange = (pagination, filters, sorter) => {
    const nextPageSize = pagination?.pageSize || currentPageSize;
    const pageSizeChanged = nextPageSize !== currentPageSize;

    searchParams.pageSize = nextPageSize;
    searchParams.page = pageSizeChanged ? 1 : pagination.current;
    searchParams.sortcolumn = sorter.columnKey;
    searchParams.sortorder = sorter.order;
    if (filters.status) {
      searchParams.statusFilters = JSON.stringify(_.flattenDeep(filters.status));
    } else {
      delete searchParams.statusFilters;
    }
    history({ search: queryString.stringify(searchParams) });
  };

  const columns = [
    {
      title: t("general.labels.created_at"),
      dataIndex: "created_at",
      key: "created_at",
      sorter: (a, b) => dateSort(a.created_at, b.created_at),
      sortOrder: sortcolumn === "created_at" && sortorder,
      render: (text, record) => <DateTimeFormatter>{record.created_at}</DateTimeFormatter>
    },
    {
      title: t("employees.fields.user_email"),
      dataIndex: "useremail",
      key: "useremail"
    },
    {
      title: t("jobs.fields.ro_number"),
      dataIndex: "ro_number",
      key: "ro_number",
      sorter: (a, b) => alphaSort(a.ro_number, b.ro_number),
      sortOrder: sortcolumn === "ro_number" && sortorder,
      render: (text, record) =>
        record.job && (
          <Link to={`/manage/jobs/${record.job.id}`}>{record.job?.ro_number || t("general.labels.na")}</Link>
        )
    },
    {
      title: t("bills.fields.invoice_number"),
      dataIndex: "invoice_number",
      key: "invoice_number",
      sorter: (a, b) => alphaSort(a.invoice_number, b.invoice_number),
      sortOrder: sortcolumn === "invoice_number" && sortorder,
      render: (text, record) =>
        record.bill && <Link to={"/manage/bills?billid=" + record.bill?.id}>{record.bill?.invoice_number}</Link>
    },
    {
      title: t("payments.fields.paymentnum"),
      dataIndex: "paymentnum",
      key: "paymentnum",
      sorter: (a, b) => alphaSort(a.paymentnum, b.paymentnum),
      sortOrder: sortcolumn === "paymentnum" && sortorder,
      render: (text, record) =>
        record.payment && (
          <Link to={"/manage/payments?search=" + record.payment?.paymentnum}>{record.payment?.paymentnum}</Link>
        )
    },
    {
      title: t("general.labels.successful"),
      dataIndex: "successful",
      key: "successful",
      sorter: (a, b) => Number(a.successful) - Number(b.successful),
      sortOrder: sortcolumn === "successful" && sortorder,
      filters: [
        { text: "True", value: true },
        { text: "False", value: false }
      ],
      onFilter: (value, record) => record.successful === value,
      render: (text, record) => <Checkbox checked={record.successful} />
    },
    {
      title: t("general.labels.message"),
      dataIndex: "message",
      key: "message",
      render: (text, record) => {
        if (!record.message) return null;
        const message = JSON.parse(record.message);
        if (Array.isArray(message)) {
          return (
            <div>
              <ul>
                {message.map((m, idx) => (
                  <li key={idx}>{typeof m === "object" ? JSON.stringify(m) : m}</li>
                ))}
              </ul>
            </div>
          );
        } else {
          return <div>{typeof message === "object" ? JSON.stringify(message) : message}</div>;
        }
      }
    }
  ];

  return (
    <Card
      extra={
        <Space wrap>
          {searchParams.search && (
            <>
              <Typography.Title level={4}>
                {t("general.labels.searchresults", {
                  search: searchParams.search
                })}
              </Typography.Title>
              <Button
                onClick={() => {
                  delete searchParams.search;
                  history({ search: queryString.stringify(searchParams) });
                }}
              >
                {t("general.actions.clear")}
              </Button>
            </>
          )}
          <Button onClick={() => refetch()} icon={<SyncOutlined />} />
          <Input.Search
            placeholder={searchParams.search || t("general.labels.search")}
            onSearch={(value) => {
              searchParams.search = value;
              history({ search: queryString.stringify(searchParams) });
            }}
            enterButton
          />
        </Space>
      }
    >
      <ResponsiveTable
        loading={loading}
        pagination={{
          placement: "top",
          pageSize: currentPageSize,
          current: currentPage,
          showSizeChanger: true,
          total: data && data.search_exportlog_aggregate.aggregate.count
        }}
        columns={columns}
        mobileColumnKeys={["created_at", "ro_number", "successful", "message"]}
        rowKey="id"
        dataSource={data?.search_exportlog}
        style={{ height: "100%" }}
        scroll={{ x: true }}
        onChange={handleTableChange}
      />
    </Card>
  );
}

export default connect(mapStateToProps, null)(ExportLogsPageComponent);
