import { useEffect, useMemo, useState } from 'react'
import { Code, Copy, KeyRound, Link2, Pencil, Plus, RefreshCw, Send, Trash2 } from 'lucide-react'
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { api, type NotifyBinding, type NotifyChannel, type Task } from '@/api'
import { useNotifyBindings, useNotifyChannels, useNotifyTypes } from '@/api/hooks'
import { Button, Card, Field, Input, Modal, PageHeader, Select, Switch, Tabs, Textarea } from '@/components/ui'
import { emptyConfigForType, getChannelFields } from '@/lib/notify-fields'
import { copyToClipboard } from '@/lib/format'
import { toast } from '@/lib/toast'

export default function Notify() {
  const [tab, setTab] = useState<'channels' | 'bindings' | 'templates' | 'api'>('channels')
  const [channelOpen, setChannelOpen] = useState(false)
  const [bindingOpen, setBindingOpen] = useState(false)
  const [editingChannel, setEditingChannel] = useState<NotifyChannel | null>(null)
  const [channelForm, setChannelForm] = useState<{
    name: string
    type: string
    enabled: boolean
    config: Record<string, string>
  }>({
    name: '',
    type: 'Telegram',
    enabled: true,
    config: emptyConfigForType('Telegram'),
  })
  const [bindingForm, setBindingForm] = useState({
    type: 'system',
    event: 'task_success',
    way_id: '',
    data_id: '',
  })
  const [testForm, setTestForm] = useState({ channel_id: '', title: '测试推送', text: '这是一条测试消息' })
  const [template, setTemplate] = useState({ title: '{{task_name}} {{status}}', body: '{{output}}' })
  const [message, setMessage] = useState('')
  const [apiToken, setApiToken] = useState('')
  const [notifyToken, setNotifyToken] = useState('')
  const [taskOptions, setTaskOptions] = useState<Task[]>([])
  const [generatingToken, setGeneratingToken] = useState(false)
  const qc = useQueryClient()

  const { data: channelsData, isLoading, refetch } = useNotifyChannels()
  const { data: bindingsData, refetch: refetchBindings } = useNotifyBindings()
  const { data: types } = useNotifyTypes()
  const channels = Array.isArray(channelsData) ? channelsData : []
  const bindings = Array.isArray(bindingsData) ? bindingsData : []
  const channelTypes = useMemo(() => {
    const list = Array.isArray(types?.channel_types) ? types!.channel_types : []
    if (list.length) return list
    return [
      { type: 'Telegram', label: 'Telegram' },
      { type: 'Bark', label: 'Bark' },
      { type: 'Dtalk', label: '钉钉' },
      { type: 'QyWeiXin', label: '企业微信' },
      { type: 'Feishu', label: '飞书' },
      { type: 'Custom', label: '自定义 Webhook' },
      { type: 'Ntfy', label: 'Ntfy' },
      { type: 'Gotify', label: 'Gotify' },
      { type: 'Email', label: 'Email' },
      { type: 'PushPlus', label: 'PushPlus' },
      { type: 'PushMe', label: 'PushMe' },
      { type: 'PushMes', label: 'PushMe' },
      { type: 'VoceChat', label: 'VoceChat' },
      { type: 'WxPusher', label: 'WxPusher' },
      { type: 'AliyunSMS', label: '阿里云短信' },
    ]
  }, [types])
  const eventTypes = useMemo(
    () =>
      Array.isArray(types?.event_types)
        ? types!.event_types
        : [
            { type: 'task_success', label: '任务成功' },
            { type: 'task_failed', label: '任务失败' },
            { type: 'task_timeout', label: '任务超时' },
          ],
    [types],
  )

  const fields = getChannelFields(channelForm.type)

  useEffect(() => {
    api.settings
      .getSite()
      .then((s: any) => setApiToken(s?.openapi_token || ''))
      .catch(() => setApiToken(''))
    api.settings
      .get('notify', 'notify_token')
      .then((t) => setNotifyToken(typeof t === 'string' ? t : ''))
      .catch(() => setNotifyToken(''))
    api.tasks
      .list({ page: 1, page_size: 1000 })
      .then((res) => setTaskOptions(Array.isArray(res?.data) ? res.data : []))
      .catch(() => setTaskOptions([]))
  }, [])

  const saveChannel = useMutation({
    mutationFn: () =>
      api.notify.saveChannel({
        id: editingChannel?.id,
        name: channelForm.name,
        type: channelForm.type,
        enabled: channelForm.enabled,
        config: channelForm.config,
      }),
    onSuccess: () => {
      setChannelOpen(false)
      setEditingChannel(null)
      setMessage('渠道已保存')
      toast.success('渠道已保存')
      qc.invalidateQueries({ queryKey: ['notifyChannels'] })
    },
    onError: (e: any) => {
      setMessage(e?.message || '保存失败')
      toast.error(e?.message || '保存失败')
    },
  })

  const deleteChannel = useMutation({
    mutationFn: (id: string) => api.notify.deleteChannel(id),
    onSuccess: () => {
      setMessage('渠道已删除')
      toast.success('渠道已删除')
      qc.invalidateQueries({ queryKey: ['notifyChannels'] })
    },
    onError: (e: any) => {
      setMessage(e?.message || '删除失败')
      toast.error(e?.message || '删除失败')
    },
  })

  const saveBinding = useMutation({
    mutationFn: () =>
      api.notify.saveBinding({
        type: bindingForm.type,
        event: bindingForm.event,
        way_id: bindingForm.way_id,
        data_id: bindingForm.data_id,
      }),
    onSuccess: () => {
      setBindingOpen(false)
      setMessage('绑定已保存')
      toast.success('绑定已保存')
      qc.invalidateQueries({ queryKey: ['notifyBindings'] })
    },
    onError: (e: any) => {
      setMessage(e?.message || '保存失败')
      toast.error(e?.message || '保存失败')
    },
  })

  const deleteBinding = useMutation({
    mutationFn: (id: string) => api.notify.deleteBinding(id),
    onSuccess: () => {
      toast.success('绑定已删除')
      qc.invalidateQueries({ queryKey: ['notifyBindings'] })
    },
    onError: (e: any) => toast.error(e?.message || '删除失败'),
  })

  const testSend = useMutation({
    mutationFn: () => api.notify.send(testForm),
    onSuccess: (res) => {
      if (res?.success === false) {
        const msg = res.error || '发送失败'
        setMessage(msg)
        toast.error(msg)
      } else {
        setMessage('测试消息已发送')
        toast.success('测试消息已发送')
      }
    },
    onError: (e: any) => {
      setMessage(e?.message || '发送失败')
      toast.error(e?.message || '发送失败')
    },
  })

  async function generateNotifyToken() {
    setGeneratingToken(true)
    try {
      const token = await api.settings.generateToken('notify', 'notify_token')
      setNotifyToken(typeof token === 'string' ? token : '')
      toast.success('Notify Token 已生成')
    } catch (e: any) {
      toast.error(e?.message || '生成失败')
    } finally {
      setGeneratingToken(false)
    }
  }

  async function copyText(text: string, okMsg: string) {
    if (!text) {
      toast.warning('内容为空')
      return
    }
    const ok = await copyToClipboard(text)
    if (ok) toast.success(okMsg)
    else toast.error('复制失败')
  }

  function openCreateChannel() {
    const type = channelTypes[0]?.type || 'Telegram'
    setEditingChannel(null)
    setChannelForm({
      name: '',
      type,
      enabled: true,
      config: emptyConfigForType(type),
    })
    setChannelOpen(true)
  }

  function openEditChannel(ch: NotifyChannel) {
    setEditingChannel(ch)
    setChannelForm({
      name: ch.name,
      type: ch.type,
      enabled: ch.enabled !== false,
      config: emptyConfigForType(ch.type, ch.config || {}),
    })
    setChannelOpen(true)
  }

  async function testChannel(ch: NotifyChannel) {
    try {
      const res = await api.notify.testChannel(ch)
      const msg = res?.success === false ? res.error || '测试失败' : '测试发送成功'
      setMessage(msg)
      if (res?.success === false) toast.error(msg)
      else toast.success(msg)
    } catch (e: any) {
      setMessage(e?.message || '测试失败')
      toast.error(e?.message || '测试失败')
    }
  }

  return (
    <div>
      <PageHeader
        title="消息推送"
        description="配置通知渠道、事件绑定与模板"
        actions={
          <>
            <Button
              variant="secondary"
              onClick={() => {
                refetch()
                refetchBindings()
              }}
            >
              <RefreshCw size={14} />
              刷新
            </Button>
            {tab === 'channels' ? (
              <Button onClick={openCreateChannel}>
                <Plus size={14} />
                新建渠道
              </Button>
            ) : null}
            {tab === 'bindings' ? (
              <Button
                onClick={() => {
                  setBindingForm({
                    type: 'system',
                    event: eventTypes[0]?.type || 'task_success',
                    way_id: channels[0]?.id || '',
                    data_id: '',
                  })
                  setBindingOpen(true)
                }}
              >
                <Plus size={14} />
                新建绑定
              </Button>
            ) : null}
          </>
        }
      />

      {message ? (
        <div className="mb-3 rounded-md border border-[var(--border)] bg-[var(--bg-tertiary)] px-3 py-2 text-sm">{message}</div>
      ) : null}

      <div className="mb-4">
        <Tabs
          value={tab}
          onValueChange={(v) => setTab(v as any)}
          items={[
            { value: 'channels', label: '渠道' },
            { value: 'bindings', label: '事件绑定' },
            { value: 'templates', label: '模板' },
            { value: 'api', label: 'API 用法' },
          ]}
        />
      </div>

      {tab === 'channels' ? (
        isLoading ? (
          <div className="text-sm text-[var(--text-muted)]">加载中...</div>
        ) : channels.length === 0 ? (
          <Card className="p-8 text-center text-sm text-[var(--text-muted)]">暂无渠道，点击新建</Card>
        ) : (
          <div className="grid gap-3 md:grid-cols-2 xl:grid-cols-3">
            {channels.map((ch) => (
              <Card key={ch.id} className="p-4">
                <div className="mb-2 flex items-start justify-between gap-2">
                  <div>
                    <div className="font-medium">{ch.name}</div>
                    <div className="text-xs text-[var(--text-muted)]">{ch.type}</div>
                  </div>
                  <span className={`text-xs ${ch.enabled === false ? 'text-[var(--text-muted)]' : 'text-emerald-500'}`}>
                    {ch.enabled === false ? '停用' : '启用'}
                  </span>
                </div>
                <div className="flex flex-wrap gap-2">
                  <Button size="sm" variant="secondary" onClick={() => openEditChannel(ch)}>
                    <Pencil size={14} />
                    编辑
                  </Button>
                  <Button size="sm" variant="secondary" onClick={() => testChannel(ch)}>
                    <Send size={14} />
                    测试
                  </Button>
                  <Button
                    size="sm"
                    variant="danger"
                    onClick={() => {
                      if (confirm('确认删除该渠道？')) deleteChannel.mutate(ch.id)
                    }}
                  >
                    <Trash2 size={14} />
                  </Button>
                </div>
              </Card>
            ))}
          </div>
        )
      ) : null}

      {tab === 'bindings' ? (
        <Card className="overflow-hidden">
          {bindings.length === 0 ? (
            <div className="p-8 text-center text-sm text-[var(--text-muted)]">暂无绑定</div>
          ) : (
            <div className="divide-y divide-[var(--border)]">
              {bindings.map((b: NotifyBinding) => (
                <div key={b.id} className="flex flex-wrap items-center justify-between gap-2 px-4 py-3 text-sm">
                  <div>
                    <div className="font-medium">
                      {b.event} · {b.type}
                    </div>
                    <div className="text-xs text-[var(--text-muted)]">
                      渠道: {channels.find((c) => c.id === b.way_id)?.name || b.way_id}
                      {b.data_id ? ` · 数据: ${b.data_id}` : ''}
                    </div>
                  </div>
                  <Button size="sm" variant="danger" onClick={() => deleteBinding.mutate(b.id)}>
                    <Trash2 size={14} />
                  </Button>
                </div>
              ))}
            </div>
          )}
        </Card>
      ) : null}

      {tab === 'templates' ? (
        <Card className="space-y-3 p-4">
          <div className="text-sm text-[var(--text-muted)]">消息模板（本地预览/参考，实际以服务端模板为准）</div>
          <Field label="标题模板">
            <Input value={template.title} onChange={(e) => setTemplate((t) => ({ ...t, title: e.target.value }))} />
          </Field>
          <Field label="正文模板">
            <Textarea className="min-h-[120px]" value={template.body} onChange={(e) => setTemplate((t) => ({ ...t, body: e.target.value }))} />
          </Field>
          <div className="rounded-md bg-[var(--bg-primary)] p-3 text-xs text-[var(--text-muted)]">
            可用变量示例: {'{{task_name}}'} {'{{status}}'} {'{{output}}'} {'{{error}}'} {'{{duration}}'}
          </div>
          <div className="border-t border-[var(--border)] pt-3">
            <div className="mb-2 text-sm font-medium">快速测试发送</div>
            <div className="grid gap-2 md:grid-cols-2">
              <Select value={testForm.channel_id} onChange={(e) => setTestForm((f) => ({ ...f, channel_id: e.target.value }))}>
                <option value="">选择渠道</option>
                {channels.map((c) => (
                  <option key={c.id} value={c.id}>
                    {c.name}
                  </option>
                ))}
              </Select>
              <Input value={testForm.title} onChange={(e) => setTestForm((f) => ({ ...f, title: e.target.value }))} placeholder="标题" />
            </div>
            <Textarea className="mt-2" value={testForm.text} onChange={(e) => setTestForm((f) => ({ ...f, text: e.target.value }))} />
            <Button className="mt-2" disabled={!testForm.channel_id || testSend.isPending} onClick={() => testSend.mutate()}>
              <Send size={14} />
              发送测试
            </Button>
          </div>
        </Card>
      ) : null}

      {tab === 'api' ? (
        <Card className="space-y-3 p-4">
          <div className="flex items-center gap-2 text-sm font-medium">
            <Code size={16} /> OpenAPI 推送用法
          </div>
          <div className="text-sm text-[var(--text-muted)]">Token: {apiToken || '（未生成，请到系统设置开启 OpenAPI）'}</div>
          <pre className="overflow-auto rounded-md bg-[var(--bg-primary)] p-3 font-mono text-xs whitespace-pre-wrap">
{`POST /api/v1/notify/send
Header: Authorization: Bearer <openapi_token>
Body:
{
  "channel_id": "<渠道ID>",
  "title": "标题",
  "text": "内容"
}`}
          </pre>
          <div className="flex items-center gap-2 text-xs text-[var(--text-muted)]">
            <Link2 size={12} /> 也可在「系统设置 → 站点」中管理 OpenAPI Token
          </div>
        </Card>
      ) : null}

      <Modal
        open={channelOpen}
        title={editingChannel ? '编辑渠道' : '新建渠道'}
        onClose={() => setChannelOpen(false)}
        size="lg"
        footer={
          <>
            <Button variant="secondary" onClick={() => setChannelOpen(false)}>
              取消
            </Button>
            <Button
              disabled={!channelForm.name || !channelForm.type || saveChannel.isPending}
              onClick={() => {
                const missing = fields.filter((f) => f.required && !channelForm.config[f.key]?.trim())
                if (missing.length) {
                  setMessage(`请填写必填项: ${missing.map((m) => m.label).join(', ')}`)
                  return
                }
                saveChannel.mutate()
              }}
            >
              保存
            </Button>
          </>
        }
      >
        <div className="space-y-3">
          <Field label="名称">
            <Input value={channelForm.name} onChange={(e) => setChannelForm((f) => ({ ...f, name: e.target.value }))} />
          </Field>
          <Field label="类型">
            <Select
              value={channelForm.type}
              onChange={(e) => {
                const type = e.target.value
                setChannelForm((f) => ({
                  ...f,
                  type,
                  config: emptyConfigForType(type, f.config),
                }))
              }}
            >
              {channelTypes.map((t) => (
                <option key={t.type} value={t.type}>
                  {t.label || t.type}
                </option>
              ))}
            </Select>
          </Field>
          {fields.map((field) => (
            <Field key={field.key} label={`${field.label}${field.required ? ' *' : ''}`}>
              {field.type === 'textarea' ? (
                <Textarea
                  value={channelForm.config[field.key] || ''}
                  placeholder={field.placeholder}
                  onChange={(e) =>
                    setChannelForm((f) => ({
                      ...f,
                      config: { ...f.config, [field.key]: e.target.value },
                    }))
                  }
                />
              ) : (
                <Input
                  value={channelForm.config[field.key] || ''}
                  placeholder={field.placeholder}
                  onChange={(e) =>
                    setChannelForm((f) => ({
                      ...f,
                      config: { ...f.config, [field.key]: e.target.value },
                    }))
                  }
                />
              )}
            </Field>
          ))}
          {!fields.length ? (
            <Field label="额外配置 (JSON)">
              <Textarea
                value={channelForm.config.extra || ''}
                placeholder='{"key":"value"}'
                onChange={(e) =>
                  setChannelForm((f) => ({
                    ...f,
                    config: { ...f.config, extra: e.target.value },
                  }))
                }
              />
            </Field>
          ) : null}
          <label className="flex items-center justify-between text-sm">
            <span>启用</span>
            <Switch checked={channelForm.enabled} onCheckedChange={(v) => setChannelForm((f) => ({ ...f, enabled: v }))} />
          </label>
        </div>
      </Modal>

      <Modal
        open={bindingOpen}
        title="新建绑定"
        onClose={() => setBindingOpen(false)}
        footer={
          <>
            <Button variant="secondary" onClick={() => setBindingOpen(false)}>
              取消
            </Button>
            <Button disabled={!bindingForm.way_id || saveBinding.isPending} onClick={() => saveBinding.mutate()}>
              保存
            </Button>
          </>
        }
      >
        <div className="space-y-3">
          <Field label="类型">
            <Select value={bindingForm.type} onChange={(e) => setBindingForm((f) => ({ ...f, type: e.target.value }))}>
              <option value="system">系统</option>
              <option value="task">任务</option>
            </Select>
          </Field>
          <Field label="事件">
            <Select value={bindingForm.event} onChange={(e) => setBindingForm((f) => ({ ...f, event: e.target.value }))}>
              {eventTypes.map((e) => (
                <option key={e.type} value={e.type}>
                  {e.label || e.type}
                </option>
              ))}
            </Select>
          </Field>
          <Field label="渠道">
            <Select value={bindingForm.way_id} onChange={(e) => setBindingForm((f) => ({ ...f, way_id: e.target.value }))}>
              <option value="">选择渠道</option>
              {channels.map((c) => (
                <option key={c.id} value={c.id}>
                  {c.name}
                </option>
              ))}
            </Select>
          </Field>
          {bindingForm.type === 'task' ? (
            <Field label="任务（可选，留空表示全部任务）">
              <Select value={bindingForm.data_id} onChange={(e) => setBindingForm((f) => ({ ...f, data_id: e.target.value }))}>
                <option value="">全部任务</option>
                {taskOptions.map((t) => (
                  <option key={t.id} value={t.id}>
                    {t.name}
                  </option>
                ))}
              </Select>
            </Field>
          ) : null}
        </div>
      </Modal>
    </div>
  )
}
