import { type FC, useCallback, useMemo, useState } from 'react';
import { FormProvider, type UseFormReturn, useForm } from 'react-hook-form';

import { zodResolver } from '@hookform/resolvers/zod';
import { type TFunction } from 'i18next';
import { type HuTableSortingHeaderProps } from '@material-hu/hooks/TableSorting/useHuServerTableSorting';
import {
  type FormValues,
  type PaginationControllerProps,
  type SearchControllerProps,
} from '@material-hu/hooks/useHuPagination';
import {
  IconAlertSquareRounded,
  IconColumns2,
  IconCopy,
  IconEdit,
  IconFileDownload,
  IconFileTypePdf,
  IconFilter,
  IconInfoCircle,
  IconToggleLeft,
  IconToggleRight,
  IconTrash,
} from '@material-hu/icons/tabler';
import { useTheme } from '@material-hu/mui/index';
import Stack from '@material-hu/mui/Stack/Stack';

import HuStateCard from '@material-hu/components/composed-components/StateCard';
import Button from '@material-hu/components/design-system/Buttons/Button';
import HuTable from '@material-hu/components/design-system/Table';
import HuTableBody from '@material-hu/components/design-system/Table/components/TableBody';
import HuTableCell from '@material-hu/components/design-system/Table/components/TableCell';
import HuTableContainer from '@material-hu/components/design-system/Table/components/TableContainer';
import HuTableHead from '@material-hu/components/design-system/Table/components/TableHead';
import HuTableRow from '@material-hu/components/design-system/Table/components/TableRow';

import useAuth from 'src/contexts/JWTContext';
import useFeatureFlag from 'src/hooks/useFeatureFlag';
import { FeatureFlags } from 'src/types/featureFlags';
import { insertIf } from 'src/utils/arrayUtils';
import { useLokaliseTranslation } from 'src/utils/i18n';
import { type PaginatedResponse } from 'src/utils/tableUtils';

import BadgeCountButton from '../../AgentManagement/components/BadgeCountButton';
import { SERVICE_TABLE_COLUMNS } from '../../constants';
import useServiceMgmtPermissions from '../../hooks/useServiceMgmtPermissions';
import {
  type DownloadCertificatesForm,
  type DownloadReportForm,
  ServiceItemStatus,
  type ServiceItemTableData,
  ServicesSortingCriteria,
} from '../../types';
import { getDefaultEmail, isCreatedRequest } from '../../utils';
import {
  downloadCertificatesSchema,
  downloadServiceItemReportSchema,
} from '../form/schemas';
import useServiceTableColumns from '../hooks/useServiceTableColumns';
import { type ServiceFilters } from '../ServiceItems';

import ColumnConfigDrawer from './ColumnConfigDrawer';
import DownloadServiceCertificateDrawer from './DownloadServiceCertificateDrawer';
import DownloadServiceReportDrawer from './DownloadServiceReportDrawer';
import ServiceFiltersDrawer from './ServiceFiltersDrawer';
import {
  FIRST_COLUMN_MIN_WIDTH,
  LAST_COLUMN_MIN_WIDTH,
  STICKY_LEFT_SX,
  STICKY_RIGHT_SX,
} from './ServicesTable.constants';
import ServicesTableRow from './ServicesTableRow';
import ServiceTableSkeleton from './ServiceTableSkeleton';
import TagsMenu from './TagMenu';

type Props = {
  isLoading: boolean;
  isError: boolean;
  isEmpty: boolean;
  isPreviousData: boolean;
  data: PaginatedResponse<ServiceItemTableData> | undefined;
  handleEdit: () => void;
  handleDuplicate: (serviceItem: ServiceItemTableData) => void;
  handleToggleStatus: (serviceItem: ServiceItemTableData) => void;
  handleDelete: () => void;
  selectedServiceItem: ServiceItemTableData | null;
  setSelectedServiceItem: (serviceItem: ServiceItemTableData) => void;
  totalPages: number;
  onApplyFilters: () => void;
  onResetFilters: () => void;
  onRestoreFilters: () => void;
  appliedFilters: ServiceFilters | null;
  onTagDeleted?: (tagId: string) => void;
  Search: (props: SearchControllerProps) => JSX.Element;
  Pagination: (props: PaginationControllerProps) => JSX.Element;
  SortingHeader: (props: HuTableSortingHeaderProps) => JSX.Element;
  paginationForm: UseFormReturn<FormValues, unknown, undefined>;
  getSortingHeaderTooltip: (id: ServicesSortingCriteria) => string | undefined;
};

const ServicesTable: FC<Props> = ({
  isLoading,
  isError,
  isEmpty,
  isPreviousData,
  data,
  handleEdit,
  handleDuplicate,
  handleToggleStatus,
  handleDelete,
  selectedServiceItem,
  setSelectedServiceItem,
  totalPages,
  onApplyFilters,
  onResetFilters,
  onRestoreFilters,
  appliedFilters,
  onTagDeleted,
  Pagination,
  Search,
  SortingHeader,
  paginationForm,
  getSortingHeaderTooltip,
}) => {
  const theme = useTheme();
  const { t } = useLokaliseTranslation([
    'service_management',
    'general',
    'workflows',
  ]);
  const { user } = useAuth();

  const { disabledColumns, isLoading: isLoadingDisabledColumns } =
    useServiceTableColumns();
  const [openColumnConfigDrawer, setOpenColumnConfigDrawer] = useState(false);

  const canDownloadCertificatesZipped = useFeatureFlag(
    FeatureFlags.DOWNLOAD_CERTIFICATES_ZIPPED_ENABLED,
  );

  const isColumnVisible = useCallback(
    (col: string) => !disabledColumns.includes(col),
    [disabledColumns],
  );
  const visibleColumnCount =
    SERVICE_TABLE_COLUMNS.filter(col => !disabledColumns.includes(col)).length +
    (isColumnVisible('visibility') ? 1 : 0);

  const showCategoryColumn = isColumnVisible('category');
  const showStatusColumn = isColumnVisible('status');
  const showCreatedAtColumn = isColumnVisible('createdAt');
  const showLastUpdatedColumn = isColumnVisible('lastUpdated');
  const showVisibilityColumn = isColumnVisible('visibility');
  const showTagsColumn = isColumnVisible('tags');

  const [tagsMenuAnchorEl, setTagsMenuAnchorEl] = useState<null | HTMLElement>(
    null,
  );
  const [tagsMenuServiceItem, setTagsMenuServiceItem] =
    useState<ServiceItemTableData | null>(null);
  const [openFiltersDrawer, setOpenFiltersDrawer] = useState(false);
  const [downloadReportDrawerOpen, setDownloadReportDrawerOpen] =
    useState(false);
  const [downloadCertificatesDrawerOpen, setDownloadCertificatesDrawerOpen] =
    useState(false);
  const [hoveredRow, setHoveredRow] = useState<string | null>(null);

  const {
    canEditServiceItems,
    canCreateServiceItems,
    canDeleteServiceItems,
    canDownloadServiceItemsReport,
  } = useServiceMgmtPermissions();

  // Will be updated once the Table header is updated to use the new theme colors
  const BG_HEADER_COLOR = `${theme.palette.new.background.layout.default} !important`;

  const downloadReportResolver = useMemo(
    () => zodResolver(downloadServiceItemReportSchema(t as TFunction)),
    [t],
  );

  const downloadCertificatesResolver = useMemo(
    () => zodResolver(downloadCertificatesSchema(t as TFunction)),
    [t],
  );

  const downloadReportForm = useForm<DownloadReportForm>({
    defaultValues: {
      email: getDefaultEmail(user),
      includeSegmentations: false,
      segmentations: [],
      includeProfileFields: false,
      profileFields: [],
      statesIn: [],
      createdAtFrom: null,
      createdAtTo: null,
      dateOptions: {
        lastSevenDays: false,
        lastThirtyDays: false,
        lastSixMonths: true,
        dateRange: false,
      },
    },
    resolver: downloadReportResolver,
    mode: 'onChange',
  });

  const downloadCertificatesForm = useForm<DownloadCertificatesForm>({
    defaultValues: {
      email: getDefaultEmail(user),
      statesIn: [],
      createdAtFrom: null,
      createdAtTo: null,
      dateOptions: {
        lastSevenDays: false,
        lastThirtyDays: false,
        lastSixMonths: true,
        dateRange: false,
      },
    },
    resolver: downloadCertificatesResolver,
    mode: 'onChange',
  });

  const showDownloadMenuItem =
    canDownloadCertificatesZipped && canDownloadServiceItemsReport;

  const getActions = useCallback(
    (serviceItem: ServiceItemTableData) => [
      ...insertIf(canEditServiceItems || canCreateServiceItems, {
        onClick: () => handleEdit(),
        title: t('general:edit'),
        Icon: IconEdit,
      }),
      ...insertIf(canEditServiceItems || canCreateServiceItems, {
        onClick: () => handleDuplicate(serviceItem),
        title: t('general:duplicate'),
        Icon: IconCopy,
      }),
      ...insertIf(
        isCreatedRequest(serviceItem) &&
          (canEditServiceItems || canCreateServiceItems),
        {
          onClick: () => handleToggleStatus(serviceItem),
          title: t(`toggle_${serviceItem.status}`),
          Icon:
            serviceItem.status === ServiceItemStatus.ACTIVE
              ? IconToggleLeft
              : IconToggleRight,
        },
      ),
      ...insertIf(canDeleteServiceItems, {
        onClick: handleDelete,
        title: t('general:delete'),
        Icon: IconTrash,
      }),
      ...insertIf(
        canDownloadServiceItemsReport &&
          !canDownloadCertificatesZipped &&
          isCreatedRequest(serviceItem),
        {
          onClick: () => setDownloadReportDrawerOpen(true),
          title: t('download_report'),
          Icon: IconFileDownload,
        },
      ),
      ...insertIf(isCreatedRequest(serviceItem) && showDownloadMenuItem, {
        onClick: () => setDownloadCertificatesDrawerOpen(true),
        title: t('general:download'),
        Icon: IconFileDownload,
        options: [
          ...insertIf(canDownloadCertificatesZipped, {
            onClick: () => setDownloadCertificatesDrawerOpen(true),
            title: t('download_certificate.title'),
            Icon: IconFileTypePdf,
          }),
          ...insertIf(canDownloadServiceItemsReport, {
            onClick: () => setDownloadReportDrawerOpen(true),
            title: t('download_report'),
            Icon: IconFileDownload,
          }),
        ],
      }),
    ],
    [
      canEditServiceItems,
      canCreateServiceItems,
      canDeleteServiceItems,
      canDownloadServiceItemsReport,
      canDownloadCertificatesZipped,
      showDownloadMenuItem,
      handleEdit,
      handleDuplicate,
      handleToggleStatus,
      handleDelete,
      t,
    ],
  );

  const handleOpenTagsMenu = useCallback(
    (
      serviceItem: ServiceItemTableData,
      e: React.MouseEvent<HTMLDivElement>,
    ) => {
      e.stopPropagation();
      setTagsMenuAnchorEl(e.currentTarget);
      setTagsMenuServiceItem(serviceItem);
    },
    [],
  );

  const handleCloseTagsMenu = useCallback(() => {
    setTagsMenuAnchorEl(null);
    setTagsMenuServiceItem(null);
  }, []);

  const handleRowActionMenuClick = useCallback(
    (serviceItem: ServiceItemTableData) => {
      setSelectedServiceItem(serviceItem);
      handleCloseTagsMenu();
    },
    [setSelectedServiceItem, handleCloseTagsMenu],
  );

  const appliedFiltersCount = useMemo(() => {
    if (!appliedFilters) return 0;

    let count = 0;

    if (appliedFilters.statuses.length > 0) count++;
    if (appliedFilters.tags.length > 0) count++;
    if (appliedFilters.createdBy.length > 0) count++;

    // Creation date counts as max 1 if any dateOption is true OR any date is set
    const hasDateOption = Object.values(appliedFilters.dateOptions).some(
      value => value,
    );
    const hasCreationDate =
      appliedFilters.creationDateFrom !== null ||
      appliedFilters.creationDateTo !== null;

    if (hasDateOption || hasCreationDate) count++;

    return count;
  }, [appliedFilters]);

  const handleCloseFilters = () => {
    setOpenFiltersDrawer(false);
    onRestoreFilters();
  };

  const handleApplyFilters = () => {
    onApplyFilters();
    setOpenFiltersDrawer(false);
  };

  const showLoadingSkeleton = isLoading || isLoadingDisabledColumns;

  const canEditOrCreateTags = canCreateServiceItems || canEditServiceItems;

  return (
    <Stack sx={{ gap: 3 }}>
      <FormProvider {...downloadReportForm}>
        <DownloadServiceReportDrawer
          open={downloadReportDrawerOpen}
          onClose={() => setDownloadReportDrawerOpen(false)}
          serviceItemId={selectedServiceItem?.id ?? ''}
        />
      </FormProvider>
      <FormProvider {...downloadCertificatesForm}>
        <DownloadServiceCertificateDrawer
          open={downloadCertificatesDrawerOpen}
          onClose={() => setDownloadCertificatesDrawerOpen(false)}
          serviceItemId={selectedServiceItem?.id ?? ''}
        />
      </FormProvider>
      <ServiceFiltersDrawer
        open={openFiltersDrawer}
        onClose={handleCloseFilters}
        onApply={handleApplyFilters}
        onReset={onResetFilters}
      />
      <ColumnConfigDrawer
        open={openColumnConfigDrawer}
        onClose={() => setOpenColumnConfigDrawer(false)}
        disabledColumns={disabledColumns}
      />
      <Stack sx={{ flexDirection: 'row', alignItems: 'center', gap: 1 }}>
        <FormProvider {...paginationForm}>
          <Search inputProps={{ placeholder: t('general:search') }} />
        </FormProvider>
        <BadgeCountButton
          buttonText={t('general:filter')}
          count={appliedFiltersCount}
          buttonProps={{
            variant: 'secondary',
            startIcon: <IconFilter size={16} />,
            onClick: () => setOpenFiltersDrawer(true),
          }}
        />
        <Button
          variant="secondary"
          aria-label={t('configure_columns')}
          onClick={() => setOpenColumnConfigDrawer(true)}
          startIcon={<IconColumns2 size={16} />}
        >
          {t('columns')}
        </Button>
      </Stack>
      {showLoadingSkeleton && <ServiceTableSkeleton />}
      {!showLoadingSkeleton && (
        <>
          <HuTableContainer
            sx={{
              overflowX: 'auto',
              position: 'relative',
            }}
          >
            <HuTable
              sx={{
                minWidth: 900,
              }}
              stickyHeader
            >
              <HuTableHead>
                <HuTableRow
                  headerRow
                  sx={{
                    '& > *': {
                      backgroundColor: BG_HEADER_COLOR,
                    },
                  }}
                >
                  <SortingHeader
                    id={ServicesSortingCriteria.NAME}
                    sx={{
                      minWidth: FIRST_COLUMN_MIN_WIDTH,
                      ...STICKY_LEFT_SX,
                      borderRight: ({ palette }) =>
                        `1px solid ${palette.new.border.neutral.default}`,
                      zIndex: 3,
                    }}
                  >
                    {t('service_item')}
                  </SortingHeader>
                  {isColumnVisible('category') && (
                    <HuTableCell
                      headerCell
                      sx={{
                        minWidth: 160,
                        backgroundColor: BG_HEADER_COLOR,
                      }}
                    >
                      {t('general:category')}
                    </HuTableCell>
                  )}
                  {isColumnVisible('status') && (
                    <HuTableCell
                      headerCell
                      sx={{
                        backgroundColor: BG_HEADER_COLOR,
                      }}
                    >
                      {t('status')}
                    </HuTableCell>
                  )}
                  {isColumnVisible('createdAt') && (
                    <SortingHeader
                      id={ServicesSortingCriteria.CREATED_AT}
                      tooltipTitle={getSortingHeaderTooltip(
                        ServicesSortingCriteria.CREATED_AT,
                      )}
                      sx={{
                        minWidth: 160,
                        backgroundColor: BG_HEADER_COLOR,
                      }}
                    >
                      {t('created_at')}
                    </SortingHeader>
                  )}
                  {isColumnVisible('lastUpdated') && (
                    <SortingHeader
                      id={ServicesSortingCriteria.UPDATED_AT}
                      tooltipTitle={getSortingHeaderTooltip(
                        ServicesSortingCriteria.UPDATED_AT,
                      )}
                      sx={{
                        minWidth: 160,
                        backgroundColor: BG_HEADER_COLOR,
                      }}
                    >
                      {t('last_updated')}
                    </SortingHeader>
                  )}
                  {isColumnVisible('visibility') && (
                    <HuTableCell
                      aria-label={t('general:visibility')}
                      sx={{
                        backgroundColor: BG_HEADER_COLOR,
                      }}
                    />
                  )}
                  {isColumnVisible('tags') && (
                    <HuTableCell
                      headerCell
                      sx={{
                        minWidth: 160,
                        backgroundColor: BG_HEADER_COLOR,
                      }}
                    >
                      {t('tags')}
                    </HuTableCell>
                  )}
                  <HuTableCell
                    headerCell
                    align="right"
                    aria-label={t('actions')}
                    sx={{
                      minWidth: LAST_COLUMN_MIN_WIDTH,
                      borderLeft: ({ palette }) =>
                        `1px solid ${palette.new.border.neutral.default}`,
                      ...STICKY_RIGHT_SX,
                      zIndex: 3,
                    }}
                  />
                </HuTableRow>
              </HuTableHead>
              <HuTableBody
                sx={{
                  opacity: isPreviousData ? 0.5 : 1,
                  width: 1,
                }}
              >
                {data?.items?.map(serviceItem => (
                  <ServicesTableRow
                    key={serviceItem.id}
                    serviceItem={serviceItem}
                    isHovered={hoveredRow === serviceItem.id}
                    isTagsMenuActive={
                      tagsMenuServiceItem?.id === serviceItem.id
                    }
                    canEditOrCreateTags={canEditOrCreateTags}
                    getActions={getActions}
                    showCategoryColumn={showCategoryColumn}
                    showStatusColumn={showStatusColumn}
                    showCreatedAtColumn={showCreatedAtColumn}
                    showLastUpdatedColumn={showLastUpdatedColumn}
                    showVisibilityColumn={showVisibilityColumn}
                    showTagsColumn={showTagsColumn}
                    setHoveredRow={setHoveredRow}
                    onOpenTagsMenu={handleOpenTagsMenu}
                    onActionMenuClick={handleRowActionMenuClick}
                  />
                ))}
                {isEmpty && (
                  <HuTableRow>
                    <HuTableCell
                      align="center"
                      colSpan={visibleColumnCount}
                    >
                      <HuStateCard
                        slotProps={{
                          title: {
                            title: t('empty_search_service_item_list_title'),
                            description: t('try_again_later'),
                          },
                          avatar: {
                            color: 'primary',
                            Icon: IconInfoCircle,
                          },
                        }}
                        sx={{
                          p: 0,
                          border: 'none',
                        }}
                      />
                    </HuTableCell>
                  </HuTableRow>
                )}
                {isError && (
                  <HuTableRow>
                    <HuTableCell
                      align="center"
                      colSpan={visibleColumnCount}
                    >
                      <HuStateCard
                        slotProps={{
                          title: {
                            title: t('error_service_item_list_title'),
                            description: t('try_again_later'),
                          },
                          avatar: {
                            color: 'error',
                            Icon: IconAlertSquareRounded,
                          },
                        }}
                        sx={{
                          p: 0,
                          border: 'none',
                        }}
                      />
                    </HuTableCell>
                  </HuTableRow>
                )}
              </HuTableBody>
            </HuTable>
          </HuTableContainer>
          <FormProvider {...paginationForm}>
            <Pagination
              inputProps={{
                totalPages: totalPages || 0,
                type: 'changer',
              }}
            />
          </FormProvider>
          <TagsMenu
            anchorEl={tagsMenuAnchorEl}
            serviceItem={tagsMenuServiceItem}
            onClose={handleCloseTagsMenu}
            onTagDeleted={onTagDeleted}
          />
        </>
      )}
    </Stack>
  );
};

export default ServicesTable;
