import React, { ReactNode } from 'react';
import styled from 'styled-components';

import type { CatalogEntityConfig, EntitiesCatalogConfig } from '@redocly/config';
import type { BffCatalogEntity } from '@redocly/theme/core/types';

import { CatalogOwnersCell } from '@redocly/theme/components/Catalog/CatalogTableView/CatalogOwnersCell';
import { CatalogDomainsCell } from '@redocly/theme/components/Catalog/CatalogTableView/CatalogDomainsCell';
import { CatalogEntityCell } from '@redocly/theme/components/Catalog/CatalogTableView/CatalogEntityCell';
import { CatalogTableHeaderCell } from '@redocly/theme/components/Catalog/CatalogTableView/CatalogTableHeaderCell';
import { CatalogTagsCell } from '@redocly/theme/components/Catalog/CatalogTableView/CatalogTagsCell';
import { CatalogTableViewRow } from '@redocly/theme/components/Catalog/CatalogTableView/CatalogTableViewRow';
import { CatalogEntityTypeTag } from '@redocly/theme/components/Catalog/CatalogEntityTypeTag';
import { breakpoints } from '@redocly/theme/core';
import { CatalogLastUpdateCell } from '@redocly/theme/components/Catalog/CatalogTableView/CatalogLastUpdateCell';

export type BaseEntity = {
  id: string;
  key: string;
  type: string;
  title: string;
  summary?: string | null;
};

export type CatalogTableViewProps<T extends BaseEntity> = {
  entities: T[];
  entitiesCatalogConfig?: EntitiesCatalogConfig;
  catalogConfig: CatalogEntityConfig;
  columns?: CatalogColumn<T>[];
  currentSortOption?: string | null;
  onRowClick?: (entity: T) => void;
  handleSortClick: (sortKey: string, direction: 'asc' | 'desc') => void;
  isColumnSorted: (sortKey: string, direction: 'asc' | 'desc') => boolean;
  style?: React.CSSProperties;
  contentMinWidth?: number;
};

export type CatalogColumn<T> = {
  key: string;
  title: string;
  render: (entity: T) => ReactNode;
  width?: string;
  minWidth?: string;
  sortable?: boolean;
  sortKey?: string;
};

const baseColumns: CatalogColumn<BffCatalogEntity>[] = [
  {
    key: 'entity',
    title: 'Entity',
    render: (entity) => <CatalogEntityCell entity={entity} />,
    width: '3fr',
    minWidth: '164px',
    sortable: true,
    sortKey: 'title',
  },
  {
    key: 'type',
    title: 'Type',
    render: (entity) => <CatalogEntityTypeTag entityType={entity.type} />,
    width: '2fr',
    minWidth: '162px',
    sortable: true,
    sortKey: 'type',
  },
  {
    key: 'domains',
    title: 'Domains',
    render: (entity) => (
      <CatalogDomainsCell domains={entity.domains?.map((domain) => domain.title) || []} />
    ),
    width: '2fr',
    minWidth: '162px',
  },
  {
    key: 'owners',
    title: 'Owners',
    render: (entity) => (
      <CatalogOwnersCell owners={entity.owners?.map((owner) => owner.title) || []} />
    ),
    width: '2fr',
    minWidth: '162px',
  },
  {
    key: 'tags',
    title: 'Tags',
    render: (entity) => <CatalogTagsCell entity={entity} />,
    width: '2fr',
    minWidth: '160px',
  },
  {
    key: 'lastUpdate',
    title: 'Last update',
    render: (entity) => <CatalogLastUpdateCell lastModified={entity.updatedAt} />,
    width: '1fr',
    minWidth: '112px',
    sortable: true,
    sortKey: 'updated_at',
  },
];

export const CatalogTableView = <T extends BaseEntity>({
  entities,
  entitiesCatalogConfig,
  catalogConfig,
  columns = baseColumns as CatalogColumn<BaseEntity>[],
  currentSortOption,
  onRowClick,
  handleSortClick,
  isColumnSorted,
  style,
  contentMinWidth,
}: CatalogTableViewProps<T>) => {
  const tableContent = (
    <>
      <CatalogTableHeader
        columnsWidths={columns.map((column) => column.width || '1fr')}
        columnsMinWidths={columns.map((column) => column.minWidth || 'auto')}
      >
        {columns.map((column) => (
          <CatalogTableHeaderCell<T>
            key={column.key}
            column={column}
            currentSortOption={currentSortOption}
            handleSortClick={handleSortClick}
            isColumnSorted={isColumnSorted}
          />
        ))}
      </CatalogTableHeader>
      <CatalogTableBody>
        {entities.map((entity) => (
          <CatalogTableViewRow
            key={entity.id}
            entity={entity}
            entitiesCatalogConfig={entitiesCatalogConfig}
            catalogConfig={catalogConfig}
            columns={columns}
            onRowClick={onRowClick}
          />
        ))}
      </CatalogTableBody>
    </>
  );

  return (
    <CatalogTableWrapper data-component-name="Catalog/CatalogTableView" style={style}>
      {contentMinWidth != null ? (
        <CatalogTableContentInner $contentMinWidth={contentMinWidth}>
          {tableContent}
        </CatalogTableContentInner>
      ) : (
        <CatalogTableScrollContent>{tableContent}</CatalogTableScrollContent>
      )}
    </CatalogTableWrapper>
  );
};

const CatalogTableWrapper = styled.div`
  width: 100%;
  border-bottom: 1px solid var(--catalog-table-border-color);
  overflow-x: auto;

  @media screen and (max-width: ${breakpoints.medium}) {
    margin-top: 0;
  }
`;

const CatalogTableScrollContent = styled.div`
  min-width: min-content;
`;

const CatalogTableContentInner = styled.div<{ $contentMinWidth: number }>`
  min-width: ${({ $contentMinWidth }) => $contentMinWidth}px;
`;

const CatalogTableHeader = styled.div<{ columnsWidths: string[]; columnsMinWidths: string[] }>`
  display: grid;
  grid-template-columns: ${({ columnsWidths, columnsMinWidths }) =>
    columnsWidths
      .map((width, index) =>
        columnsMinWidths[index] !== 'auto' ? `minmax(${columnsMinWidths[index]}, ${width})` : width,
      )
      .join(' ')};
  background: var(--catalog-table-header-bg-color);
  font-weight: var(--catalog-table-header-font-weight);
  border-radius: var(--border-radius) var(--border-radius) 0 0;
`;

const CatalogTableBody = styled.div`
  min-width: min-content;
`;
