import { useCallback, useEffect, useState } from 'react'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import {
  CheckCircle2,
  Cloud,
  CloudOff,
  Database,
  HardDrive,
  Loader2,
  RefreshCw,
  Save,
  Settings,
  Upload,
} from 'lucide-react'
import { toast } from '@/components/Toast'
import { PageHeader } from '@/components/PageHeader'
import { api, type SyncStatusResponse, type SyncPushResponse } from '@/lib/api'
import { cn } from '@/lib/cn'

type PartEntry = {
  key: string
  label: string
}

const ALL_PARTS: PartEntry[] = [
  { key: 'kline_daily', label: '日 K 线' },
  { key: 'kline_daily_enriched', label: '日 K 增强' },
  { key: 'kline_index_daily', label: '指数日 K' },
  { key: 'kline_index_enriched', label: '指数日 K 增强' },
  { key: 'kline_etf_daily', label: 'ETF 日 K' },
  { key: 'kline_etf_enriched', label: 'ETF 日 K 增强' },
  { key: 'kline_etf_minute', label: 'ETF 分钟 K' },
  { key: 'kline_minute', label: '分钟 K' },
  { key: 'adj_factor', label: '复权因子' },
  { key: 'adj_factor_etf', label: 'ETF 复权因子' },
  { key: 'instruments', label: '股票列表' },
  { key: 'instruments_index', label: '指数列表' },
  { key: 'instruments_etf', label: 'ETF 列表' },
  { key: 'financials', label: '财务数据' },
  { key: 'pools', label: '板块池' },
  { key: 'ext_data', label: '扩展数据(概念/行业)' },
]

function fmtSize(bytes: number): string {
  if (bytes === 0) return '—'
  if (bytes < 1024) return `${bytes} B`
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`
  return `${(bytes / (1024 * 1024)).toFixed(1)} MB`
}

export function Sync() {
  const qc = useQueryClient()
  const [showSettings, setShowSettings] = useState(false)
  const [serveUrl, setServeUrl] = useState('')
  const [syncKey, setSyncKey] = useState('')
  const [selected, setSelected] = useState<Set<string>>(new Set(ALL_PARTS.map(p => p.key)))

  // Status
  const { data: status, isLoading, refetch } = useQuery<SyncStatusResponse>({
    queryKey: ['sync-status'],
    queryFn: api.syncStatus,
    refetchInterval: 30000,
  })

  // Init form from server config
  useEffect(() => {
    if (status?.config) {
      setServeUrl(status.config.serve_url)
      setSyncKey(status.config.sync_key)
    }
  }, [status?.config])

  // Save config
  const saveCfg = useMutation<{ ok: boolean }, Error, void>({
    mutationFn: () => api.syncConfig({ serve_url: serveUrl, sync_key: syncKey }),
    onSuccess: () => {
      toast('同步配置已保存', 'success')
      qc.invalidateQueries({ queryKey: ['sync-status'] })
      setShowSettings(false)
    },
  })

  // Push sync
  const push = useMutation<SyncPushResponse, Error, void>({
    mutationFn: () => api.syncPush([...selected]),
    onSuccess: (res) => {
      if (res.ok) {
        toast(
          `同步完成: ${res.parts_sent.length} 个目录, ${res.serve_response.file_count} 个文件`,
          'success',
        )
        qc.invalidateQueries({ queryKey: ['sync-status'] })
      }
    },
  })

  const togglePart = useCallback((key: string) => {
    setSelected(prev => {
      const next = new Set(prev)
      if (next.has(key)) next.delete(key)
      else next.add(key)
      return next
    })
  }, [])

  const selectAll = () => setSelected(new Set(ALL_PARTS.map(p => p.key)))
  const selectNone = () => setSelected(new Set())

  return (
    <div className="mx-auto max-w-5xl space-y-6 px-4 py-6">
      <PageHeader
        title="数据同步"
        subtitle="将本地数据推送到 serve 服务器"
      />

      {/* 连接配置 */}
      <section className="rounded-card border border-border bg-surface p-5">
        <div className="flex items-center justify-between">
          <div className="flex items-center gap-2">
            {status?.config.serve_url ? (
              <Cloud className="h-5 w-5 text-accent" />
            ) : (
              <CloudOff className="h-5 w-5 text-muted" />
            )}
            <div>
              <div className="text-sm font-medium text-foreground">Serve 连接</div>
              <div className="text-xs text-muted">
                {status?.config.serve_url
                  ? status.config.serve_url
                  : '未配置 — 点击右侧设置按钮'}
              </div>
            </div>
          </div>
          <div className="flex items-center gap-2">
            {status?.last_sync && (
              <span className="text-[10px] text-muted">
                上次同步: {new Date(status.last_sync).toLocaleString('zh-CN')}
              </span>
            )}
            <button
              onClick={() => { setShowSettings(v => !v); refetch() }}
              className="rounded-btn p-2 text-muted hover:text-foreground hover:bg-elevated transition-colors"
              title="同步设置"
            >
              <Settings className="h-4 w-4" />
            </button>
            <button
              onClick={() => refetch()}
              className="rounded-btn p-2 text-muted hover:text-foreground hover:bg-elevated transition-colors"
              title="刷新状态"
            >
              <RefreshCw className={cn('h-4 w-4', isLoading && 'animate-spin')} />
            </button>
          </div>
        </div>

        {showSettings && (
          <div className="mt-4 space-y-3 border-t border-border pt-4">
            <div>
              <label className="text-xs text-muted">Serve 地址</label>
              <input
                value={serveUrl}
                onChange={e => setServeUrl(e.target.value)}
                placeholder="http://your-server:3018"
                className="mt-1 w-full rounded border border-border bg-base px-3 py-2 text-sm text-foreground placeholder:text-muted focus:border-accent focus:outline-none"
              />
            </div>
            <div>
              <label className="text-xs text-muted">同步 Key（可选）</label>
              <input
                value={syncKey}
                onChange={e => setSyncKey(e.target.value)}
                placeholder="留空则不校验"
                type="password"
                className="mt-1 w-full rounded border border-border bg-base px-3 py-2 text-sm text-foreground placeholder:text-muted focus:border-accent focus:outline-none"
              />
            </div>
            <button
              onClick={() => saveCfg.mutate()}
              disabled={saveCfg.isPending}
              className="inline-flex items-center gap-2 rounded-btn bg-accent px-4 py-2 text-sm font-medium text-white hover:bg-accent/90 disabled:opacity-50 transition-colors"
            >
              {saveCfg.isPending ? (
                <Loader2 className="h-4 w-4 animate-spin" />
              ) : (
                <Save className="h-4 w-4" />
              )}
              保存配置
            </button>
          </div>
        )}
      </section>

      {/* 数据选择 */}
      <section className="rounded-card border border-border bg-surface p-5">
        <div className="flex items-center justify-between">
          <h3 className="text-sm font-medium text-foreground">选择要同步的数据</h3>
          <div className="flex items-center gap-2">
            <button
              onClick={selectAll}
              className="text-xs text-accent hover:text-accent/80 transition-colors"
            >
              全选
            </button>
            <span className="text-xs text-muted">/</span>
            <button
              onClick={selectNone}
              className="text-xs text-accent hover:text-accent/80 transition-colors"
            >
              取消
            </button>
          </div>
        </div>

        <div className="mt-3 grid grid-cols-2 gap-2">
          {ALL_PARTS.map(({ key, label }) => {
            const info = status?.parts?.[key]
            const hasData = info && info.file_count > 0
            return (
              <label
                key={key}
                className={cn(
                  'flex items-center gap-3 rounded-lg border px-3 py-2.5 cursor-pointer transition-colors',
                  selected.has(key)
                    ? 'border-accent/40 bg-accent/5'
                    : 'border-border bg-base hover:border-muted',
                )}
              >
                <input
                  type="checkbox"
                  checked={selected.has(key)}
                  onChange={() => togglePart(key)}
                  className="h-4 w-4 rounded border-border text-accent focus:ring-accent"
                />
                <div className="min-w-0 flex-1">
                  <div className="flex items-center gap-1.5">
                    <span className="text-sm text-foreground">{label}</span>
                    {hasData && (
                      <HardDrive className="h-3 w-3 text-accent shrink-0" />
                    )}
                  </div>
                  {info && (
                    <div className="mt-0.5 text-[10px] text-muted">
                      {info.file_count > 0
                        ? `${info.file_count} 文件 · ${fmtSize(info.size_bytes)}`
                        : '无数据'}
                    </div>
                  )}
                </div>
              </label>
            )
          })}
        </div>
      </section>

      {/* 操作 */}
      <section className="flex items-center justify-between rounded-card border border-border bg-surface p-5">
        <div className="flex items-center gap-2 text-sm text-muted">
          <Database className="h-4 w-4" />
          <span>
            已选 {selected.size} 个目录
            {push.data && (
              <span className="ml-2 text-bull">
                <CheckCircle2 className="inline h-3.5 w-3.5 mr-0.5" />
                上次同步成功
              </span>
            )}
          </span>
        </div>
        <button
          onClick={() => push.mutate()}
          disabled={push.isPending || selected.size === 0}
          className="inline-flex items-center gap-2 rounded-btn bg-accent px-5 py-2.5 text-sm font-medium text-white hover:bg-accent/90 disabled:opacity-50 transition-colors"
        >
          {push.isPending ? (
            <>
              <Loader2 className="h-4 w-4 animate-spin" />
              同步中…
            </>
          ) : (
            <>
              <Upload className="h-4 w-4" />
              立即同步
            </>
          )}
        </button>
      </section>

      {/* 同步日志 */}
      {push.data && (
        <section className="rounded-card border border-border bg-surface p-4">
          <div className="text-xs text-muted font-mono leading-relaxed">
            <div>✓ 同步完成</div>
            <div>  目录: {push.data.parts_sent.join(', ')}</div>
            <div>  数据包: {fmtSize(push.data.size_bytes)}</div>
            <div>  文件数: {push.data.serve_response.file_count}</div>
          </div>
        </section>
      )}

      {push.error && (
        <section className="rounded-card border border-danger/30 bg-danger/5 p-4">
          <div className="text-xs text-danger font-mono leading-relaxed">
            <div>✗ 同步失败</div>
            <div>  {String(push.error)}</div>
          </div>
        </section>
      )}
    </div>
  )
}
