'use client'

import {
  useContext,
  useEffect,
  useState,
  useCallback,
  ChangeEvent,
} from 'react'

import { openExternalUrl, fs } from '@janhq/core'

import {
  Switch,
  Button,
  Input,
  Select,
  Checkbox,
  SelectContent,
  SelectGroup,
  SelectPortal,
  SelectLabel,
  SelectTrigger,
  SelectValue,
  Tooltip,
  TooltipArrow,
  TooltipContent,
  TooltipTrigger,
} from '@janhq/uikit'

import { AlertTriangleIcon, AlertCircleIcon } from 'lucide-react'

import ShortcutModal from '@/containers/ShortcutModal'

import { snackbar, toaster } from '@/containers/Toast'

import { FeatureToggleContext } from '@/context/FeatureToggle'

import { useSettings } from '@/hooks/useSettings'

import DataFolder from './DataFolder'
import FactoryReset from './FactoryReset'

type GPU = {
  id: string
  vram: number | null
  name: string
}

const Advanced = () => {
  const {
    experimentalFeature,
    setExperimentalFeature,
    ignoreSSL,
    setIgnoreSSL,
    proxy,
    setProxy,
  } = useContext(FeatureToggleContext)
  const [partialProxy, setPartialProxy] = useState<string>(proxy)
  const [gpuEnabled, setGpuEnabled] = useState<boolean>(false)
  const [gpuList, setGpuList] = useState<GPU[]>([])
  const [gpusInUse, setGpusInUse] = useState<string[]>([])
  const { readSettings, saveSettings, validateSettings, setShowNotification } =
    useSettings()

  const selectedGpu = gpuList
    .filter((x) => gpusInUse.includes(x.id))
    .map((y) => {
      return y['name']
    })

  const onProxyChange = useCallback(
    (event: ChangeEvent<HTMLInputElement>) => {
      const value = event.target.value || ''
      setPartialProxy(value)
      if (value.trim().startsWith('http')) {
        setProxy(value.trim())
      } else {
        setProxy('')
      }
    },
    [setPartialProxy, setProxy]
  )

  useEffect(() => {
    const setUseGpuIfPossible = async () => {
      const settings = await readSettings()
      setGpuEnabled(settings.run_mode === 'gpu' && gpuList.length > 0)
      setGpusInUse(settings.gpus_in_use || [])
      if (settings.gpus) {
        setGpuList(settings.gpus)
      }
    }
    setUseGpuIfPossible()
  }, [readSettings, gpuList])

  const clearLogs = async () => {
    if (await fs.existsSync(`file://logs`)) {
      await fs.rmdirSync(`file://logs`, { recursive: true })
    }
    toaster({
      title: 'Logs cleared',
      description: 'All logs have been cleared.',
      type: 'success',
    })
  }

  const handleGPUChange = (gpuId: string) => {
    // TODO detect current use GPU nvidia or AMD
    let updatedGpusInUse = [...gpusInUse]
    if (updatedGpusInUse.includes(gpuId)) {
      updatedGpusInUse = updatedGpusInUse.filter((id) => id !== gpuId)
      if (gpuEnabled && updatedGpusInUse.length === 0) {
        updatedGpusInUse.push(gpuId)
      }
    } else {
      updatedGpusInUse.push(gpuId)
    }
    setGpusInUse(updatedGpusInUse)
    saveSettings({ gpusInUse: updatedGpusInUse })
  }

  const gpuSelectionPlaceHolder =
    gpuList.length > 0 ? 'Select GPU' : "You don't have any compatible GPU"

  return (
    <div className="block w-full">
      {/* Keyboard shortcut  */}
      <div className="flex w-full items-start justify-between border-b border-border py-4 first:pt-0 last:border-none">
        <div className="flex-shrink-0 space-y-1.5">
          <div className="flex gap-x-2">
            <h6 className="text-sm font-semibold capitalize">
              Keyboard Shortcuts
            </h6>
          </div>
          <p className="leading-relaxed">
            Shortcuts that you might find useful in Jan app.
          </p>
        </div>
        <ShortcutModal />
      </div>

      {/* Experimental */}
      <div className="flex w-full items-start justify-between border-b border-border py-4 first:pt-0 last:border-none">
        <div className="flex-shrink-0 space-y-1.5">
          <div className="flex gap-x-2">
            <h6 className="text-sm font-semibold capitalize">
              Experimental Mode
            </h6>
          </div>
          <p className="leading-relaxed">
            Enable experimental features that may be unstable tested.
          </p>
        </div>
        <Switch
          checked={experimentalFeature}
          onCheckedChange={setExperimentalFeature}
        />
      </div>

      {/* CPU / GPU switching */}
      {!isMac && (
        <div className="flex w-full flex-col items-start justify-between border-b border-border py-4 first:pt-0 last:border-none">
          <div className="flex items-start justify-between w-full">
            <div className="space-y-1.5">
              <div className="flex gap-x-2">
                <h6 className="text-sm font-semibold capitalize">
                  GPU Acceleration
                </h6>
              </div>
              <p className="pr-8 leading-relaxed">
                Enable to enhance model performance by utilizing your devices
                GPU for acceleration. Read{' '}
                <span>
                  {' '}
                  <span
                    className="cursor-pointer text-blue-600"
                    onClick={() =>
                      openExternalUrl(
                        'https://jan.ai/guides/troubleshooting/gpu-not-used/'
                      )
                    }
                  >
                    troubleshooting guide
                  </span>{' '}
                </span>{' '}
                for further assistance.
              </p>
            </div>
            {gpuList.length > 0 && !gpuEnabled && (
              <Tooltip>
                <TooltipTrigger>
                  <AlertCircleIcon size={20} className="mr-2 text-yellow-600" />
                </TooltipTrigger>
                <TooltipContent
                  side="right"
                  sideOffset={10}
                  className="max-w-[240px]"
                >
                  <span>
                    Disabling GPU Acceleration may result in reduced
                    performance. It is recommended to keep this enabled for
                    optimal user experience.
                  </span>
                  <TooltipArrow />
                </TooltipContent>
              </Tooltip>
            )}

            <Tooltip>
              <TooltipTrigger>
                <Switch
                  disabled={gpuList.length === 0}
                  checked={gpuEnabled}
                  onCheckedChange={(e) => {
                    if (e === true) {
                      saveSettings({ runMode: 'gpu' })
                      setGpuEnabled(true)
                      setShowNotification(false)
                      snackbar({
                        description: 'Successfully turned on GPU Accelertion',
                        type: 'success',
                      })
                      setTimeout(() => {
                        validateSettings()
                      }, 300)
                    } else {
                      saveSettings({ runMode: 'cpu' })
                      setGpuEnabled(false)
                      snackbar({
                        description: 'Successfully turned off GPU Accelertion',
                        type: 'success',
                      })
                    }
                  }}
                />
              </TooltipTrigger>
              {gpuList.length === 0 && (
                <TooltipContent
                  side="right"
                  sideOffset={10}
                  className="max-w-[240px]"
                >
                  <span>
                    Your current device does not have a compatible GPU for
                    monitoring. To enable GPU monitoring, please ensure your
                    device has a supported Nvidia or AMD GPU with updated
                    drivers.
                  </span>
                  <TooltipArrow />
                </TooltipContent>
              )}
            </Tooltip>
          </div>
          <div className="mt-2 w-full rounded-lg bg-secondary p-4">
            <label className="mb-1 inline-block font-medium">Choose GPU</label>
            <Select
              disabled={gpuList.length === 0 || !gpuEnabled}
              value={selectedGpu.join()}
            >
              <SelectTrigger className="w-[340px] bg-white">
                <SelectValue placeholder={gpuSelectionPlaceHolder}>
                  <span className="line-clamp-1 w-full pr-8">
                    {selectedGpu.join()}
                  </span>
                </SelectValue>
              </SelectTrigger>
              <SelectPortal>
                <SelectContent className="w-[400px] px-1 pb-2">
                  <SelectGroup>
                    <SelectLabel>Nvidia</SelectLabel>
                    <div className="px-4 pb-2">
                      <div className="rounded-lg bg-secondary p-3">
                        {gpuList
                          .filter((gpu) =>
                            gpu.name.toLowerCase().includes('nvidia')
                          )
                          .map((gpu) => (
                            <div
                              key={gpu.id}
                              className="my-1 flex items-center space-x-2"
                            >
                              <Checkbox
                                id={`gpu-${gpu.id}`}
                                name="gpu-nvidia"
                                className="bg-white"
                                value={gpu.id}
                                checked={gpusInUse.includes(gpu.id)}
                                onCheckedChange={() => handleGPUChange(gpu.id)}
                              />
                              <label
                                className="flex w-full items-center justify-between"
                                htmlFor={`gpu-${gpu.id}`}
                              >
                                <span>{gpu.name}</span>
                                <span>{gpu.vram}MB VRAM</span>
                              </label>
                            </div>
                          ))}
                      </div>
                      {/* Warning message */}
                      {gpuEnabled && gpusInUse.length > 1 && (
                        <div className="mt-2 flex items-start space-x-2 text-yellow-500">
                          <AlertTriangleIcon
                            size={16}
                            className="flex-shrink-0"
                          />
                          <p className="text-xs leading-relaxed">
                            If multi-GPU is enabled with different GPU models or
                            without NVLink, it could impact token speed.
                          </p>
                        </div>
                      )}
                    </div>
                  </SelectGroup>

                  {/* TODO enable this when we support AMD */}
                </SelectContent>
              </SelectPortal>
            </Select>
          </div>
        </div>
      )}

      <DataFolder />
      {/* Proxy */}
      <div className="flex w-full items-start justify-between border-b border-border py-4 first:pt-0 last:border-none">
        <div className="flex-shrink-0 space-y-1.5">
          <div className="flex gap-x-2">
            <h6 className="text-sm font-semibold capitalize">HTTPS Proxy</h6>
          </div>
          <p className="leading-relaxed">
            Specify the HTTPS proxy or leave blank (proxy auto-configuration and
            SOCKS not supported).
          </p>
          <Input
            placeholder={'http://<user>:<password>@<domain or IP>:<port>'}
            value={partialProxy}
            onChange={onProxyChange}
          />
        </div>
      </div>

      {/* Ignore SSL certificates */}
      <div className="flex w-full items-start justify-between border-b border-border py-4 first:pt-0 last:border-none">
        <div className="flex-shrink-0 space-y-1.5">
          <div className="flex gap-x-2">
            <h6 className="text-sm font-semibold capitalize">
              Ignore SSL certificates
            </h6>
          </div>
          <p className="leading-relaxed">
            Allow self-signed or unverified certificates - may be required for
            certain proxies.
          </p>
        </div>
        <Switch checked={ignoreSSL} onCheckedChange={(e) => setIgnoreSSL(e)} />
      </div>

      {/* Clear log */}
      <div className="flex w-full items-start justify-between border-b border-border py-4 first:pt-0 last:border-none">
        <div className="flex-shrink-0 space-y-1.5">
          <div className="flex gap-x-2">
            <h6 className="text-sm font-semibold capitalize">Clear logs</h6>
          </div>
          <p className="leading-relaxed">Clear all logs from Jan app.</p>
        </div>
        <Button size="sm" themes="secondaryDanger" onClick={clearLogs}>
          Clear
        </Button>
      </div>

      {/* Factory Reset */}
      <FactoryReset />
    </div>
  )
}

export default Advanced
