import { Tag } from 'antd'
import React, { useCallback, useMemo, useState } from 'react'

import { workspaceHandlerListWorkspaces } from 'apiClient/services/ticket-manager'
import type {
  WorkspaceHandlerListWorkspacesParams,
  WorkspaceWorkspace
} from 'apiClient/services/ticket-manager/interface'
import DebounceSelect from 'components/DebounceSelect/DebounceSelect'

type WorkspaceOption = {
  label: React.ReactNode
  value: number
}

type WorkspaceSearchInputValue = number | number[]

export type WorkspaceSearchInputSearchParams = Omit<
  WorkspaceHandlerListWorkspacesParams,
  'keyword'
>

export interface WorkspaceSearchInputProps {
  value?: WorkspaceSearchInputValue
  onChange?: (value?: WorkspaceSearchInputValue) => void
  searchParams?: WorkspaceSearchInputSearchParams
  disabled?: boolean
  placeholder?: string
  className?: string
  style?: React.CSSProperties
  allowClear?: boolean
  mode?: 'multiple'
}

const DEFAULT_PLACEHOLDER = 'Search by workspace name or ID'
const DEFAULT_PAGE_SIZE = 20
const WORKSPACE_STATUS_COLORS: Record<string, string> = {
  firing: 'orange',
  recovered: 'green',
  archived: 'default'
}

function formatWorkspaceLabel(workspace: WorkspaceWorkspace) {
  return (
    <span>
      {workspace.id} / {workspace.name} /{' '}
      <Tag
        color={WORKSPACE_STATUS_COLORS[workspace.status!]}
        style={{ marginRight: 0 }}
      >
        {workspace.status}
      </Tag>
    </span>
  )
}

const WorkspaceSearchInput: React.FC<WorkspaceSearchInputProps> = ({
  value,
  onChange,
  searchParams,
  disabled,
  placeholder = DEFAULT_PLACEHOLDER,
  className,
  style,
  allowClear = true,
  mode
}) => {
  const [innerValue, setInnerValue] = useState<WorkspaceSearchInputValue>()
  const [selectedOptions, setSelectedOptions] = useState<WorkspaceOption[]>([])
  const isMultiple = mode === 'multiple'

  const currentValue = value ?? innerValue

  const fetchOptions = useCallback(
    async (search: string) => {
      const { data } = await workspaceHandlerListWorkspaces({
        ...searchParams,
        keyword: search,
        page: searchParams?.page ?? 1,
        page_size: searchParams?.page_size ?? DEFAULT_PAGE_SIZE
      })

      return (data.workspaces || []).map((workspace) => ({
        label: formatWorkspaceLabel(workspace),
        value: workspace.id!
      }))
    },
    [searchParams]
  )

  const selectValue = useMemo(() => {
    if (
      !currentValue ||
      (Array.isArray(currentValue) && currentValue.length === 0)
    ) {
      return undefined
    }

    const currentValues = Array.isArray(currentValue)
      ? currentValue
      : [currentValue]

    const mappedOptions = currentValues.map((item) => {
      return (
        selectedOptions.find(
          (selectedOption) => selectedOption.value === item
        ) || {
          value: item,
          label: item
        }
      )
    })

    return isMultiple ? mappedOptions : mappedOptions[0]
  }, [currentValue, isMultiple, selectedOptions])

  const handleChange = (option?: WorkspaceOption | WorkspaceOption[]) => {
    const nextOptions = Array.isArray(option) ? option : option ? [option] : []
    const nextSelectedOptions = nextOptions.map((selectedOption) => ({
      value: selectedOption.value,
      label: selectedOption.label
    }))
    const nextValue = isMultiple
      ? nextSelectedOptions.map((selectedOption) => selectedOption.value)
      : nextSelectedOptions[0]?.value

    if (value === undefined) {
      setInnerValue(nextValue)
    }

    setSelectedOptions(nextSelectedOptions)
    onChange?.(nextValue)
  }

  return (
    <DebounceSelect<WorkspaceOption>
      value={selectValue}
      mode={mode}
      disabled={disabled}
      placeholder={placeholder}
      className={className}
      style={style}
      allowClear={allowClear}
      showSearch
      fetchOptions={fetchOptions}
      onChange={handleChange}
    />
  )
}

export default WorkspaceSearchInput
export { WorkspaceSearchInput }
