import type { Dispatch, SetStateAction } from 'react'
import type {
  Credential,
  CustomConfigurationModelFixedFields,
  CustomModelCredential,
  ModelCredential,
  ModelLoadBalancingConfig,
  ModelLoadBalancingConfigEntry,
  ModelProvider,
} from '../declarations'
import { cn } from '@langgenius/dify-ui/cn'
import { StatusDot } from '@langgenius/dify-ui/status-dot'
import { Switch } from '@langgenius/dify-ui/switch'
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
import { useCallback, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import Badge from '@/app/components/base/badge/index'
import GridMask from '@/app/components/base/grid-mask'
import { Infotip } from '@/app/components/base/infotip'
import UpgradeBtn from '@/app/components/billing/upgrade-btn'
import s from '@/app/components/custom/style.module.css'
import { AddCredentialInLoadBalancing } from '@/app/components/header/account-setting/model-provider-page/model-auth'
import { IS_CE_EDITION } from '@/config'
import { useProviderContextSelector } from '@/context/provider-context'
import { ConfigurationMethodEnum } from '../declarations'
import CooldownTimer from './cooldown-timer'

type ModelLoadBalancingConfigsProps = {
  draftConfig?: ModelLoadBalancingConfig
  setDraftConfig: Dispatch<SetStateAction<ModelLoadBalancingConfig | undefined>>
  provider: ModelProvider
  configurationMethod: ConfigurationMethodEnum
  currentCustomConfigurationModelFixedFields?: CustomConfigurationModelFixedFields
  withSwitch?: boolean
  className?: string
  modelCredential: ModelCredential
  onUpdate?: (payload?: any, formValues?: Record<string, any>) => void
  onRemove?: (credentialId: string) => void
  model: CustomModelCredential
}

const ModelLoadBalancingConfigs = ({
  draftConfig,
  setDraftConfig,
  provider,
  model,
  configurationMethod,
  currentCustomConfigurationModelFixedFields: _currentCustomConfigurationModelFixedFields,
  withSwitch = false,
  className,
  modelCredential,
  onUpdate,
  onRemove,
}: ModelLoadBalancingConfigsProps) => {
  const { t } = useTranslation()
  const providerFormSchemaPredefined = configurationMethod === ConfigurationMethodEnum.predefinedModel
  const modelLoadBalancingEnabled = useProviderContextSelector(state => state.modelLoadBalancingEnabled)

  const updateConfigEntry = useCallback(
    (
      index: number,
      modifier: (entry: ModelLoadBalancingConfigEntry) => ModelLoadBalancingConfigEntry | undefined,
    ) => {
      setDraftConfig((prev) => {
        if (!prev)
          return prev
        const newConfigs = [...prev.configs]
        const modifiedConfig = modifier(newConfigs[index]!)
        if (modifiedConfig)
          newConfigs[index] = modifiedConfig
        else
          newConfigs.splice(index, 1)
        return {
          ...prev,
          configs: newConfigs,
        }
      })
    },
    [setDraftConfig],
  )

  const addConfigEntry = useCallback((credential: Credential) => {
    setDraftConfig((prev: any) => {
      if (!prev)
        return prev
      return {
        ...prev,
        configs: [...prev.configs, {
          credential_id: credential.credential_id,
          enabled: true,
          name: credential.credential_name,
        }],
      }
    })
  }, [setDraftConfig])

  const toggleModalBalancing = useCallback((enabled: boolean) => {
    if ((modelLoadBalancingEnabled || !enabled) && draftConfig) {
      setDraftConfig({
        ...draftConfig,
        enabled,
      })
    }
  }, [draftConfig, modelLoadBalancingEnabled, setDraftConfig])

  const toggleConfigEntryEnabled = useCallback((index: number, state?: boolean) => {
    updateConfigEntry(index, entry => ({
      ...entry,
      enabled: typeof state === 'boolean' ? state : !entry.enabled,
    }))
  }, [updateConfigEntry])

  const clearCountdown = useCallback((index: number) => {
    updateConfigEntry(index, ({ ttl: _, ...entry }) => {
      return {
        ...entry,
        in_cooldown: false,
      }
    })
  }, [updateConfigEntry])

  const validDraftConfigList = useMemo(() => {
    if (!draftConfig)
      return []
    return draftConfig.configs
  }, [draftConfig])

  const handleUpdate = useCallback((payload?: any, formValues?: Record<string, any>) => {
    onUpdate?.(payload, formValues)
  }, [onUpdate])

  const handleRemove = useCallback((credentialId: string) => {
    const index = draftConfig?.configs.findIndex(item => item.credential_id === credentialId && item.name !== '__inherit__')
    if (typeof index === 'number' && index > -1)
      updateConfigEntry(index, () => undefined)
    onRemove?.(credentialId)
  }, [draftConfig?.configs, updateConfigEntry, onRemove])

  if (!draftConfig)
    return null

  return (
    <>
      <div
        className={cn('min-h-16 rounded-xl border bg-components-panel-bg transition-colors', (withSwitch || !draftConfig.enabled) ? 'border-components-panel-border' : 'border-util-colors-blue-blue-600', (withSwitch || draftConfig.enabled) ? 'cursor-default' : 'cursor-pointer', className)}
        onClick={(!withSwitch && !draftConfig.enabled) ? () => toggleModalBalancing(true) : undefined}
        data-testid="load-balancing-main-panel"
      >
        <div className="flex items-center gap-2 px-[15px] py-3 select-none">
          <div className="flex size-8 shrink-0 grow-0 items-center justify-center rounded-lg border border-util-colors-indigo-indigo-100 bg-util-colors-indigo-indigo-50 text-util-colors-blue-blue-600">
            <div className="i-custom-vender-line-financeandecommerce-balance size-4" />
          </div>
          <div className="grow">
            <div className="flex items-center gap-1 text-sm text-text-primary">
              {t('modelProvider.loadBalancing', { ns: 'common' })}
              <Infotip
                aria-label={t('modelProvider.loadBalancingInfo', { ns: 'common' })}
                className="size-3"
                iconClassName="h-full w-full"
                popupClassName="max-w-[300px]"
              >
                {t('modelProvider.loadBalancingInfo', { ns: 'common' })}
              </Infotip>
            </div>
            <div className="text-xs text-text-tertiary">{t('modelProvider.loadBalancingDescription', { ns: 'common' })}</div>
          </div>
          {
            withSwitch && (
              <Switch
                checked={Boolean(draftConfig.enabled)}
                size="lg"
                className="ml-3 justify-self-end"
                disabled={!modelLoadBalancingEnabled && !draftConfig.enabled}
                onCheckedChange={value => toggleModalBalancing(value)}
                data-testid="load-balancing-switch-main"
              />
            )
          }
        </div>
        {draftConfig.enabled && (
          <div className="flex flex-col gap-1 px-3 pb-3">
            {validDraftConfigList.map((config, index) => {
              const isProviderManaged = config.name === '__inherit__'
              const credential = modelCredential.available_credentials.find(c => c.credential_id === config.credential_id)
              return (
                <div key={config.id || index} className="group flex h-10 items-center rounded-lg border border-components-panel-border bg-components-panel-on-panel-item-bg px-3 shadow-xs">
                  <div className="flex grow items-center">
                    <div className="mr-2 flex size-3 items-center justify-center">
                      {(config.in_cooldown && Boolean(config.ttl))
                        ? (
                            <CooldownTimer secondsRemaining={config.ttl} onFinish={() => clearCountdown(index)} />
                          )
                        : (
                            <Tooltip>
                              <TooltipTrigger
                                render={(
                                  <StatusDot status={credential?.not_allowed_to_use ? 'disabled' : 'success'} />
                                )}
                              />
                              <TooltipContent>
                                {t('modelProvider.apiKeyStatusNormal', { ns: 'common' })}
                              </TooltipContent>
                            </Tooltip>
                          )}
                    </div>
                    <div className="mr-1 text-[13px] text-text-secondary">
                      {isProviderManaged ? t('modelProvider.defaultConfig', { ns: 'common' }) : config.name}
                    </div>
                    {isProviderManaged && providerFormSchemaPredefined && (
                      <Badge className="ml-2">{t('modelProvider.providerManaged', { ns: 'common' })}</Badge>
                    )}
                    {
                      credential?.from_enterprise && (
                        <Badge className="ml-2">Enterprise</Badge>
                      )
                    }
                  </div>
                  <div className="flex items-center gap-1">
                    {!isProviderManaged && (
                      <>
                        <div className="flex items-center gap-1 opacity-0 transition-opacity group-hover:opacity-100">
                          <Tooltip>
                            <TooltipTrigger
                              render={(
                                <span
                                  className="flex size-8 cursor-pointer items-center justify-center rounded-lg bg-components-button-secondary-bg text-text-tertiary transition-colors hover:bg-components-button-secondary-bg-hover"
                                  onClick={() => updateConfigEntry(index, () => undefined)}
                                  data-testid={`load-balancing-remove-${config.id || index}`}
                                >
                                  <div className="i-ri-indeterminate-circle-line size-4" />
                                </span>
                              )}
                            />
                            <TooltipContent>
                              {t('operation.remove', { ns: 'common' })}
                            </TooltipContent>
                          </Tooltip>
                        </div>
                      </>
                    )}
                    {
                      (config.credential_id || config.name === '__inherit__') && (
                        <>
                          <span className="mr-2 h-3 border-r border-r-divider-subtle" />
                          <Switch
                            checked={credential?.not_allowed_to_use ? false : Boolean(config.enabled)}
                            size="md"
                            className="justify-self-end"
                            onCheckedChange={value => toggleConfigEntryEnabled(index, value)}
                            disabled={credential?.not_allowed_to_use}
                            data-testid={`load-balancing-switch-${config.id || index}`}
                          />
                        </>
                      )
                    }
                  </div>
                </div>
              )
            })}
            <AddCredentialInLoadBalancing
              provider={provider}
              model={model}
              configurationMethod={configurationMethod}
              modelCredential={modelCredential}
              onSelectCredential={addConfigEntry}
              onUpdate={handleUpdate}
              onRemove={handleRemove}
            />
          </div>
        )}
        {
          draftConfig.enabled && validDraftConfigList.length < 2 && (
            <div className="flex h-[34px] items-center rounded-b-xl border-t border-t-divider-subtle bg-components-panel-bg px-6 text-xs text-text-secondary">
              <div className="i-custom-vender-solid-alertsandfeedback-alert-triangle mr-1 h-3 w-3 text-[#f79009]" />
              {t('modelProvider.loadBalancingLeastKeyWarning', { ns: 'common' })}
            </div>
          )
        }
      </div>

      {!modelLoadBalancingEnabled && !IS_CE_EDITION && (
        <GridMask canvasClassName="rounded-xl!">
          <div className="mt-2 flex h-14 items-center justify-between rounded-xl border-[0.5px] border-components-panel-border px-4 shadow-md">
            <div
              className={cn('text-gradient text-sm/tight font-semibold', s.textGradient)}
            >
              {t('modelProvider.upgradeForLoadBalancing', { ns: 'common' })}
            </div>
            <UpgradeBtn />
          </div>
        </GridMask>
      )}
    </>
  )
}

export default ModelLoadBalancingConfigs
