/**
 * TemplatePushWizard -- multi-step dialog for pushing a template to devices.
 * Steps: Target Selection -> Variable Input -> Preview -> Confirm & Push -> Progress
 */

import { useState } from 'react'
import { useQuery, useMutation } from '@tanstack/react-query'
import { ChevronLeft, ChevronRight, Loader2, AlertTriangle, Play } from 'lucide-react'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { Checkbox } from '@/components/ui/checkbox'
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
} from '@/components/ui/dialog'
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select'
import { cn } from '@/lib/utils'
import {
  templatesApi,
  type TemplateResponse,
} from '@/lib/templatesApi'
import { deviceGroupsApi, metricsApi } from '@/lib/api'
import { PushProgressPanel } from './PushProgressPanel'

interface TemplatePushWizardProps {
  open: boolean
  onClose: () => void
  tenantId: string
  template: TemplateResponse
}

type WizardStep = 'targets' | 'variables' | 'preview' | 'confirm' | 'progress'

export function TemplatePushWizard({ open, onClose, tenantId, template }: TemplatePushWizardProps) {
  const [step, setStep] = useState<WizardStep>('targets')
  const [selectedDeviceIds, setSelectedDeviceIds] = useState<Set<string>>(new Set())
  const [variables, setVariables] = useState<Record<string, string>>(() => {
    const defaults: Record<string, string> = {}
    for (const v of template.variables) {
      if (v.default) defaults[v.name] = v.default
    }
    return defaults
  })
  const [previewDevice, setPreviewDevice] = useState<string | null>(null)
  const [previews, setPreviews] = useState<Record<string, string>>({})
  const [rolloutId, setRolloutId] = useState<string | null>(null)

  // Fetch devices
  const { data: devices } = useQuery({
    queryKey: ['fleet-devices', tenantId],
    queryFn: () => metricsApi.fleetSummary(tenantId),
    enabled: open,
  })

  // Fetch groups
  const { data: groups } = useQuery({
    queryKey: ['device-groups', tenantId],
    queryFn: () => deviceGroupsApi.list(tenantId),
    enabled: open,
  })

  // Preview mutation
  const previewMutation = useMutation({
    mutationFn: ({ deviceId }: { deviceId: string }) =>
      templatesApi.preview(tenantId, template.id, deviceId, variables),
    onSuccess: (data, { deviceId }) => {
      setPreviews((prev) => ({ ...prev, [deviceId]: data.rendered }))
    },
  })

  // Push mutation
  const pushMutation = useMutation({
    mutationFn: () =>
      templatesApi.push(tenantId, template.id, Array.from(selectedDeviceIds), variables),
    onSuccess: (data) => {
      setRolloutId(data.rollout_id)
      setStep('progress')
    },
  })

  const selectedDevices = devices?.filter((d) => selectedDeviceIds.has(d.id)) ?? []

  const handleGroupSelect = (_groupId: string) => {
    // For now, just select all online devices. In a real implementation,
    // we'd load group members from the API. Here we select all devices
    // as a simplified approach.
    if (devices) {
      const onlineIds = new Set(devices.filter((d) => d.status === 'online').map((d) => d.id))
      setSelectedDeviceIds(onlineIds)
    }
  }

  const toggleDevice = (deviceId: string) => {
    setSelectedDeviceIds((prev) => {
      const next = new Set(prev)
      if (next.has(deviceId)) {
        next.delete(deviceId)
      } else {
        next.add(deviceId)
      }
      return next
    })
  }

  const goToPreview = () => {
    setStep('preview')
    // Trigger preview for first selected device
    if (selectedDevices.length > 0) {
      const firstId = selectedDevices[0].id
      setPreviewDevice(firstId)
      if (!previews[firstId]) {
        previewMutation.mutate({ deviceId: firstId })
      }
    }
  }

  const selectPreviewDevice = (deviceId: string) => {
    setPreviewDevice(deviceId)
    if (!previews[deviceId]) {
      previewMutation.mutate({ deviceId })
    }
  }

  const handleClose = () => {
    setStep('targets')
    setSelectedDeviceIds(new Set())
    setVariables(() => {
      const defaults: Record<string, string> = {}
      for (const v of template.variables) {
        if (v.default) defaults[v.name] = v.default
      }
      return defaults
    })
    setPreviews({})
    setRolloutId(null)
    onClose()
  }

  const userVars = template.variables.filter((v) => v.name !== 'device')

  return (
    <Dialog open={open} onOpenChange={(o) => !o && handleClose()}>
      <DialogContent className="max-w-2xl max-h-[85vh] overflow-y-auto bg-surface border-border text-text-primary">
        <DialogHeader>
          <DialogTitle className="text-sm flex items-center gap-2">
            Push Template: {template.name}
            {step !== 'progress' && (
              <span className="text-[10px] text-text-muted font-normal">
                Step {['targets', 'variables', 'preview', 'confirm'].indexOf(step) + 1} of 4
              </span>
            )}
          </DialogTitle>
        </DialogHeader>

        {/* Step 1: Target Selection */}
        {step === 'targets' && (
          <div className="space-y-4">
            <div className="text-xs text-text-secondary">Select devices to push the template to.</div>

            {groups && groups.length > 0 && (
              <div className="space-y-1">
                <Label className="text-xs text-text-secondary">Select Group</Label>
                <Select onValueChange={handleGroupSelect}>
                  <SelectTrigger className="bg-elevated/50 border-border text-xs">
                    <SelectValue placeholder="Select a device group..." />
                  </SelectTrigger>
                  <SelectContent>
                    {groups.map((g) => (
                      <SelectItem key={g.id} value={g.id}>
                        {g.name}
                      </SelectItem>
                    ))}
                  </SelectContent>
                </Select>
              </div>
            )}

            <div className="space-y-1">
              <Label className="text-xs text-text-secondary">
                Devices ({selectedDeviceIds.size} selected)
              </Label>
              <div className="max-h-60 overflow-y-auto rounded-lg border border-border divide-y divide-white/5">
                {devices?.map((device) => (
                  <label
                    key={device.id}
                    className="flex items-center gap-3 px-3 py-2 hover:bg-surface cursor-pointer"
                  >
                    <Checkbox
                      checked={selectedDeviceIds.has(device.id)}
                      onCheckedChange={() => toggleDevice(device.id)}
                    />
                    <div className="flex-1 min-w-0">
                      <div className="text-xs text-text-primary truncate">{device.hostname}</div>
                      <div className="text-[10px] text-text-muted">{device.ip_address}</div>
                    </div>
                    <div
                      className={cn(
                        'h-2 w-2 rounded-full flex-shrink-0',
                        device.status === 'online' ? 'bg-success' : 'bg-error',
                      )}
                    />
                  </label>
                )) ?? (
                  <div className="px-3 py-6 text-xs text-text-muted text-center">Loading devices...</div>
                )}
              </div>
            </div>

            <div className="flex justify-end">
              <Button
                size="sm"
                className="text-xs gap-1"
                disabled={selectedDeviceIds.size === 0}
                onClick={() => setStep(userVars.length > 0 ? 'variables' : 'preview')}
              >
                Next
                <ChevronRight className="h-3 w-3" />
              </Button>
            </div>
          </div>
        )}

        {/* Step 2: Variable Input */}
        {step === 'variables' && (
          <div className="space-y-4">
            <div className="text-xs text-text-secondary">
              Provide values for template variables. Built-in device variables are auto-populated per device.
            </div>

            <div className="text-[10px] text-text-muted bg-surface rounded px-3 py-2">
              Auto-populated: {'{{ device.hostname }}'}, {'{{ device.ip }}'}, {'{{ device.model }}'}
            </div>

            <div className="space-y-3">
              {userVars.map((v) => (
                <div key={v.name} className="space-y-1">
                  <Label className="text-xs text-text-secondary">
                    {v.name}
                    {v.description && (
                      <span className="ml-2 text-text-muted">-- {v.description}</span>
                    )}
                  </Label>
                  {v.type === 'boolean' ? (
                    <div className="flex items-center gap-2">
                      <Checkbox
                        checked={variables[v.name] === 'true'}
                        onCheckedChange={(c) =>
                          setVariables((prev) => ({ ...prev, [v.name]: c ? 'true' : 'false' }))
                        }
                      />
                      <span className="text-xs text-text-secondary">{variables[v.name] ?? 'false'}</span>
                    </div>
                  ) : (
                    <Input
                      value={variables[v.name] ?? ''}
                      onChange={(e) =>
                        setVariables((prev) => ({ ...prev, [v.name]: e.target.value }))
                      }
                      placeholder={
                        v.type === 'ip'
                          ? '192.168.1.1'
                          : v.type === 'subnet'
                            ? '192.168.1.0/24'
                            : v.type === 'integer'
                              ? '0'
                              : v.default ?? ''
                      }
                      type={v.type === 'integer' ? 'number' : 'text'}
                      className="h-8 text-xs bg-elevated/50 border-border font-mono"
                    />
                  )}
                  <div className="text-[10px] text-text-muted">
                    type: {v.type}
                    {v.default && ` | default: ${v.default}`}
                  </div>
                </div>
              ))}
            </div>

            <div className="flex justify-between">
              <Button
                variant="outline"
                size="sm"
                className="text-xs gap-1"
                onClick={() => setStep('targets')}
              >
                <ChevronLeft className="h-3 w-3" />
                Back
              </Button>
              <Button size="sm" className="text-xs gap-1" onClick={goToPreview}>
                Next
                <ChevronRight className="h-3 w-3" />
              </Button>
            </div>
          </div>
        )}

        {/* Step 3: Preview */}
        {step === 'preview' && (
          <div className="space-y-4">
            <div className="text-xs text-text-secondary">
              Preview the rendered template for each device.
            </div>

            <div className="flex gap-2 flex-wrap">
              {selectedDevices.map((d) => (
                <button
                  key={d.id}
                  onClick={() => selectPreviewDevice(d.id)}
                  className={cn(
                    'text-xs px-2 py-1 rounded transition-colors',
                    previewDevice === d.id
                      ? 'bg-elevated text-text-primary'
                      : 'bg-surface text-text-secondary hover:text-text-secondary',
                  )}
                >
                  {d.hostname}
                </button>
              ))}
            </div>

            {previewDevice && previews[previewDevice] && (
              <pre className="text-xs font-mono bg-background border border-border rounded-lg p-3 text-success overflow-x-auto max-h-64 whitespace-pre-wrap">
                {previews[previewDevice]}
              </pre>
            )}

            {previewDevice && !previews[previewDevice] && previewMutation.isPending && (
              <div className="flex items-center justify-center py-8 text-text-muted">
                <Loader2 className="h-4 w-4 animate-spin mr-2" />
                Loading preview...
              </div>
            )}

            {previewMutation.isError && (
              <div className="text-xs text-error bg-error/10 rounded px-3 py-2">
                Preview failed: {previewMutation.error instanceof Error ? previewMutation.error.message : 'Unknown error'}
              </div>
            )}

            <div className="flex justify-between">
              <Button
                variant="outline"
                size="sm"
                className="text-xs gap-1"
                onClick={() => setStep(userVars.length > 0 ? 'variables' : 'targets')}
              >
                <ChevronLeft className="h-3 w-3" />
                Back
              </Button>
              <Button size="sm" className="text-xs gap-1" onClick={() => setStep('confirm')}>
                Next
                <ChevronRight className="h-3 w-3" />
              </Button>
            </div>
          </div>
        )}

        {/* Step 4: Confirm & Push */}
        {step === 'confirm' && (
          <div className="space-y-4">
            <div className="rounded-lg border border-warning/20 bg-warning/5 p-3 flex gap-2">
              <AlertTriangle className="h-4 w-4 text-warning flex-shrink-0 mt-0.5" />
              <div className="text-xs text-warning leading-relaxed">
                This will push configuration to <strong>{selectedDeviceIds.size}</strong> device(s).
                Each device will be backed up before changes are applied. If a device becomes
                unreachable after push, it will automatically revert.
              </div>
            </div>

            <div className="space-y-2">
              <div className="text-xs text-text-secondary">Template: {template.name}</div>
              <div className="text-xs text-text-secondary">
                Devices: {selectedDevices.map((d) => d.hostname).join(', ')}
              </div>
              {Object.entries(variables).length > 0 && (
                <div className="text-xs text-text-secondary">
                  Variables:{' '}
                  {Object.entries(variables)
                    .map(([k, v]) => `${k}=${v}`)
                    .join(', ')}
                </div>
              )}
            </div>

            <div className="flex justify-between">
              <Button
                variant="outline"
                size="sm"
                className="text-xs gap-1"
                onClick={() => setStep('preview')}
              >
                <ChevronLeft className="h-3 w-3" />
                Back
              </Button>
              <Button
                size="sm"
                className="text-xs gap-1"
                onClick={() => pushMutation.mutate()}
                disabled={pushMutation.isPending}
              >
                {pushMutation.isPending ? (
                  <Loader2 className="h-3 w-3 animate-spin" />
                ) : (
                  <Play className="h-3 w-3" />
                )}
                Push to {selectedDeviceIds.size} Device(s)
              </Button>
            </div>

            {pushMutation.isError && (
              <div className="text-xs text-error bg-error/10 rounded px-3 py-2">
                Push failed: {pushMutation.error instanceof Error ? pushMutation.error.message : 'Unknown error'}
              </div>
            )}
          </div>
        )}

        {/* Step 5: Progress */}
        {step === 'progress' && rolloutId && (
          <PushProgressPanel tenantId={tenantId} rolloutId={rolloutId} onClose={handleClose} />
        )}
      </DialogContent>
    </Dialog>
  )
}
