/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { Button, ButtonGroup, Intent, Label, MenuItem, Tag } from '@blueprintjs/core';
import { IconNames } from '@blueprintjs/icons';
import { formatDistanceToNow } from 'date-fns';
import React, { type ReactNode } from 'react';
import type { Filter } from 'react-table';
import ReactTable from 'react-table';

import {
  ACTION_COLUMN_ID,
  ACTION_COLUMN_LABEL,
  ACTION_COLUMN_WIDTH,
  ActionCell,
  MoreButton,
  RefreshButton,
  TableClickableCell,
  TableColumnSelector,
  TableFilterableCell,
  ViewControlBar,
} from '../../components';
import { AlertDialog, AsyncActionDialog, SpecDialog, TaskTableActionDialog } from '../../dialogs';
import type { QueryWithContext } from '../../druid-models';
import {
  getConsoleViewIcon,
  TASK_CANCELED_ERROR_MESSAGES,
  TASK_CANCELED_PREDICATE,
} from '../../druid-models';
import type { Capabilities } from '../../helpers';
import {
  SMALL_TABLE_PAGE_SIZE,
  SMALL_TABLE_PAGE_SIZE_OPTIONS,
  suggestibleFilterInput,
} from '../../react-table';
import { Api, AppToaster } from '../../singletons';
import {
  formatDuration,
  getApiArray,
  getDruidErrorMessage,
  hasOverlayOpen,
  LocalStorageBackedVisibility,
  LocalStorageKeys,
  oneOf,
  queryDruidSql,
  QueryManager,
  QueryState,
} from '../../utils';
import type { BasicAction } from '../../utils/basic-action';
import { ExecutionDetailsDialog } from '../workbench-view/execution-details-dialog/execution-details-dialog';

import './tasks-view.scss';

const taskTableColumns: string[] = [
  'Task ID',
  'Group ID',
  'Type',
  'Datasource',
  'Status',
  'Error',
  'Created time',
  'Duration',
  'Location',
];

interface TaskQueryResultRow {
  task_id: string;
  group_id: string;
  type: string;
  created_time: string;
  datasource: string;
  duration: number;
  error_msg: string | null;
  location: string | null;
  status: string;
}

export interface TasksViewProps {
  filters: Filter[];
  onFiltersChange(filters: Filter[]): void;
  openTaskDialog: boolean | undefined;
  goToDatasource(datasource: string): void;
  goToQuery(queryWithContext: QueryWithContext): void;
  goToClassicBatchDataLoader(taskId?: string): void;
  capabilities: Capabilities;
}

export interface TasksViewState {
  tasksState: QueryState<TaskQueryResultRow[]>;

  groupTasksBy?: 'group_id' | 'type' | 'datasource' | 'status';

  killTaskId?: string;

  taskSpecDialogOpen: boolean;
  alertErrorMsg?: string;

  taskTableActionDialogOpen?: { id: string; status: string; actions: BasicAction[] };
  executionDialogOpen?: string;
  visibleColumns: LocalStorageBackedVisibility;
}

function statusToColor(status: string): string {
  switch (status) {
    case 'RUNNING':
      return '#2167d5';
    case 'WAITING':
      return '#d5631a';
    case 'PENDING':
      return '#ffbf00';
    case 'SUCCESS':
      return '#57d500';
    case 'FAILED':
      return '#d5100a';
    case 'CANCELED':
      return '#858585';
    default:
      return '#0a1500';
  }
}

export class TasksView extends React.PureComponent<TasksViewProps, TasksViewState> {
  private readonly taskQueryManager: QueryManager<Capabilities, TaskQueryResultRow[]>;
  static statusRanking: Record<string, number> = {
    RUNNING: 4,
    PENDING: 3,
    WAITING: 2,
    SUCCESS: 1,
    FAILED: 1,
  };

  static TASK_SQL = `WITH tasks AS (SELECT
  "task_id", "group_id", "type", "datasource", "created_time", "location", "duration", "error_msg",
  CASE WHEN ${TASK_CANCELED_PREDICATE} THEN 'CANCELED' WHEN "status" = 'RUNNING' THEN "runner_status" ELSE "status" END AS "status"
  FROM sys.tasks
)
SELECT "task_id", "group_id", "type", "datasource", "created_time", "location", "duration", "error_msg", "status"
FROM tasks
ORDER BY
  (
    CASE "status"
    WHEN 'RUNNING' THEN 4
    WHEN 'PENDING' THEN 3
    WHEN 'WAITING' THEN 2
    ELSE 1
    END
  ) DESC,
  "created_time" DESC`;

  constructor(props: TasksViewProps) {
    super(props);

    this.state = {
      tasksState: QueryState.INIT,

      taskSpecDialogOpen: Boolean(props.openTaskDialog),

      visibleColumns: new LocalStorageBackedVisibility(
        LocalStorageKeys.TASK_TABLE_COLUMN_SELECTION,
        ['Error'],
      ),
    };

    this.taskQueryManager = new QueryManager({
      processQuery: async (capabilities, signal) => {
        if (capabilities.hasSql()) {
          return await queryDruidSql(
            {
              query: TasksView.TASK_SQL,
            },
            signal,
          );
        } else if (capabilities.hasOverlordAccess()) {
          return (await getApiArray(`/druid/indexer/v1/tasks`, signal)).map(d => {
            return {
              task_id: d.id,
              group_id: d.groupId,
              type: d.type,
              created_time: d.createdTime,
              datasource: d.dataSource,
              duration: d.duration ? d.duration : 0,
              error_msg: d.errorMsg,
              location: d.location.host ? `${d.location.host}:${d.location.port}` : null,
              status: d.statusCode === 'RUNNING' ? d.runnerStatusCode : d.statusCode,
            };
          });
        } else {
          throw new Error(`must have SQL or overlord access`);
        }
      },
      onStateChange: tasksState => {
        this.setState({
          tasksState,
        });
      },
    });
  }

  componentDidMount(): void {
    const { capabilities } = this.props;

    this.taskQueryManager.runQuery(capabilities);
  }

  componentWillUnmount(): void {
    this.taskQueryManager.terminate();
  }

  private readonly closeSpecDialogs = () => {
    this.setState({
      taskSpecDialogOpen: false,
    });
  };

  private readonly submitTask = async (spec: JSON) => {
    try {
      await Api.instance.post('/druid/indexer/v1/task', spec);
    } catch (e) {
      AppToaster.show({
        message: `Failed to submit task: ${getDruidErrorMessage(e)}`,
        intent: Intent.DANGER,
      });
      return;
    }

    AppToaster.show({
      message: 'Task submitted successfully',
      intent: Intent.SUCCESS,
    });
    this.taskQueryManager.rerunLastQuery();
  };

  private getTaskActions(
    id: string,
    datasource: string,
    status: string,
    type: string,
    fromTable?: boolean,
  ): BasicAction[] {
    const { goToDatasource, goToClassicBatchDataLoader } = this.props;

    const actions: BasicAction[] = [];
    if (fromTable) {
      actions.push({
        icon: IconNames.SEARCH_TEMPLATE,
        title: 'View raw details',
        onAction: () => {
          this.setState({
            taskTableActionDialogOpen: {
              id,
              status,
              actions: this.getTaskActions(id, datasource, status, type),
            },
          });
        },
      });
    }
    if (datasource && status === 'SUCCESS') {
      actions.push({
        icon: IconNames.MULTI_SELECT,
        title: 'Go to datasource',
        onAction: () => goToDatasource(datasource),
      });
    }
    if (oneOf(type, 'index', 'index_parallel')) {
      actions.push({
        icon: IconNames.CLOUD_UPLOAD,
        title: 'Open in data loader',
        onAction: () => goToClassicBatchDataLoader(id),
      });
    }
    if (oneOf(status, 'RUNNING', 'WAITING', 'PENDING')) {
      actions.push({
        icon: IconNames.CROSS,
        title: 'Kill',
        intent: Intent.DANGER,
        onAction: () => this.setState({ killTaskId: id }),
      });
    }
    return actions;
  }

  renderKillTaskAction() {
    const { killTaskId } = this.state;
    if (!killTaskId) return;

    return (
      <AsyncActionDialog
        action={async () => {
          const resp = await Api.instance.post(
            `/druid/indexer/v1/task/${Api.encodePath(killTaskId)}/shutdown`,
            {},
          );
          return resp.data;
        }}
        confirmButtonText="Kill task"
        successText="Task was killed"
        failText="Could not kill task"
        intent={Intent.DANGER}
        onClose={() => {
          this.setState({ killTaskId: undefined });
        }}
        onSuccess={() => {
          this.taskQueryManager.rerunLastQuery();
        }}
      >
        <p>
          Are you sure you want to kill task <Tag minimal>{killTaskId}</Tag>?
        </p>
      </AsyncActionDialog>
    );
  }

  private renderTaskFilterableCell(
    field: string,
    enableComparisons = false,
    valueFn: (value: string) => ReactNode = String,
  ) {
    const { filters, onFiltersChange } = this.props;

    return function TaskFilterableCell(row: { value: any }) {
      return (
        <TableFilterableCell
          field={field}
          value={row.value}
          filters={filters}
          onFiltersChange={onFiltersChange}
          enableComparisons={enableComparisons}
        >
          {valueFn(row.value)}
        </TableFilterableCell>
      );
    };
  }

  private onTaskDetail(task: TaskQueryResultRow) {
    if (task.type === 'query_controller') {
      this.setState({
        executionDialogOpen: task.task_id,
      });
    } else {
      this.setState({
        taskTableActionDialogOpen: {
          id: task.task_id,
          status: task.status,
          actions: this.getTaskActions(task.task_id, task.datasource, task.status, task.type),
        },
      });
    }
  }

  private renderTaskTable() {
    const { filters, onFiltersChange } = this.props;
    const { tasksState, groupTasksBy, visibleColumns } = this.state;

    const tasks = tasksState.data || [];
    return (
      <ReactTable
        data={tasks}
        loading={tasksState.loading}
        noDataText={tasksState.isEmpty() ? 'No tasks' : tasksState.getErrorMessage() || ''}
        filterable
        filtered={filters}
        onFilteredChange={onFiltersChange}
        defaultSorted={[{ id: 'status', desc: true }]}
        pivotBy={groupTasksBy ? [groupTasksBy] : []}
        defaultPageSize={SMALL_TABLE_PAGE_SIZE}
        pageSizeOptions={SMALL_TABLE_PAGE_SIZE_OPTIONS}
        showPagination={tasks.length > SMALL_TABLE_PAGE_SIZE}
        columns={[
          {
            Header: 'Task ID',
            accessor: 'task_id',
            width: 440,
            Cell: ({ value, original }) => (
              <TableClickableCell
                tooltip="Show detail"
                onClick={() => this.onTaskDetail(original)}
                hoverIcon={IconNames.SEARCH_TEMPLATE}
              >
                {value}
              </TableClickableCell>
            ),
            Aggregated: () => '',
            show: visibleColumns.shown('Task ID'),
          },
          {
            Header: 'Group ID',
            accessor: 'group_id',
            width: 300,
            Cell: this.renderTaskFilterableCell('group_id'),
            Aggregated: () => '',
            show: visibleColumns.shown('Group ID'),
          },
          {
            Header: 'Type',
            accessor: 'type',
            width: 140,
            Cell: this.renderTaskFilterableCell('type'),
            show: visibleColumns.shown('Type'),
          },
          {
            Header: 'Datasource',
            accessor: 'datasource',
            width: 200,
            Cell: this.renderTaskFilterableCell('datasource'),
            show: visibleColumns.shown('Datasource'),
          },
          {
            Header: 'Status',
            id: 'status',
            width: 110,
            Filter: suggestibleFilterInput([
              'CANCELED',
              'FAILED',
              'PENDING',
              'RUNNING',
              'SUCCESS',
              'WAITING',
            ]),
            accessor: row => ({
              status: row.status,
              created_time: row.created_time,
              toString: () => row.status,
            }),
            Cell: row => {
              if (row.aggregated) return '';
              const { status, error_msg } = row.original;
              const errorMsg =
                error_msg && !TASK_CANCELED_ERROR_MESSAGES.includes(error_msg)
                  ? error_msg
                  : undefined;
              return (
                <TableFilterableCell
                  field="status"
                  value={status}
                  filters={filters}
                  onFiltersChange={onFiltersChange}
                >
                  <span data-tooltip={errorMsg}>
                    <span style={{ color: statusToColor(status) }}>&#x25cf;&nbsp;</span>
                    {status}
                    {errorMsg && (
                      <a onClick={() => this.setState({ alertErrorMsg: errorMsg })}>&nbsp;?</a>
                    )}
                  </span>
                </TableFilterableCell>
              );
            },
            sortMethod: (d1, d2) => {
              const typeofD1 = typeof d1;
              const typeofD2 = typeof d2;
              if (typeofD1 !== typeofD2) return 0;
              switch (typeofD1) {
                case 'string':
                  return TasksView.statusRanking[d1] - TasksView.statusRanking[d2];

                case 'object':
                  return (
                    TasksView.statusRanking[d1.status] - TasksView.statusRanking[d2.status] ||
                    d1.created_time.localeCompare(d2.created_time)
                  );

                default:
                  return 0;
              }
            },
            show: visibleColumns.shown('Status'),
          },
          {
            Header: 'Error',
            id: 'error',
            accessor: row => row.error_msg || '',
            width: 300,
            Cell: this.renderTaskFilterableCell('error'),
            Aggregated: () => '',
            show: visibleColumns.shown('Error'),
          },
          {
            Header: 'Created time',
            accessor: 'created_time',
            width: 190,
            Cell: this.renderTaskFilterableCell('created_time', true, value => {
              const valueAsDate = new Date(value);
              return isNaN(valueAsDate.valueOf()) ? (
                String(value)
              ) : (
                <span data-tooltip={formatDistanceToNow(valueAsDate, { addSuffix: true })}>
                  {value}
                </span>
              );
            }),
            Aggregated: () => '',
            show: visibleColumns.shown('Created time'),
          },
          {
            Header: 'Duration',
            accessor: 'duration',
            width: 80,
            filterable: false,
            className: 'padded',
            Cell({ value, original, aggregated }) {
              if (aggregated) return '';
              if (value > 0) {
                const shownDuration = formatDuration(value);

                const start = new Date(original.created_time);
                if (isNaN(start.valueOf())) return shownDuration;

                const end = new Date(start.valueOf() + value);
                return (
                  <span
                    data-tooltip={`End time: ${end.toISOString()}\n(${formatDistanceToNow(end, {
                      addSuffix: true,
                    })})`}
                  >
                    {shownDuration}
                  </span>
                );
              }
              if (oneOf(original.status, 'RUNNING', 'PENDING') && original.created_time) {
                // Compute running duration from the created time if it exists
                return formatDuration(Date.now() - Date.parse(original.created_time));
              }
              return '';
            },
            Aggregated: () => '',
            show: visibleColumns.shown('Duration'),
          },
          {
            Header: 'Location',
            accessor: 'location',
            width: 200,
            Cell: this.renderTaskFilterableCell('location'),
            Aggregated: () => '',
            show: visibleColumns.shown('Location'),
          },
          {
            Header: ACTION_COLUMN_LABEL,
            id: ACTION_COLUMN_ID,
            accessor: 'task_id',
            width: ACTION_COLUMN_WIDTH,
            filterable: false,
            sortable: false,
            Cell: row => {
              if (row.aggregated) return '';
              const id = row.value;
              const type = row.row.type;
              const { datasource, status } = row.original;
              return (
                <ActionCell
                  onDetail={() => this.onTaskDetail(row.original)}
                  actions={this.getTaskActions(id, datasource, status, type, true)}
                  menuTitle={id}
                />
              );
            },
            Aggregated: () => '',
          },
        ]}
      />
    );
  }

  renderBulkTasksActions() {
    const { goToQuery, capabilities } = this.props;

    return (
      <MoreButton>
        {capabilities.hasSql() && (
          <MenuItem
            icon={getConsoleViewIcon('workbench')}
            text="View SQL query for table"
            onClick={() => goToQuery({ queryString: TasksView.TASK_SQL })}
          />
        )}
        <MenuItem
          icon={IconNames.MANUALLY_ENTERED_DATA}
          text="Submit JSON task"
          onClick={() => this.setState({ taskSpecDialogOpen: true })}
        />
      </MoreButton>
    );
  }

  render() {
    const { onFiltersChange } = this.props;
    const {
      groupTasksBy,
      taskSpecDialogOpen,
      executionDialogOpen,
      alertErrorMsg,
      taskTableActionDialogOpen,
      visibleColumns,
    } = this.state;

    return (
      <div className="tasks-view app-view">
        <ViewControlBar label="Tasks">
          <Label>Group by</Label>
          <ButtonGroup>
            <Button
              active={!groupTasksBy}
              onClick={() => this.setState({ groupTasksBy: undefined })}
            >
              None
            </Button>
            <Button
              active={groupTasksBy === 'group_id'}
              onClick={() => this.setState({ groupTasksBy: 'group_id' })}
            >
              Group ID
            </Button>
            <Button
              active={groupTasksBy === 'type'}
              onClick={() => this.setState({ groupTasksBy: 'type' })}
            >
              Type
            </Button>
            <Button
              active={groupTasksBy === 'datasource'}
              onClick={() => this.setState({ groupTasksBy: 'datasource' })}
            >
              Datasource
            </Button>
            <Button
              active={groupTasksBy === 'status'}
              onClick={() => this.setState({ groupTasksBy: 'status' })}
            >
              Status
            </Button>
          </ButtonGroup>
          <RefreshButton
            localStorageKey={LocalStorageKeys.TASKS_REFRESH_RATE}
            onRefresh={auto => {
              if (auto && hasOverlayOpen()) return;
              this.taskQueryManager.rerunLastQuery(auto);
            }}
          />
          {this.renderBulkTasksActions()}
          <TableColumnSelector
            columns={taskTableColumns}
            onChange={column =>
              this.setState(prevState => ({
                visibleColumns: prevState.visibleColumns.toggle(column),
              }))
            }
            tableColumnsHidden={visibleColumns.getHiddenColumns()}
          />
        </ViewControlBar>
        {this.renderTaskTable()}

        {this.renderKillTaskAction()}
        {taskSpecDialogOpen && (
          <SpecDialog
            onClose={this.closeSpecDialogs}
            onSubmit={this.submitTask}
            title="Submit task"
          />
        )}
        <AlertDialog
          icon={IconNames.ERROR}
          intent={Intent.PRIMARY}
          isOpen={Boolean(alertErrorMsg)}
          confirmButtonText="OK"
          onConfirm={() => this.setState({ alertErrorMsg: undefined })}
        >
          <p>{alertErrorMsg}</p>
        </AlertDialog>
        {taskTableActionDialogOpen && (
          <TaskTableActionDialog
            taskId={taskTableActionDialogOpen.id}
            status={taskTableActionDialogOpen.status}
            actions={taskTableActionDialogOpen.actions}
            onClose={() => this.setState({ taskTableActionDialogOpen: undefined })}
          />
        )}
        {executionDialogOpen && (
          <ExecutionDetailsDialog
            id={executionDialogOpen}
            goToTask={taskId => {
              onFiltersChange([{ id: 'task_id', value: `=${taskId}` }]);
              this.setState({ executionDialogOpen: undefined });
            }}
            onClose={() => this.setState({ executionDialogOpen: undefined })}
          />
        )}
      </div>
    );
  }
}
