import { Bot, Eye, KeyRound, ListRestart, Loader2, Save, SlidersHorizontal } from 'lucide-react'
import { useEffect, useState } from 'react'
import { toast } from 'sonner'

import { Button } from '@renderer/components/ui/button'
import { Card, CardContent, CardHeader } from '@renderer/components/ui/card'
import { Input } from '@renderer/components/ui/input'
import { ScrollArea } from '@renderer/components/ui/scroll-area'
import type { ModelConfig, SettingKey } from '@renderer/types/app'

import { Field } from './Field'

const defaultModelConfig: ModelConfig = {
  provider: 'OpenAI Compatible',
  baseUrl: 'https://api.openai.com/v1',
  apiKey: '',
  model: 'gpt-4.1-mini',
  temperature: '0.7',
  maxTokens: '1200',
  systemPrompt: '你是一名幼儿园教师，请根据幼儿观察记录生成温暖、具体、正向的成长评语。'
}

export function ModelSettingsForm(): React.JSX.Element {
  const [setting, setSetting] = useState<SettingKey>('model')
  const [modelConfig, setModelConfig] = useState<ModelConfig>(defaultModelConfig)
  const [modelOptions, setModelOptions] = useState<string[]>([])
  const [modelListLoading, setModelListLoading] = useState(false)
  const [settingsSaving, setSettingsSaving] = useState(false)
  const [connectionTesting, setConnectionTesting] = useState(false)

  const updateModelConfig = (key: keyof ModelConfig, value: string): void => {
    setModelConfig((current) => ({ ...current, [key]: value }))
  }

  useEffect(() => {
    window.api.loadSettings().then((response) => {
      if (!response.ok) {
        toast.error(response.message)
        return
      }

      if (response.modelConfig) {
        setModelConfig(response.modelConfig)
        setModelOptions((options) =>
          response.modelConfig && !options.includes(response.modelConfig.model)
            ? [response.modelConfig.model, ...options]
            : options
        )
        toast.success('已加载本地配置')
      }
    })
  }, [])

  const fetchModelList = async (): Promise<void> => {
    setModelListLoading(true)

    try {
      const response = await window.api.listModels({
        baseUrl: modelConfig.baseUrl,
        apiKey: modelConfig.apiKey
      })

      if (!response.ok) {
        toast.error(response.message)
        return
      }

      setModelOptions(response.models)
      toast.success(`已获取 ${response.models.length} 个模型`)

      if (!response.models.includes(modelConfig.model)) {
        updateModelConfig('model', response.models[0])
      }
    } finally {
      setModelListLoading(false)
    }
  }

  const saveSettings = async (): Promise<void> => {
    setSettingsSaving(true)

    try {
      const response = await window.api.saveSettings(modelConfig)

      if (!response.ok) {
        toast.error(response.message)
        return
      }

      toast.success('配置已保存')
    } finally {
      setSettingsSaving(false)
    }
  }

  const testConnection = async (): Promise<void> => {
    setConnectionTesting(true)

    try {
      const response = await window.api.testModelConnection(modelConfig)

      if (!response.ok) {
        toast.error(response.message)
        return
      }

      toast.success(response.message)
    } finally {
      setConnectionTesting(false)
    }
  }

  return (
    <section className="grid h-[calc(100vh-9rem)] min-h-130 grid-cols-[240px_minmax(0,1fr)] overflow-hidden rounded-lg border bg-card max-[900px]:h-auto max-[900px]:grid-cols-1">
      <aside className="flex min-h-0 flex-col border-r bg-card max-[900px]:border-b max-[900px]:border-r-0">
        <div className="shrink-0 px-4 py-4">
          <h3 className="text-base font-semibold">设置项</h3>
        </div>
        <ScrollArea className="min-h-0 flex-1 px-3 py-3">
          <nav className="space-y-1">
            <Button
              className="h-10 w-full justify-start gap-2 px-3"
              variant={setting === 'model' ? 'secondary' : 'ghost'}
              type="button"
              onClick={() => setSetting('model')}
            >
              <Bot className="size-4" />
              大模型配置
            </Button>
          </nav>
        </ScrollArea>
      </aside>

      <Card className="min-h-0 overflow-hidden rounded-none border-0 shadow-none">
        <CardHeader className="flex flex-row items-center justify-between gap-4 space-y-0 border-b">
          <div>大模型配置</div>
          <div className="flex shrink-0 gap-2">
            <Button
              variant="outline"
              type="button"
              onClick={testConnection}
              disabled={connectionTesting}
            >
              {connectionTesting && <Loader2 className="size-4 animate-spin" />}
              测试连接
            </Button>
            <Button type="button" onClick={saveSettings} disabled={settingsSaving}>
              {settingsSaving ? (
                <Loader2 className="size-4 animate-spin" />
              ) : (
                <Save className="size-4" />
              )}
              保存配置
            </Button>
          </div>
        </CardHeader>
        <ScrollArea className="h-[calc(100%-5.75rem)] max-[900px]:h-auto">
          <CardContent className="space-y-6 p-6">
            <div className="grid grid-cols-2 gap-4 max-[900px]:grid-cols-1">
              <Field label="供应商">
                <Input
                  value={modelConfig.provider}
                  onChange={(event) => updateModelConfig('provider', event.target.value)}
                  placeholder="OpenAI Compatible"
                />
              </Field>
              <Field label="模型名称">
                <Input
                  list="model-options"
                  value={modelConfig.model}
                  onChange={(event) => updateModelConfig('model', event.target.value)}
                  placeholder="输入或从候选模型中选择"
                />
                <datalist id="model-options">
                  {modelOptions.map((model) => (
                    <option value={model} key={model} />
                  ))}
                </datalist>
              </Field>
            </div>

            <Field label="接口地址">
              <Input
                value={modelConfig.baseUrl}
                onChange={(event) => updateModelConfig('baseUrl', event.target.value)}
                placeholder="https://api.openai.com/v1"
              />
            </Field>

            <Field label="API Key">
              <div className="flex gap-2">
                <div className="relative flex-1">
                  <KeyRound className="pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" />
                  <Input
                    className="pl-9"
                    type="password"
                    value={modelConfig.apiKey}
                    onChange={(event) => updateModelConfig('apiKey', event.target.value)}
                    placeholder="sk-..."
                  />
                </div>
                <Button variant="outline" size="icon" type="button" title="后续可切换明文显示">
                  <Eye className="size-4" />
                </Button>
              </div>
            </Field>

            <div className="flex flex-wrap items-center gap-3 rounded-md border bg-muted/30 p-3">
              <Button
                type="button"
                variant="outline"
                onClick={fetchModelList}
                disabled={modelListLoading}
              >
                {modelListLoading ? (
                  <Loader2 className="size-4 animate-spin" />
                ) : (
                  <ListRestart className="size-4" />
                )}
                获取模型列表
              </Button>
              <p className="text-sm text-muted-foreground">
                根据接口地址和 API Key 获取可用模型后，再选择模型名称。
              </p>
            </div>

            <div className="grid grid-cols-2 gap-4 max-[900px]:grid-cols-1">
              <Field label="温度">
                <div className="relative">
                  <SlidersHorizontal className="pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" />
                  <Input
                    className="pl-9"
                    value={modelConfig.temperature}
                    onChange={(event) => updateModelConfig('temperature', event.target.value)}
                    placeholder="0.7"
                  />
                </div>
              </Field>
              <Field label="最大输出 Token">
                <Input
                  value={modelConfig.maxTokens}
                  onChange={(event) => updateModelConfig('maxTokens', event.target.value)}
                  placeholder="1200"
                />
              </Field>
            </div>

            <Field label="系统提示词">
              <textarea
                className="min-h-28 w-full resize-y rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm outline-none transition-colors placeholder:text-muted-foreground focus-visible:ring-1 focus-visible:ring-ring"
                value={modelConfig.systemPrompt}
                onChange={(event) => updateModelConfig('systemPrompt', event.target.value)}
                placeholder="请输入生成评语时使用的系统提示词"
              />
            </Field>

            <p className="border-t pt-5 text-sm text-muted-foreground">
              当前配置将作为“生成评语”工具的大模型参数来源。
            </p>
          </CardContent>
        </ScrollArea>
      </Card>
    </section>
  )
}
