import MilestoneDescription from '@/components/Description/MilestoneDescription'
import {
  Button,
  Classes,
  Colors,
  Dialog,
  Icon,
  Popover,
  SwitchCard,
} from '@blueprintjs/core'
import { Dot, Flag, IconSize } from '@blueprintjs/icons'
import { css, cx } from '@emotion/css'
import type { Milestone, MilestoneState } from '@inject/graphql/fragment-types'
import { type VariablesOf } from '@inject/graphql/graphql'
import { SetMilestone } from '@inject/graphql/mutations'
import StyledTag from '@inject/shared/components/StyledTag'
import { useState, type FC } from 'react'
import { useClient } from 'urql'

const timestamp = css`
  margin: 0.5rem;
`

const wrapper = css`
  display: flex;
  align-items: center;
  gap: 0.2rem;
  justify-content: center;
`

interface MilestoneIndicatorProps {
  states: MilestoneState[]
  milestone: Milestone
  teamIds: string[]
}

const AllMilestoneIndicator: FC<MilestoneIndicatorProps> = ({
  milestone,
  states,
  teamIds,
}) => {
  const client = useClient()
  const filteredStates = states.filter(
    state => milestone.id === state.milestone.id
  )
  const subbedTeams =
    teamIds.length !== 0
      ? filteredStates.filter(state =>
          state.teamIds.some(id => teamIds.includes(id))
        )
      : filteredStates
  const reached = subbedTeams.every(({ reached }) => reached)
  const unreachedAll = subbedTeams.every(({ reached }) => !reached)
  const contentTag = `Partially reached ${subbedTeams.filter(state => state.reached).length}/${subbedTeams.length}`
  /*
   * the switch will change its state even if the alert is cancelled;
   * we track of the state separately to revert it if the alert is cancelled
   */
  const [open, setOpen] = useState(false)
  const confirm = async () => {
    subbedTeams
      .filter(state => state.reached === reached)
      .forEach(state => {
        state.teamIds.forEach(teamId => {
          client
            .mutation<unknown, VariablesOf<typeof SetMilestone>>(SetMilestone, {
              milestone: milestone.name,
              activate: !reached,
              teamId,
            })
            .toPromise()
        })
      })
    setOpen(false)
  }

  // todo: does not consider selected teamids into consideration
  return (
    <SwitchCard
      style={{ order: reached ? 1 : 3 }}
      compact
      checked={reached}
      showAsSelectedWhenChecked={false}
      onChange={() => {
        setOpen(true)
      }}
    >
      <MilestoneDescription
        milestone={milestone}
        getChildren={displayName => (
          <>
            <Popover
              interactionKind='hover'
              content={
                reached ? (
                  <StyledTag
                    isAchieved
                    content='Reached'
                    className={timestamp}
                  />
                ) : unreachedAll ? (
                  <StyledTag
                    isAchieved={false}
                    content='Not reached'
                    className={timestamp}
                  />
                ) : (
                  <StyledTag
                    isRead={false}
                    content={contentTag}
                    className={timestamp}
                  />
                )
              }
            >
              <Dot
                style={{
                  color: reached
                    ? Colors.GREEN3
                    : unreachedAll
                      ? Colors.RED3
                      : Colors.GOLD3,
                  marginRight: '0.5rem',
                }}
                size={IconSize.LARGE}
              />
            </Popover>
            <div className={wrapper}>
              {displayName}
              {milestone.final && (
                <Flag style={{ padding: '0.2rem' }} title='Final milestone' />
              )}
            </div>
          </>
        )}
      />

      <Dialog
        isOpen={open}
        role='alertdialog'
        onClose={() => setOpen(false)}
        className={Classes.ALERT}
      >
        <div className={Classes.ALERT_BODY}>
          <Icon icon='warning-sign' size={40} intent={teamIds.length === 0 ? 'danger' : 'warning'} />
          <div className={Classes.ALERT_CONTENTS}>
            Are you sure you want to mark this milestone as{' '}
            {reached ? 'not reached' : 'reached'} for
            {teamIds.length === 0 ? ' ALL teams' : ' selected teams'}
          </div>
        </div>
        <div
          className={cx({
            [Classes.ALERT_FOOTER]: true,
            [css`
              flex-wrap: wrap;
              gap: 0.5rem;
            `]: true,
          })}
        >
          <Button
            intent={teamIds.length === 0 ? 'danger' : 'warning'}
            title={
              teamIds.length === 0
                ? 'Sets milestone for all teams'
                : 'Sets milestone for selected teams'
            }
            onClick={confirm}
          >
            Confirm
          </Button>
          <Button onClick={() => setOpen(false)}>Cancel</Button>
        </div>
      </Dialog>
    </SwitchCard>
  )
}

export default AllMilestoneIndicator
