'use client'
import type { FC } from 'react'
import type { AppIconSelection } from '@/app/components/base/app-icon-picker'
import type { AppDetailResponse } from '@/models/app'
import type { AppIconType, AppSSO, Language } from '@/types/app'
import { RiArrowRightSLine, RiCloseLine } from '@remixicon/react'
import Link from 'next/link'
import * as React from 'react'
import { useCallback, useEffect, useRef, useState } from 'react'
import { Trans, useTranslation } from 'react-i18next'
import ActionButton from '@/app/components/base/action-button'
import AppIcon from '@/app/components/base/app-icon'
import AppIconPicker from '@/app/components/base/app-icon-picker'
import Button from '@/app/components/base/button'
import Divider from '@/app/components/base/divider'
import { SparklesSoft } from '@/app/components/base/icons/src/public/common'
import Input from '@/app/components/base/input'
import Modal from '@/app/components/base/modal'
import PremiumBadge from '@/app/components/base/premium-badge'
import { SimpleSelect } from '@/app/components/base/select'
import Switch from '@/app/components/base/switch'
import Textarea from '@/app/components/base/textarea'
import { useToastContext } from '@/app/components/base/toast/context'
import Tooltip from '@/app/components/base/tooltip'
import { ACCOUNT_SETTING_TAB } from '@/app/components/header/account-setting/constants'
import { useModalContext } from '@/context/modal-context'
import { useProviderContext } from '@/context/provider-context'
import { languages } from '@/i18n-config/language'
import { AppModeEnum } from '@/types/app'
import { cn } from '@/utils/classnames'

export type ISettingsModalProps = {
  isChat: boolean
  appInfo: AppDetailResponse & Partial<AppSSO>
  isShow: boolean
  defaultValue?: string
  onClose: () => void
  onSave?: (params: ConfigParams) => Promise<void>
}

export type ConfigParams = {
  title: string
  description: string
  default_language: string
  chat_color_theme: string
  chat_color_theme_inverted: boolean
  prompt_public: boolean
  copyright: string
  privacy_policy: string
  custom_disclaimer: string
  icon_type: AppIconType
  icon: string
  icon_background?: string
  show_workflow_steps: boolean
  use_icon_as_answer_icon: boolean
  enable_sso?: boolean
}

const prefixSettings = 'overview.appInfo.settings'

const SettingsModal: FC<ISettingsModalProps> = ({
  isChat,
  appInfo,
  isShow = false,
  onClose,
  onSave,
}) => {
  const { notify } = useToastContext()
  const [isShowMore, setIsShowMore] = useState(false)
  const {
    title,
    icon_type,
    icon,
    icon_background,
    icon_url,
    description,
    chat_color_theme,
    chat_color_theme_inverted,
    copyright,
    privacy_policy,
    custom_disclaimer,
    default_language,
    show_workflow_steps,
    use_icon_as_answer_icon,
  } = appInfo.site
  const [inputInfo, setInputInfo] = useState({
    title,
    desc: description,
    chatColorTheme: chat_color_theme,
    chatColorThemeInverted: chat_color_theme_inverted,
    copyright,
    copyrightSwitchValue: !!copyright,
    privacyPolicy: privacy_policy,
    customDisclaimer: custom_disclaimer,
    show_workflow_steps,
    use_icon_as_answer_icon,
    enable_sso: appInfo.enable_sso,
  })
  const [language, setLanguage] = useState(default_language)
  const [saveLoading, setSaveLoading] = useState(false)
  const { t } = useTranslation()
  const hideMoreTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)

  const [showAppIconPicker, setShowAppIconPicker] = useState(false)
  const [appIcon, setAppIcon] = useState<AppIconSelection>(
    icon_type === 'image'
      ? { type: 'image', url: icon_url!, fileId: icon }
      : { type: 'emoji', icon, background: icon_background! },
  )

  const { enableBilling, plan, webappCopyrightEnabled } = useProviderContext()
  const { setShowPricingModal, setShowAccountSettingModal } = useModalContext()
  const isFreePlan = plan.type === 'sandbox'
  const handlePlanClick = useCallback(() => {
    if (isFreePlan)
      setShowPricingModal()
    else
      setShowAccountSettingModal({ payload: ACCOUNT_SETTING_TAB.BILLING })
  }, [isFreePlan, setShowAccountSettingModal, setShowPricingModal])

  useEffect(() => {
    setInputInfo({
      title,
      desc: description,
      chatColorTheme: chat_color_theme,
      chatColorThemeInverted: chat_color_theme_inverted,
      copyright,
      copyrightSwitchValue: !!copyright,
      privacyPolicy: privacy_policy,
      customDisclaimer: custom_disclaimer,
      show_workflow_steps,
      use_icon_as_answer_icon,
      enable_sso: appInfo.enable_sso,
    })
    setLanguage(default_language)
    setAppIcon(icon_type === 'image'
      ? { type: 'image', url: icon_url!, fileId: icon }
      : { type: 'emoji', icon, background: icon_background! })
  }, [appInfo, chat_color_theme, chat_color_theme_inverted, copyright, custom_disclaimer, default_language, description, icon, icon_background, icon_type, icon_url, privacy_policy, show_workflow_steps, title, use_icon_as_answer_icon])

  useEffect(() => {
    return () => {
      if (hideMoreTimerRef.current) {
        clearTimeout(hideMoreTimerRef.current)
        hideMoreTimerRef.current = null
      }
    }
  }, [])

  const onHide = () => {
    onClose()
    if (hideMoreTimerRef.current)
      clearTimeout(hideMoreTimerRef.current)
    hideMoreTimerRef.current = setTimeout(() => {
      setIsShowMore(false)
      hideMoreTimerRef.current = null
    }, 200)
  }

  const onClickSave = async () => {
    if (!inputInfo.title) {
      notify({ type: 'error', message: t('newApp.nameNotEmpty', { ns: 'app' }) })
      return
    }

    const validateColorHex = (hex: string | null) => {
      if (hex === null || hex?.length === 0)
        return true

      const regex = /#([A-F0-9]{6})/i
      const check = regex.test(hex)
      return check
    }

    const validatePrivacyPolicy = (privacyPolicy: string | null) => {
      if (privacyPolicy === null || privacyPolicy?.length === 0)
        return true

      return privacyPolicy.startsWith('http://') || privacyPolicy.startsWith('https://')
    }

    if (inputInfo !== null) {
      if (!validateColorHex(inputInfo.chatColorTheme)) {
        notify({ type: 'error', message: t(`${prefixSettings}.invalidHexMessage`, { ns: 'appOverview' }) })
        return
      }
      if (!validatePrivacyPolicy(inputInfo.privacyPolicy)) {
        notify({ type: 'error', message: t(`${prefixSettings}.invalidPrivacyPolicy`, { ns: 'appOverview' }) })
        return
      }
    }

    setSaveLoading(true)
    const params = {
      title: inputInfo.title,
      description: inputInfo.desc,
      default_language: language,
      chat_color_theme: inputInfo.chatColorTheme,
      chat_color_theme_inverted: inputInfo.chatColorThemeInverted,
      prompt_public: false,
      copyright: !webappCopyrightEnabled
        ? ''
        : inputInfo.copyrightSwitchValue
          ? inputInfo.copyright
          : '',
      privacy_policy: inputInfo.privacyPolicy,
      custom_disclaimer: inputInfo.customDisclaimer,
      icon_type: appIcon.type,
      icon: appIcon.type === 'emoji' ? appIcon.icon : appIcon.fileId,
      icon_background: appIcon.type === 'emoji' ? appIcon.background : undefined,
      show_workflow_steps: inputInfo.show_workflow_steps,
      use_icon_as_answer_icon: inputInfo.use_icon_as_answer_icon,
      enable_sso: inputInfo.enable_sso,
    }
    await onSave?.(params)
    setSaveLoading(false)
    onHide()
  }

  const onChange = (field: string) => {
    return (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
      let value: string | boolean
      if (e.target.type === 'checkbox')
        value = (e.target as HTMLInputElement).checked
      else
        value = e.target.value

      setInputInfo(item => ({ ...item, [field]: value }))
    }
  }

  const onDesChange = (value: string) => {
    setInputInfo(item => ({ ...item, desc: value }))
  }

  return (
    <>
      <Modal
        isShow={isShow}
        closable={false}
        onClose={onHide}
        className="max-w-[520px] p-0"
      >
        {/* header */}
        <div className="pb-3 pl-6 pr-5 pt-5">
          <div className="flex items-center gap-1">
            <div className="grow text-text-primary title-2xl-semi-bold">{t(`${prefixSettings}.title`, { ns: 'appOverview' })}</div>
            <ActionButton className="shrink-0" onClick={onHide}>
              <RiCloseLine className="h-4 w-4" />
            </ActionButton>
          </div>
          <div className="mt-0.5 text-text-tertiary system-xs-regular">
            <span>{t(`${prefixSettings}.modalTip`, { ns: 'appOverview' })}</span>
          </div>
        </div>
        {/* form body */}
        <div className="space-y-5 px-6 py-3">
          {/* name & icon */}
          <div className="flex gap-4">
            <div className="grow">
              <div className={cn('mb-1 py-1 text-text-secondary system-sm-semibold')}>{t(`${prefixSettings}.webName`, { ns: 'appOverview' })}</div>
              <Input
                className="w-full"
                value={inputInfo.title}
                onChange={onChange('title')}
                placeholder={t('appNamePlaceholder', { ns: 'app' }) || ''}
              />
            </div>
            <AppIcon
              size="xxl"
              onClick={() => { setShowAppIconPicker(true) }}
              className="mt-2 cursor-pointer"
              iconType={appIcon.type}
              icon={appIcon.type === 'image' ? appIcon.fileId : appIcon.icon}
              background={appIcon.type === 'image' ? undefined : appIcon.background}
              imageUrl={appIcon.type === 'image' ? appIcon.url : undefined}
            />
          </div>
          {/* description */}
          <div className="relative">
            <div className={cn('py-1 text-text-secondary system-sm-semibold')}>{t(`${prefixSettings}.webDesc`, { ns: 'appOverview' })}</div>
            <Textarea
              className="mt-1"
              value={inputInfo.desc}
              onChange={e => onDesChange(e.target.value)}
              placeholder={t(`${prefixSettings}.webDescPlaceholder`, { ns: 'appOverview' }) as string}
            />
            <p className={cn('pb-0.5 text-text-tertiary body-xs-regular')}>{t(`${prefixSettings}.webDescTip`, { ns: 'appOverview' })}</p>
          </div>
          <Divider className="my-0 h-px" />
          {/* answer icon */}
          {isChat && (
            <div className="w-full">
              <div className="flex items-center justify-between">
                <div className={cn('py-1 text-text-secondary system-sm-semibold')}>{t('answerIcon.title', { ns: 'app' })}</div>
                <Switch
                  value={inputInfo.use_icon_as_answer_icon}
                  onChange={v => setInputInfo({ ...inputInfo, use_icon_as_answer_icon: v })}
                />
              </div>
              <p className="pb-0.5 text-text-tertiary body-xs-regular">{t('answerIcon.description', { ns: 'app' })}</p>
            </div>
          )}
          {/* language */}
          <div className="flex items-center">
            <div className={cn('grow py-1 text-text-secondary system-sm-semibold')}>{t(`${prefixSettings}.language`, { ns: 'appOverview' })}</div>
            <SimpleSelect
              wrapperClassName="w-[200px]"
              items={languages.filter(item => item.supported)}
              defaultValue={language}
              onSelect={item => setLanguage(item.value as Language)}
              notClearable
            />
          </div>
          {/* theme color */}
          {isChat && (
            <div className="flex items-center">
              <div className="grow">
                <div className={cn('py-1 text-text-secondary system-sm-semibold')}>{t(`${prefixSettings}.chatColorTheme`, { ns: 'appOverview' })}</div>
                <div className="pb-0.5 text-text-tertiary body-xs-regular">{t(`${prefixSettings}.chatColorThemeDesc`, { ns: 'appOverview' })}</div>
              </div>
              <div className="shrink-0">
                <Input
                  className="mb-1 w-[200px]"
                  value={inputInfo.chatColorTheme ?? ''}
                  onChange={onChange('chatColorTheme')}
                  placeholder="E.g #A020F0"
                />
                <div className="flex items-center justify-between">
                  <p className={cn('text-text-tertiary body-xs-regular')}>{t(`${prefixSettings}.chatColorThemeInverted`, { ns: 'appOverview' })}</p>
                  <Switch value={inputInfo.chatColorThemeInverted} onChange={v => setInputInfo({ ...inputInfo, chatColorThemeInverted: v })}></Switch>
                </div>
              </div>
            </div>
          )}
          {/* workflow detail */}
          <div className="w-full">
            <div className="flex items-center justify-between">
              <div className={cn('py-1 text-text-secondary system-sm-semibold')}>{t(`${prefixSettings}.workflow.subTitle`, { ns: 'appOverview' })}</div>
              <Switch
                disabled={!(appInfo.mode === AppModeEnum.WORKFLOW || appInfo.mode === AppModeEnum.ADVANCED_CHAT)}
                value={inputInfo.show_workflow_steps}
                onChange={v => setInputInfo({ ...inputInfo, show_workflow_steps: v })}
              />
            </div>
            <p className="pb-0.5 text-text-tertiary body-xs-regular">{t(`${prefixSettings}.workflow.showDesc`, { ns: 'appOverview' })}</p>
          </div>
          {/* more settings switch */}
          <Divider className="my-0 h-px" />
          {!isShowMore && (
            <div className="flex cursor-pointer items-center" onClick={() => setIsShowMore(true)}>
              <div className="grow">
                <div className={cn('py-1 text-text-secondary system-sm-semibold')}>{t(`${prefixSettings}.more.entry`, { ns: 'appOverview' })}</div>
                <p className={cn('pb-0.5 text-text-tertiary body-xs-regular')}>
                  {t(`${prefixSettings}.more.copyRightPlaceholder`, { ns: 'appOverview' })}
                  {' '}
                  &
                  {' '}
                  {t(`${prefixSettings}.more.privacyPolicyPlaceholder`, { ns: 'appOverview' })}
                </p>
              </div>
              <RiArrowRightSLine className="ml-1 h-4 w-4 shrink-0 text-text-secondary" />
            </div>
          )}
          {/* more settings */}
          {isShowMore && (
            <>
              {/* copyright */}
              <div className="w-full">
                <div className="flex items-center">
                  <div className="flex grow items-center">
                    <div className={cn('mr-1 py-1 text-text-secondary system-sm-semibold')}>{t(`${prefixSettings}.more.copyright`, { ns: 'appOverview' })}</div>
                    {/* upgrade button */}
                    {enableBilling && isFreePlan && (
                      <div className="h-[18px] select-none">
                        <PremiumBadge size="s" color="blue" allowHover={true} onClick={handlePlanClick}>
                          <SparklesSoft className="flex h-3.5 w-3.5 items-center py-[1px] pl-[3px] text-components-premium-badge-indigo-text-stop-0" />
                          <div className="system-xs-medium">
                            <span className="p-1">
                              {t('upgradeBtn.encourageShort', { ns: 'billing' })}
                            </span>
                          </div>
                        </PremiumBadge>
                      </div>
                    )}
                  </div>
                  <Tooltip
                    disabled={webappCopyrightEnabled}
                    popupContent={
                      <div className="w-[180px]">{t(`${prefixSettings}.more.copyrightTooltip`, { ns: 'appOverview' })}</div>
                    }
                    asChild={false}
                  >
                    <Switch
                      disabled={!webappCopyrightEnabled}
                      value={inputInfo.copyrightSwitchValue}
                      onChange={v => setInputInfo({ ...inputInfo, copyrightSwitchValue: v })}
                    />
                  </Tooltip>
                </div>
                <p className="pb-0.5 text-text-tertiary body-xs-regular">{t(`${prefixSettings}.more.copyrightTip`, { ns: 'appOverview' })}</p>
                {inputInfo.copyrightSwitchValue && (
                  <Input
                    className="mt-2 h-10"
                    value={inputInfo.copyright}
                    onChange={onChange('copyright')}
                    placeholder={t(`${prefixSettings}.more.copyRightPlaceholder`, { ns: 'appOverview' }) as string}
                  />
                )}
              </div>
              {/* privacy policy */}
              <div className="w-full">
                <div className={cn('py-1 text-text-secondary system-sm-semibold')}>{t(`${prefixSettings}.more.privacyPolicy`, { ns: 'appOverview' })}</div>
                <p className={cn('pb-0.5 text-text-tertiary body-xs-regular')}>
                  <Trans
                    i18nKey={`${prefixSettings}.more.privacyPolicyTip`}
                    ns="appOverview"
                    components={{ privacyPolicyLink: <Link href="https://dify.ai/privacy" target="_blank" rel="noopener noreferrer" className="text-text-accent" /> }}
                  />
                </p>
                <Input
                  className="mt-1"
                  value={inputInfo.privacyPolicy}
                  onChange={onChange('privacyPolicy')}
                  placeholder={t(`${prefixSettings}.more.privacyPolicyPlaceholder`, { ns: 'appOverview' }) as string}
                />
              </div>
              {/* custom disclaimer */}
              <div className="w-full">
                <div className={cn('py-1 text-text-secondary system-sm-semibold')}>{t(`${prefixSettings}.more.customDisclaimer`, { ns: 'appOverview' })}</div>
                <p className={cn('pb-0.5 text-text-tertiary body-xs-regular')}>{t(`${prefixSettings}.more.customDisclaimerTip`, { ns: 'appOverview' })}</p>
                <Textarea
                  className="mt-1"
                  value={inputInfo.customDisclaimer}
                  onChange={onChange('customDisclaimer')}
                  placeholder={t(`${prefixSettings}.more.customDisclaimerPlaceholder`, { ns: 'appOverview' }) as string}
                />
              </div>
            </>
          )}
        </div>
        {/* footer */}
        <div className="flex justify-end p-6 pt-5">
          <Button className="mr-2" onClick={onHide}>{t('operation.cancel', { ns: 'common' })}</Button>
          <Button variant="primary" onClick={onClickSave} loading={saveLoading}>{t('operation.save', { ns: 'common' })}</Button>
        </div>
        {showAppIconPicker && (
          <div onClick={e => e.stopPropagation()}>
            <AppIconPicker
              onSelect={(payload) => {
                setAppIcon(payload)
                setShowAppIconPicker(false)
              }}
              onClose={() => {
                setAppIcon(icon_type === 'image'
                  ? { type: 'image', url: icon_url!, fileId: icon }
                  : { type: 'emoji', icon, background: icon_background! })
                setShowAppIconPicker(false)
              }}
            />
          </div>
        )}
      </Modal>
    </>
  )
}
export default React.memo(SettingsModal)
