import React, { useCallback, useMemo } from "react";
import Column from "../../../components/common/columns";
import Table, { PublishedTableProps } from "../../../components/common/Table";
import { Paginated } from "../../../services/Paginated";
import { AuditLogEntry } from "../services/auditService";
import { Namespaces } from "../../../i18n/i18n";
import { useTranslation } from "react-i18next";

interface AuditFieldValues {
  OldDisplayName?: string;
  OldValue?: string;
  NewDisplayName?: string;
  NewValue?: string;
}

interface AuditFieldChanges {
  [fieldname: string]: AuditFieldValues;
}

interface AuditFieldChangeValues {
  fieldName: string;
  oldDisplayName?: string;
  oldValue?: string;
  newDisplayName?: string;
  newValue?: string;
}

export default function AuditTable(props: PublishedTableProps<AuditLogEntry>) {
  const { data, sortColumn, onChangePage, onSearch, onSort } = props;
  const { t } = useTranslation<typeof Namespaces.Common>();

  const fieldColumns: Column<AuditFieldChangeValues>[] = useMemo(
    () => [
      { key: "fieldName", label: t("Field") },
      {
        key: "oldDisplayName",
        label: t("OldValue"),
        content: (item) => {
          if (item.oldDisplayName !== undefined)
            return <>{item.oldDisplayName}</>;
          return (
            <>{item.oldValue !== undefined ? String(item.oldValue) : ""}</>
          );
        },
      },
      {
        key: "newDisplayName",
        label: t("NewValue"),
        content: (item) => {
          if (item.newDisplayName !== undefined)
            return <>{item.newDisplayName}</>;
          return (
            <>{item.newValue !== undefined ? String(item.newValue) : ""}</>
          );
        },
      },
    ],
    [t],
  );

  const columns: Column<AuditLogEntry>[] = useMemo(
    () => [
      { key: "dateTime", label: t("Timing"), order: "asc", searchable: false },
      { key: "userDisplayName", label: t("User Name"), order: "asc" },
      { key: "comment", label: t("Comment"), order: "asc" },
      {
        key: "entityDisplayName",
        label: t("EntityDisplayName"),
        order: "asc",
        searchable: false,
      },
      { key: "type", label: t("Type"), order: "asc" },
      { key: "displayName", label: t("DisplayName"), order: "asc" },
      {
        key: "fields",
        label: t("Changes"),
        order: "asc",
        searchable: false,
        content: (item) => {
          if (
            (item.type === "Delete" || item.type === "Purge") &&
            item.displayName !== ""
          ) {
            return <></>;
          }

          const fieldsObject: AuditFieldChanges = JSON.parse(item!.fields);
          const data: AuditFieldChangeValues[] = [];

          Object.keys(fieldsObject).forEach((key) => {
            const dataItem: AuditFieldChangeValues = {
              fieldName: key,
              oldValue: fieldsObject[key].OldValue,
              oldDisplayName: fieldsObject[key].OldDisplayName,
              newValue: fieldsObject[key].NewValue,
              newDisplayName: fieldsObject[key].NewDisplayName,
            };
            data.push(dataItem);
          });

          const paginated: Paginated<AuditFieldChangeValues> = {
            count: 0,
            page: 1,
            pageSize: 10,
            totalPages: 0,
            data,
          };

          let displayColumns: Column<AuditFieldChangeValues>[] = [
            ...fieldColumns,
          ];

          if (item.type === "Create" || item.type === "Restore") {
            displayColumns = displayColumns.filter(
              (x) => x.key !== "oldDisplayName",
            );
          }

          if (item.type === "Delete" || item.type === "Purge") {
            displayColumns = displayColumns.filter(
              (x) => x.key !== "newDisplayName",
            );
          }

          return (
            <Table data={paginated} keyName="id" columns={displayColumns} />
          );
        },
      },
    ],
    [fieldColumns, t],
  );

  const raiseSort = useCallback(
    (sortCol: Column<AuditLogEntry>) => {
      if (onSort !== undefined) onSort(sortCol);
    },
    [onSort],
  );

  const handleAuditParams = useCallback((item: any) => {
    return {
      entityName: item.entityName,
      primaryKey: item.primaryKey,
    };
  }, []);

  return (
    <Table
      data={data}
      keyName="id"
      columns={columns}
      sortColumn={sortColumn}
      onSort={raiseSort}
      onChangePage={onChangePage}
      onSearch={onSearch}
      onAuditParams={handleAuditParams}
      secondaryAudit={true}
    />
  );
}
