// Commands page: history + a console to send new commands to a chosen router.

import { useState } from 'react'
import { useQuery, useQueryClient } from '@tanstack/react-query'
import { useMutation } from '@tanstack/react-query'
import { format } from 'date-fns'
import { CheckCircle2, Clock, Loader2, Play, Send, XCircle, Zap } from 'lucide-react'
import { api } from '../lib/api'
import { Button, Card, FadeIn, Input, Pill, Skeleton } from '../components/ui'

const COMMANDS = [
  { name: 'reboot', label: 'Reboot', danger: true, args: [] as string[] },
  { name: 'wifi_restart', label: 'Restart WiFi', danger: false, args: [] as string[] },
  { name: 'status', label: 'Get status', danger: false, args: [] as string[] },
  { name: 'shell', label: 'Run shell', danger: true, args: ['command'] },
  { name: 'uci_set', label: 'Set UCI', danger: true, args: ['config', 'section', 'option', 'value'] },
] as const

export function CommandsPage() {
  const qc = useQueryClient()
  const [routerId, setRouterId] = useState('')
  const [selectedCmd, setSelectedCmd] = useState<typeof COMMANDS[number] | null>(null)
  const [args, setArgs] = useState<Record<string, string>>({})
  const [lastResult, setLastResult] = useState<{ ok: boolean; msg: string } | null>(null)

  const { data: routers } = useQuery({ queryKey: ['routers'], queryFn: api.routers, refetchInterval: 5_000 })
  const { data: cmds, isLoading } = useQuery({
    queryKey: ['commands', routerId],
    queryFn: () => api.commands({ limit: 50, router_id: routerId }),
    refetchInterval: 5_000,
  })

  const send = useMutation({
    mutationFn: () => api.sendCommand(routerId, selectedCmd!.name, args),
    onSuccess: (res) => {
      setLastResult({ ok: true, msg: `Command ${res.status}. id=${res.command_id}` })
      setArgs({})
      qc.invalidateQueries({ queryKey: ['commands'] })
    },
    onError: (e: Error) => {
      setLastResult({ ok: false, msg: e.message })
    },
  })

  const statusTone = (s: string) => {
    if (s === 'completed' || s === 'delivered') return 'success'
    if (s === 'queued' || s === 'pending') return 'warning'
    if (s === 'timeout' || s === 'publish_failed') return 'danger'
    return 'neutral'
  }

  const statusIcon = (s: string) => {
    if (s === 'completed') return <CheckCircle2 className="w-3 h-3" />
    if (s === 'queued' || s === 'pending') return <Clock className="w-3 h-3" />
    if (s === 'timeout' || s === 'publish_failed') return <XCircle className="w-3 h-3" />
    return null
  }

  return (
    <div className="flex flex-col gap-8">
      <FadeIn>
        <h1 className="text-h1 mb-2">Commands</h1>
        <p className="text-body-lg text-ink-400">Send instructions to any router in your fleet</p>
      </FadeIn>

      {/* Console */}
      <FadeIn delay={0.05}>
        <Card padding="lg">
          <div className="flex items-center gap-2 mb-5">
            <Zap className="w-4 h-4 text-amber-400" />
            <h2 className="text-h3">Command console</h2>
          </div>

          <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
            <div className="flex flex-col gap-4">
              <div>
                <span className="text-caption text-ink-500 uppercase tracking-wider mb-1.5 block">Target router</span>
                <select
                  value={routerId}
                  onChange={(e) => setRouterId(e.target.value)}
                  className="w-full bg-white/5 border border-white/10 rounded-xl px-4 py-3 text-body text-ink-100 focus:border-[var(--accent)] focus:outline-none"
                >
                  <option value="">Select a router…</option>
                  {routers?.routers.map((r) => (
                    <option key={r.id} value={r.id}>{r.id} {r.online ? '🟢' : '⚫'}</option>
                  ))}
                </select>
              </div>

              <div>
                <span className="text-caption text-ink-500 uppercase tracking-wider mb-1.5 block">Command</span>
                <div className="flex flex-wrap gap-1.5">
                  {COMMANDS.map((c) => (
                    <button
                      key={c.name}
                      onClick={() => { setSelectedCmd(c); setArgs({}) }}
                      className={`pill transition-colors ${
                        selectedCmd?.name === c.name
                          ? c.danger ? 'bg-rose-500/20 text-rose-200' : 'bg-blue-500/20 text-blue-200'
                          : 'bg-white/5 text-ink-300 hover:bg-white/10'
                      }`}
                    >
                      {c.label}
                    </button>
                  ))}
                </div>
              </div>
            </div>

            <div className="flex flex-col gap-3">
              {selectedCmd && selectedCmd.args.length > 0 && (
                <div className="flex flex-col gap-3">
                  {selectedCmd.args.map((a) => (
                    <Input
                      key={a}
                      label={a}
                      value={args[a] ?? ''}
                      onChange={(e) => setArgs((p) => ({ ...p, [a]: e.target.value }))}
                      placeholder={`Enter ${a}…`}
                    />
                  ))}
                </div>
              )}
              {selectedCmd && selectedCmd.args.length === 0 && (
                <div className="text-caption text-ink-500 italic">
                  This command takes no arguments.
                </div>
              )}
              {!selectedCmd && (
                <div className="text-caption text-ink-500">Select a command to continue.</div>
              )}

              <Button
                size="lg"
                disabled={!routerId || !selectedCmd || send.isPending}
                onClick={() => send.mutate()}
                variant={selectedCmd?.danger ? 'danger' : 'primary'}
                className="self-end"
              >
                {send.isPending ? <Loader2 className="w-4 h-4 animate-spin" /> : <Send className="w-4 h-4" />}
                Send
              </Button>
            </div>
          </div>

          {lastResult && (
            <div className={`mt-4 p-3 rounded-xl text-small ${lastResult.ok ? 'bg-emerald-500/10 text-emerald-200' : 'bg-rose-500/10 text-rose-200'}`}>
              {lastResult.msg}
            </div>
          )}
        </Card>
      </FadeIn>

      {/* History */}
      <FadeIn delay={0.1}>
        <div className="flex items-center justify-between mb-4">
          <h2 className="text-h3">History</h2>
          <span className="text-caption text-ink-500">{cmds?.commands.length ?? 0} commands</span>
        </div>

        {isLoading && (
          <div className="flex flex-col gap-2">
            {Array.from({ length: 4 }).map((_, i) => <Skeleton key={i} className="h-14" />)}
          </div>
        )}

        {!isLoading && (cmds?.commands.length ?? 0) === 0 && (
          <Card padding="lg" className="text-center">
            <Play className="w-8 h-8 mx-auto mb-2 text-ink-500" />
            <p className="text-body text-ink-300">No commands sent yet</p>
          </Card>
        )}

        <div className="flex flex-col gap-1.5">
          {cmds?.commands.map((c) => (
            <Card key={c.id} padding="sm">
              <div className="flex items-center gap-4 px-2 py-1">
                <Pill tone={statusTone(c.status)}>
                  {statusIcon(c.status)}
                  {c.status}
                </Pill>
                <div className="flex-1 min-w-0">
                  <div className="text-small font-medium text-ink-200">
                    {c.command}
                    {c.router_id && <span className="text-ink-500 font-normal"> → {c.router_id}</span>}
                  </div>
                  {c.result && (
                    <div className="text-caption text-ink-500 truncate mt-0.5">
                      {c.result.success ? c.result.output : c.result.error}
                    </div>
                  )}
                </div>
                <div className="text-caption text-ink-500 shrink-0 text-right">
                  <div>{c.issued_by}</div>
                  <div className="text-[10px]">{format(new Date(c.ts), 'MMM d HH:mm:ss')}</div>
                </div>
              </div>
            </Card>
          ))}
        </div>
      </FadeIn>
    </div>
  )
}
