import { HIGHLIGHTED_COLOR, formatTimestamp } from '@/analyst/utilities'
import DeleteAlert from '@/exercisepanel/DeleteAlert'
import type { Intent } from '@blueprintjs/core'
import { Button, ButtonGroup, Card, Classes, Colors } from '@blueprintjs/core'
import { css, cx } from '@emotion/css'
import type { Exercise } from '@inject/graphql/fragments/Exercise.generated'
import { useMemo, useState, type FC, type ReactNode } from 'react'
import LinkButton from '../LinkButton'
import DownloadLogsButton from './DownloadLogsButton'

const card = css`
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  overflow: auto;
  gap: 1rem;
`

const buttonGroup = css`
  align-self: flex-end;
`

const selected = css`
  background-color: ${HIGHLIGHTED_COLOR} !important;
`
const running = css`
  background-color: ${Colors.GREEN3}1a !important;
  color: ${Colors.GREEN1};
  box-shadow: 0 0 0 1px ${Colors.GREEN3} !important;

  .${Classes.DARK} & {
    background-color: ${Colors.GREEN3}33 !important;
    color: ${Colors.GREEN5};
  }
`

const infoWrapper = css`
  display: flex;
  flex-direction: column;
  overflow: auto;
  gap: 1rem;
`

const detailWrapper = css`
  display: grid;
  grid-template-columns: repeat(2, auto);
  gap: 0.25rem 0.5rem;
`

const detailTitle = css`
  font-weight: bold;
`

const detailText = css`
  overflow: hidden;
  text-overflow: ellipsis;
`

const title = css`
  overflow: hidden;
  text-overflow: ellipsis;
  margin: 0;
`

export type SelectingDetails = {
  onSelect: () => void
}

export type ManagingDetails = {
  runningAny: boolean
  onStart: () => void
  startLoading?: boolean
  onDelete: () => void
  deleteLoading?: boolean
  onPause: () => void
  pauseLoading?: boolean
}

type ExerciseCardProps = {
  isSelected?: boolean
  exercise: Exercise
} & (
  | {
      type: 'selecting'
      details: SelectingDetails
    }
  | { type: 'managing'; details: ManagingDetails }
)

const ExerciseCard: FC<ExerciseCardProps> = ({
  exercise,
  isSelected,
  type,
  details,
}) => {
  const [alertOpen, setAlertOpen] = useState(false)

  const intent: Intent | undefined = useMemo(
    () => (exercise.running ? 'success' : undefined),
    [exercise.running]
  )
  const buttons: ReactNode = useMemo(
    () =>
      type === 'selecting' ? (
        !isSelected && (
          <Button onClick={details.onSelect} intent={intent}>
            Select
          </Button>
        )
      ) : (
        <>
          {!exercise.running && !exercise.finished && (
            <Button
              intent={intent}
              icon='play'
              onClick={details.onStart}
              loading={details.startLoading}
              disabled={details.runningAny}
              title={
                details.runningAny
                  ? 'Only one exercise can run at a time'
                  : exercise.exerciseStart
                    ? 'Resume'
                    : 'Start'
              }
            />
          )}
          {exercise.running && (
            <Button
              intent={intent}
              icon='pause'
              onClick={details.onPause}
              loading={details.pauseLoading}
              title='Pause'
            />
          )}
          <LinkButton
            link={[
              '/exercise-panel/exercise/:exerciseId',
              { params: { exerciseId: exercise.id } },
            ]}
            button={{
              icon: 'people',
              title: 'Participants',
              intent,
            }}
          />
          <Button
            intent={intent}
            icon='trash'
            onClick={() => setAlertOpen(true)}
            disabled={exercise.running}
            title={
              exercise.running ? 'Cannot delete a running exercise' : 'Delete'
            }
            active={alertOpen}
          />
          <DownloadLogsButton
            exerciseId={exercise.id}
            buttonProps={{
              intent,
              title: 'Download logs',
              text: undefined,
              rightIcon: undefined,
            }}
          />
        </>
      ),
    [
      alertOpen,
      details,
      exercise.exerciseStart,
      exercise.finished,
      exercise.id,
      exercise.running,
      intent,
      isSelected,
      type,
    ]
  )

  return (
    <Card
      className={cx({
        [card]: true,
        [selected]: isSelected,
        [running]: exercise.running,
      })}
    >
      <div className={infoWrapper}>
        <h3 className={title} title={exercise.name}>
          {exercise.name}
        </h3>
        <div className={detailWrapper}>
          <div className={detailTitle}>Definition:</div>
          {/* TODO: test ellipsis */}
          <div
            className={detailText}
            title={
              exercise.definition?.name || exercise.definition?.id?.toString()
            }
          >
            {exercise.definition?.name || exercise.definition?.id}
          </div>
          <div className={detailTitle}>Teams:</div>
          <div className={detailText} title={exercise.teams.length.toString()}>
            {exercise.teams.length}
          </div>
          <div className={detailTitle}>Started:</div>
          <div className={detailText}>
            {exercise.exerciseStart
              ? formatTimestamp(exercise.exerciseStart)
              : 'not started yet'}
          </div>
          <div className={detailTitle}>Finished:</div>
          {/* TODO: add timestamp */}
          <div className={detailText}>
            {exercise.finished ? 'yes' : 'not finished yet'}
          </div>
        </div>
      </div>

      <ButtonGroup className={buttonGroup} alignText='left'>
        {buttons}
      </ButtonGroup>

      {type === 'managing' && (
        <DeleteAlert
          open={alertOpen}
          setOpen={setAlertOpen}
          onDelete={details.onDelete}
          loading={details.deleteLoading}
        >
          <p>
            Are you sure you want to delete the selected exercise? This action
            is irreversible.
          </p>
        </DeleteAlert>
      )}
    </Card>
  )
}
export default ExerciseCard
