'use client'

import { useState, useCallback } from 'react'
import Link from 'next/link'
import { useFlowRun } from '@/hooks/useFlowRun'
import StreamingTerminal from '@/components/StreamingTerminal'
import ConfirmDialog from '@/components/ConfirmDialog'

type RestartMode = 'reload' | 'force'

const FLOW_KEYS: Record<RestartMode, string> = {
  reload: 'update_caddy_config',
  force: 'update_caddy_config_force',
}

const STEP_LABELS: Record<RestartMode, string[]> = {
  reload: [
    'caddy validate (syntax check)',
    'caddy reload (zero-downtime via admin API)',
    'smoke test: curl -I each hostname (expect 200/301/308/401)',
  ],
  force: [
    'caddy validate (syntax check)',
    'docker compose up --force-recreate caddy (hard restart)',
    'smoke test: curl -I each hostname (expect 200/301/308/401)',
  ],
}

function parseCaddyfileHostnames(content: string): string[] {
  const hostnames: string[] = []
  // Match top-level server block labels: hostname { or hostname:port {
  for (const match of content.matchAll(/^([a-zA-Z0-9][a-zA-Z0-9\-.:]+)\s*\{/gm)) {
    const candidate = match[1].trim()
    // Skip obvious non-hostnames like "tls", "log", "handle", etc.
    if (!candidate.includes('.') && !candidate.includes(':')) continue
    // Strip port suffix for display
    const host = candidate.split(':')[0]
    if (!hostnames.includes(host)) hostnames.push(host)
  }
  return hostnames
}

function CaddyfileDiff({ content, error }: { content: string; error: string | null }) {
  if (error) {
    return (
      <div className="rounded-lg border border-destructive/50 bg-destructive/10 p-4 text-sm text-destructive">
        Could not load Caddyfile: {error}
      </div>
    )
  }
  if (!content.trim()) {
    return (
      <div className="rounded-lg border border-border px-4 py-6 text-sm text-muted-foreground text-center">
        Caddyfile is empty or not found
      </div>
    )
  }
  return (
    <pre className="overflow-x-auto rounded-lg border border-border bg-zinc-950 p-4 text-xs font-mono text-zinc-100 leading-relaxed max-h-80">
      {content}
    </pre>
  )
}

type Props = {
  caddyfile: string
  caddyfileError: string | null
}

export default function FlowPanel({ caddyfile, caddyfileError }: Props) {
  const [mode, setMode] = useState<RestartMode>('reload')
  const [pendingDryRun, setPendingDryRun] = useState<boolean | null>(null)
  const [completedFlowRunId, setCompletedFlowRunId] = useState<string | null>(null)
  const [showConfig, setShowConfig] = useState(false)

  const handleComplete = useCallback((flowRunId: string) => {
    setCompletedFlowRunId(flowRunId)
  }, [])

  const flowRun = useFlowRun(handleComplete)

  const handleConfirm = useCallback(() => {
    if (pendingDryRun === null) return
    const dryRun = pendingDryRun
    setPendingDryRun(null)
    setCompletedFlowRunId(null)
    flowRun.startFlow(FLOW_KEYS[mode], dryRun)
  }, [pendingDryRun, flowRun, mode])

  const handleReset = useCallback(() => {
    flowRun.reset()
    setCompletedFlowRunId(null)
  }, [flowRun])

  const hostnames = parseCaddyfileHostnames(caddyfile)
  const steps = STEP_LABELS[mode]
  const flowKey = FLOW_KEYS[mode]

  return (
    <div className="space-y-6">
      {/* Description */}
      <div className="rounded-lg border border-border p-5 space-y-4">
        <div>
          <p className="text-sm text-muted-foreground">
            Validates the Caddyfile on disk, then reloads or restarts Caddy, and
            smoke-tests every public hostname. Edit the config first via the{' '}
            <Link href="/caddy/edit" className="underline hover:text-foreground transition-colors">
              Caddy editor
            </Link>
            .
          </p>
          <p className="mt-1 text-xs text-muted-foreground font-mono">
            config: /srv/scrum4me/caddy/Caddyfile
          </p>
        </div>

        {/* Restart mode toggle */}
        <div className="flex items-center gap-2">
          <span className="text-xs text-muted-foreground">Restart mode:</span>
          <button
            onClick={() => setMode('reload')}
            className={`rounded px-3 py-1 text-xs font-medium transition-colors ${
              mode === 'reload'
                ? 'bg-foreground text-background'
                : 'border border-border hover:bg-muted/50'
            }`}
          >
            Reload (zero-downtime)
          </button>
          <button
            onClick={() => setMode('force')}
            className={`rounded px-3 py-1 text-xs font-medium transition-colors ${
              mode === 'force'
                ? 'bg-foreground text-background'
                : 'border border-border hover:bg-muted/50'
            }`}
          >
            Force Restart (docker compose)
          </button>
        </div>

        {/* Step list */}
        <ol className="space-y-1">
          {steps.map((step, i) => (
            <li key={i} className="flex gap-2 text-xs font-mono text-muted-foreground">
              <span className="text-border min-w-[1.5rem]">{i + 1}.</span>
              <span>{step}</span>
            </li>
          ))}
        </ol>

        {/* Detected hostnames */}
        {hostnames.length > 0 && (
          <div className="space-y-1">
            <p className="text-xs text-muted-foreground">
              Hostnames detected in Caddyfile (will be smoke-tested):
            </p>
            <ul className="space-y-0.5">
              {hostnames.map((h) => (
                <li key={h} className="text-xs font-mono text-muted-foreground pl-4">
                  • {h}
                </li>
              ))}
            </ul>
          </div>
        )}
      </div>

      {/* Config preview (dry-run diff) */}
      <div className="space-y-2">
        <button
          onClick={() => setShowConfig((v) => !v)}
          className="text-xs text-muted-foreground hover:text-foreground transition-colors"
        >
          {showConfig ? '▾' : '▸'} {showConfig ? 'Hide' : 'Preview'} pending Caddyfile
        </button>
        {showConfig && (
          <div className="space-y-2">
            <p className="text-xs text-muted-foreground">
              This is the config that will be validated and applied:
            </p>
            <CaddyfileDiff content={caddyfile} error={caddyfileError} />
            {!caddyfileError && (
              <p className="text-xs text-muted-foreground">
                To change the config before applying,{' '}
                <Link href="/caddy/edit" className="underline hover:text-foreground">
                  edit in the Caddy editor
                </Link>{' '}
                first.
              </p>
            )}
          </div>
        )}
      </div>

      {/* Action buttons */}
      <div className="flex items-center gap-3">
        <button
          onClick={() => setPendingDryRun(false)}
          disabled={flowRun.status === 'running'}
          className="rounded-lg bg-foreground text-background px-4 py-2 text-sm font-medium hover:opacity-90 disabled:opacity-50 transition-opacity"
        >
          Run
        </button>
        <button
          onClick={() => setPendingDryRun(true)}
          disabled={flowRun.status === 'running'}
          className="rounded-lg border border-border px-4 py-2 text-sm hover:bg-muted/50 disabled:opacity-50 transition-colors"
        >
          Dry Run
        </button>
        {flowRun.status !== 'idle' && flowRun.status !== 'running' && (
          <button
            onClick={handleReset}
            className="text-xs text-muted-foreground hover:text-foreground transition-colors"
          >
            Reset
          </button>
        )}
      </div>

      {/* Terminal output */}
      {flowRun.status !== 'idle' && (
        <div className="space-y-2">
          <div className="flex items-center justify-between">
            <span className="text-sm font-medium">Output</span>
            {completedFlowRunId && (
              <Link
                href={`/audit/${completedFlowRunId}`}
                className="text-xs text-muted-foreground hover:text-foreground transition-colors"
              >
                View in audit log →
              </Link>
            )}
          </div>
          <StreamingTerminal
            lines={flowRun.lines}
            status={flowRun.status}
            error={flowRun.error}
          />
        </div>
      )}

      {/* Confirm dialog */}
      <ConfirmDialog
        open={pendingDryRun !== null}
        title={
          pendingDryRun
            ? `Dry Run: Update Caddy Config (${mode === 'reload' ? 'Reload' : 'Force Restart'})`
            : `Run: Update Caddy Config (${mode === 'reload' ? 'Reload' : 'Force Restart'})`
        }
        commandPreview={
          pendingDryRun
            ? `[DRY RUN] flow: ${flowKey}\n\nAll steps will be shown without executing.\n\nPending config: /srv/scrum4me/caddy/Caddyfile${hostnames.length > 0 ? `\nHostnames: ${hostnames.join(', ')}` : ''}`
            : `flow: ${flowKey}\n\nSteps:\n${steps.map((s, i) => `  ${i + 1}. ${s}`).join('\n')}${hostnames.length > 0 ? `\n\nHostnames to smoke-test: ${hostnames.join(', ')}` : ''}`
        }
        onConfirm={handleConfirm}
        onCancel={() => setPendingDryRun(null)}
      />
    </div>
  )
}
