import {
  Box,
  Button,
  Link,
  Skeleton,
  Table,
  TableBody,
  TableCell,
  tableCellClasses,
  TableContainer,
  TableHead,
  TableRow,
  TableSortLabel,
  Typography
} from '@mui/material';

import { Pagination } from '../../common/Pagination';
import { DEFAULT_COLUMNS } from '../constants';
import type { InventoryResult, SortState } from '../types';

const isSafeHref = (href: string) => /^https?:\/\//i.test(href) || href.startsWith('/');

const parser = new DOMParser();

// Some cells (e.g. Host name) arrive as an HTML anchor string. Parse it with
// DOMParser (no injection) into a real MUI Link; everything else is plain text.
const renderCell = (value: string | number | null) => {
  if (typeof value !== 'string' || !value.includes('<a')) return value ?? '';
  const anchor = parser.parseFromString(value, 'text/html').querySelector('a');
  const href = anchor?.getAttribute('href');
  if (!anchor || !href || !isSafeHref(href)) return anchor?.textContent ?? value;
  // A real anchor on purpose: the host page lives outside this bundle.
  return <Link href={href}>{anchor.textContent}</Link>;
};

interface HostsResultTableProps {
  loading: boolean;
  onChangePage: (page: number) => void;
  onChangeRowsPerPage: (value: number) => void;
  onOpenReport: () => void;
  onSort: (column: string) => void;
  page: number;
  result: InventoryResult;
  rowsPerPage: number;
  sort: SortState;
}

const tableContainerSx = {
  border: 1,
  borderColor: 'divider',
  borderRadius: '4px'
} as const;

const tableSx = {
  [`& .${tableCellClasses.root}`]: { borderColor: 'divider' },
  [`& tbody tr:last-child .${tableCellClasses.root}`]: { borderBottom: 'none' }
} as const;

const SKELETON_ROW_COUNT = 5;

const SkeletonRows = ({ columnCount }: { columnCount: number }) => (
  <>
    {Array.from({ length: SKELETON_ROW_COUNT }, (_, row) => (
      <TableRow key={row}>
        {Array.from({ length: columnCount }, (_, column) => (
          <TableCell key={column}>
            <Skeleton />
          </TableCell>
        ))}
      </TableRow>
    ))}
  </>
);

export const HostsResultTable = ({ result, sort, loading, page, rowsPerPage, onSort, onChangePage, onChangeRowsPerPage, onOpenReport }: HostsResultTableProps) => {
  // The requested columns are known before the first response, so a loading
  // table keeps its header and only swaps the rows for skeletons.
  const columns = result.header.length > 0 ? result.header.map(({ columnName }) => columnName) : DEFAULT_COLUMNS;

  return (
    <Box>
      <Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 1 }}>
        <Typography variant="h2">
          Hosts
        </Typography>
        <Button
          size="small"
          variant="outlined"
          sx={{ color: 'text.primary', borderColor: 'divider', fontWeight: 500, '&:hover': { borderColor: 'text.secondary', backgroundColor: 'action.hover' } }}
          onClick={onOpenReport}
        >
          Open inventory report
        </Button>
      </Box>

      {!loading && result.rowCount === 0 ? (
        <Typography align="center" variant="h6" sx={{ my: 3 }}>
          No hosts found
        </Typography>
      ) : (
        <>
          <TableContainer sx={tableContainerSx}>
            <Table size="small" sx={tableSx}>
              <TableHead>
                <TableRow>
                  {columns.map(column => (
                    <TableCell key={column} sortDirection={sort.column === column ? (sort.descending ? 'desc' : 'asc') : false}>
                      <TableSortLabel
                        active={sort.column === column}
                        direction={sort.column === column && sort.descending ? 'desc' : 'asc'}
                        onClick={() => onSort(column)}
                      >
                        {column}
                      </TableSortLabel>
                    </TableCell>
                  ))}
                </TableRow>
              </TableHead>
              <TableBody>
                {loading ? (
                  <SkeletonRows columnCount={columns.length} />
                ) : (
                  result.rows.map((row, rowIndex) => (
                    <TableRow key={rowIndex} hover>
                      {columns.map((column, columnIndex) => (
                        <TableCell key={column}>{renderCell(row[columnIndex])}</TableCell>
                      ))}
                    </TableRow>
                  ))
                )}
              </TableBody>
            </Table>
          </TableContainer>
          <Pagination
            align="left"
            count={result.rowCount}
            page={page}
            rowsPerPage={rowsPerPage}
            onChangePage={onChangePage}
            onChangeRowsPerPage={onChangeRowsPerPage}
          />
        </>
      )}
    </Box>
  );
};
