import { Server } from 'lucide-react';
import { useCurrentStateAndParams } from '@uirouter/react';
import { useMemo } from 'react';
import { Pod } from 'kubernetes-types/core/v1';

import { IndexOptional } from '@CE/react/kubernetes/configs/types';
import { createStore } from '@CE/react/kubernetes/datatables/default-kube-datatable-store';
import { useEnvironmentId } from '@CE/react/hooks/useEnvironmentId';
import { useEnvironment } from '@CE/react/portainer/environments/queries';

import {
  Datatable,
  TableSettingsMenu,
  TableSettingsMenuAutoRefresh,
} from '@@CE/datatables';
import { useTableState } from '@@CE/datatables/useTableState';

import { useApplication } from '../../queries/useApplication';
import { useApplicationPods } from '../../queries/useApplicationPods';

import { ContainerRowData } from './types';
import { getColumns } from './columns';
import { computeContainerStatus } from './computeContainerStatus';

const storageKey = 'k8sContainersDatatable';
const settingsStore = createStore(storageKey);

export function ApplicationContainersDatatable() {
  const environmentId = useEnvironmentId();
  const useServerMetricsQuery = useEnvironment(
    environmentId,
    (env) => !!env?.Kubernetes?.Configuration.UseServerMetrics
  );
  const tableState = useTableState(settingsStore, storageKey);
  const {
    params: { name, namespace, 'resource-type': resourceType },
  } = useCurrentStateAndParams();

  // get the containers from the aapplication pods
  const applicationQuery = useApplication(
    environmentId,
    namespace,
    name,
    resourceType,
    {
      autoRefreshRate: tableState.autoRefreshRate * 1000,
    }
  );
  const podsQuery = useApplicationPods(
    environmentId,
    namespace,
    name,
    applicationQuery.data,
    {
      autoRefreshRate: tableState.autoRefreshRate * 1000,
    }
  );
  const appContainers = useContainersRowData(podsQuery.data);

  return (
    <Datatable<IndexOptional<ContainerRowData>>
      dataset={appContainers}
      columns={getColumns(!!useServerMetricsQuery.data)}
      settingsManager={tableState}
      isLoading={
        applicationQuery.isLoading ||
        podsQuery.isLoading ||
        useServerMetricsQuery.isLoading
      }
      title="Application containers"
      titleIcon={Server}
      getRowId={(row) => row.podName} // use pod name because it's unique (name is not unique)
      disableSelect
      data-cy="k8s-application-containers-datatable"
      renderTableSettings={() => (
        <TableSettingsMenu>
          <TableSettingsMenuAutoRefresh
            value={tableState.autoRefreshRate}
            onChange={(value) => tableState.setAutoRefreshRate(value)}
          />
        </TableSettingsMenu>
      )}
    />
  );
}

// useContainersRowData row data gets the pod.spec?.containers and pod.spec?.initContainers from an array of pods
// it then appends the podName, nodeName, podId, creationDate, and status to each container
function useContainersRowData(pods?: Pod[]): ContainerRowData[] {
  return (
    useMemo(
      () =>
        pods?.flatMap((pod) => {
          const containers = [
            ...(pod.spec?.containers?.map((c) => ({ ...c, isInit: false })) ||
              []),
            ...(pod.spec?.initContainers?.map((c) => ({
              ...c,
              isInit: true,
              // https://kubernetes.io/docs/concepts/workloads/pods/sidecar-containers/#sidecar-containers-and-pod-lifecycle
              isSidecar: c.restartPolicy === 'Always',
            })) || []),
          ];
          return containers.map((container) => ({
            ...container,
            podName: pod.metadata?.name ?? '',
            nodeName: pod.spec?.nodeName ?? '',
            podIp: pod.status?.podIP ?? '',
            creationDate: pod.status?.startTime ?? '',
            status: computeContainerStatus(
              container.name,
              pod.status?.containerStatuses,
              pod.status?.initContainerStatuses
            ),
          }));
        }) || [],
      [pods]
    ) || []
  );
}
