'use client'

import { useState, useCallback, useEffect } from 'react'
import { Button } from '@/components/ui/button'
import { Loader } from '@/components/ui/loader'

type CheckSeverity = 'critical' | 'high' | 'medium' | 'low'
type FixSafety = 'safe' | 'requires-restart' | 'requires-review' | 'manual-only'

interface Check {
  id: string
  name: string
  status: 'pass' | 'fail' | 'warn'
  detail: string
  fix: string
  severity?: CheckSeverity
  fixSafety?: FixSafety
}

interface Category {
  score: number
  checks: Check[]
}

interface ScanResult {
  overall: 'secure' | 'hardened' | 'needs-attention' | 'at-risk'
  score: number
  timestamp: number
  categories: {
    credentials: Category
    network: Category
    openclaw: Category
    runtime: Category
    os: Category
  }
}

// Check IDs that the /api/security-scan/fix endpoint can auto-fix, with safety levels
const FIX_SAFETY: Record<string, FixSafety> = {
  env_permissions: 'safe', config_permissions: 'safe', world_writable: 'safe',
  hsts_enabled: 'requires-restart', cookie_secure: 'requires-restart',
  allowed_hosts: 'requires-restart', rate_limiting: 'requires-restart', api_key_set: 'requires-restart',
  log_redaction: 'requires-restart', dm_isolation: 'requires-restart',
  fs_workspace_only: 'requires-restart',
  exec_restricted: 'requires-review', gateway_auth: 'requires-review',
  gateway_bind: 'requires-review', elevated_disabled: 'requires-review',
  control_ui_device_auth: 'requires-review', control_ui_insecure_auth: 'requires-review',
}

const FIXABLE_IDS = new Set(Object.keys(FIX_SAFETY))

const SEVERITY_BADGE: Record<CheckSeverity, { label: string; className: string }> = {
  critical: { label: 'C', className: 'bg-red-500/20 text-red-400' },
  high: { label: 'H', className: 'bg-orange-500/20 text-orange-400' },
  medium: { label: 'M', className: 'bg-amber-500/20 text-amber-400' },
  low: { label: 'L', className: 'bg-blue-500/20 text-blue-300' },
}

const STATUS_ICON: Record<string, string> = {
  pass: '+',
  fail: 'x',
  warn: '!',
}

const STATUS_COLOR: Record<string, string> = {
  pass: 'text-green-400',
  fail: 'text-red-400',
  warn: 'text-amber-400',
}

const OVERALL_COLOR: Record<string, string> = {
  hardened: 'text-green-400',
  secure: 'text-green-300',
  'needs-attention': 'text-amber-400',
  'at-risk': 'text-red-400',
}

const CATEGORY_LABELS: Record<string, { label: string; icon: string }> = {
  credentials: { label: 'Credentials', icon: 'K' },
  network: { label: 'Network', icon: 'N' },
  openclaw: { label: 'OpenClaw', icon: 'O' },
  runtime: { label: 'Runtime', icon: 'R' },
  os: { label: 'OS Security', icon: 'S' },
}

export function SecurityScanCard({ compact = false, autoScan = false }: { compact?: boolean; autoScan?: boolean }) {
  const [result, setResult] = useState<ScanResult | null>(null)
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState<string | null>(null)
  const [expandedCategory, setExpandedCategory] = useState<string | null>(null)
  const [copiedFix, setCopiedFix] = useState<string | null>(null)
  const [fixing, setFixing] = useState<string | null>(null) // 'all' or a check id
  const [fixResult, setFixResult] = useState<{
    attempted: number
    fixed: number
    failed: number
    remaining: number
    remainingAutoFixable: number
    remainingManual: number
    note?: string
  } | null>(null)

  const copyFix = useCallback(async (fix: string, checkId: string) => {
    try {
      await navigator.clipboard.writeText(fix)
      setCopiedFix(checkId)
      setTimeout(() => setCopiedFix(null), 2000)
    } catch {
      // Fallback
      const el = document.createElement('textarea')
      el.value = fix
      document.body.appendChild(el)
      el.select()
      document.execCommand('copy')
      document.body.removeChild(el)
      setCopiedFix(checkId)
      setTimeout(() => setCopiedFix(null), 2000)
    }
  }, [])

  const runScan = useCallback(async () => {
    setLoading(true)
    setError(null)
    setFixResult(null)
    try {
      const res = await fetch('/api/security-scan')
      if (!res.ok) {
        setError(res.status === 401 ? 'Admin access required' : 'Scan failed')
        return
      }
      setResult(await res.json())
    } catch {
      setError('Failed to connect')
    } finally {
      setLoading(false)
    }
  }, [])

  const runFix = useCallback(async (ids?: string[]) => {
    const fixKey = ids?.length === 1 ? ids[0] : 'all'
    setFixing(fixKey)
    setFixResult(null)
    try {
      const res = await fetch('/api/security-scan/fix', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: ids ? JSON.stringify({ ids }) : '{}',
      })
      if (!res.ok) {
        setFixResult({ attempted: 0, fixed: 0, failed: 1, remaining: 0, remainingAutoFixable: 0, remainingManual: 0, note: res.status === 401 ? 'Admin access required' : 'Fix failed' })
        return
      }
      const data = await res.json()
      setFixResult({
        attempted: data.attempted ?? data.fixed + data.failed,
        fixed: data.fixed ?? 0,
        failed: data.failed ?? 0,
        remaining: data.remaining ?? 0,
        remainingAutoFixable: data.remainingAutoFixable ?? 0,
        remainingManual: data.remainingManual ?? 0,
        note: data.note,
      })
      // Re-scan after fixes
      setTimeout(() => runScan(), 1500)
    } catch {
      setFixResult({ attempted: 0, fixed: 0, failed: 1, remaining: 0, remainingAutoFixable: 0, remainingManual: 0, note: 'Network error' })
    } finally {
      setTimeout(() => setFixing(null), 1500)
    }
  }, [runScan])

  useEffect(() => {
    if (autoScan && !result && !loading && !error) {
      runScan()
    }
  }, [autoScan, result, loading, error, runScan])

  if (!result && !loading && !error) {
    return (
      <div className="flex flex-col items-center gap-4 py-6">
        <div className="text-center">
          <p className="text-sm text-muted-foreground mb-1">Run a comprehensive security scan of your installation</p>
          <p className="text-xs text-muted-foreground/60">Checks credentials, network config, OpenClaw hardening, and runtime security</p>
        </div>
        <Button onClick={runScan} variant="outline" size="sm" className="border-void-cyan/30 text-void-cyan hover:bg-void-cyan/10">
          Run Security Scan
        </Button>
      </div>
    )
  }

  if (loading) {
    return (
      <div className="flex items-center justify-center py-8">
        <Loader variant="inline" label="Scanning..." />
      </div>
    )
  }

  if (error) {
    return (
      <div className="flex flex-col items-center gap-3 py-6">
        <p className="text-sm text-red-400">{error}</p>
        <Button onClick={runScan} variant="outline" size="sm">Retry</Button>
      </div>
    )
  }

  if (!result) return null

  const failingChecks = Object.values(result.categories).flatMap((cat) => cat.checks.filter((check) => check.status !== 'pass'))
  const autoFixableChecks = failingChecks.filter((check) => FIXABLE_IDS.has(check.id))
  const manualChecks = failingChecks.filter((check) => !FIXABLE_IDS.has(check.id))

  return (
    <div className="space-y-4">
      {/* Score header */}
      <div className="flex items-center justify-between">
        <div className="flex items-center gap-3">
          <div className={`text-3xl font-bold tabular-nums ${OVERALL_COLOR[result.overall]}`}>
            {result.score}
          </div>
          <div>
            <div className={`text-sm font-medium capitalize ${OVERALL_COLOR[result.overall]}`}>
              {result.overall.replace('-', ' ')}
            </div>
            <div className="text-xs text-muted-foreground">Security score</div>
          </div>
        </div>
        <Button onClick={runScan} variant="ghost" size="sm" className="text-xs text-muted-foreground hover:text-foreground">
          Re-scan
        </Button>
      </div>

      {/* Score bar */}
      <div className="h-1.5 rounded-full bg-surface-2 overflow-hidden">
        <div
          className={`h-full rounded-full transition-all duration-700 ${
            result.score >= 90 ? 'bg-green-400' :
            result.score >= 70 ? 'bg-green-300' :
            result.score >= 40 ? 'bg-amber-400' : 'bg-red-400'
          }`}
          style={{ width: `${result.score}%` }}
        />
      </div>

      {/* Issue summary + Fix All */}
      {(() => {
        const totalFailing = failingChecks.length
        return totalFailing > 0 ? (
          <div className="flex items-center justify-between gap-2">
            <div className="text-xs text-muted-foreground">
              <p>{totalFailing} issue{totalFailing > 1 ? 's' : ''} found</p>
              <p>{autoFixableChecks.length} auto-fixable, {manualChecks.length} manual/review</p>
            </div>
            <Button
              onClick={() => runFix()}
              disabled={fixing !== null || autoFixableChecks.length === 0}
              variant="outline"
              size="sm"
              className="text-xs border-void-cyan/30 text-void-cyan hover:bg-void-cyan/10"
            >
              {fixing === 'all' ? 'Fixing...' : 'Fix Auto-Fixable'}
            </Button>
          </div>
        ) : null
      })()}

      {/* Fix result feedback */}
      {fixResult && (
        <div className={`text-xs px-3 py-2 rounded-lg border ${fixResult.failed > 0 ? 'bg-amber-500/10 border-amber-500/20 text-amber-300' : 'bg-green-500/10 border-green-500/20 text-green-300'}`}>
          {fixResult.attempted > 0 && <span>{fixResult.attempted} auto-fix attempt{fixResult.attempted > 1 ? 's' : ''}. </span>}
          {fixResult.fixed > 0 && <span>{fixResult.fixed} issue{fixResult.fixed > 1 ? 's' : ''} fixed. </span>}
          {fixResult.failed > 0 && <span>{fixResult.failed} failed. </span>}
          {fixResult.remaining > 0 && <span>{fixResult.remaining} issue{fixResult.remaining > 1 ? 's' : ''} remain. </span>}
          {fixResult.remainingManual > 0 && <span>{fixResult.remainingManual} still need manual action or review. </span>}
          {fixResult.note && <span className="text-muted-foreground">{fixResult.note}</span>}
        </div>
      )}

      {/* Categories */}
      <div className="space-y-2">
        {Object.entries(result.categories).map(([key, cat]) => {
          const meta = CATEGORY_LABELS[key]
          const isExpanded = expandedCategory === key
          const failing = cat.checks.filter(c => c.status !== 'pass')

          return (
            <div key={key} className="border border-border/50 rounded-lg overflow-hidden">
              <button
                onClick={() => setExpandedCategory(isExpanded ? null : key)}
                className="w-full flex items-center gap-3 px-3 py-2.5 text-left hover:bg-surface-1/50 transition-colors"
              >
                <span className="w-5 h-5 rounded bg-surface-2 flex items-center justify-center text-xs font-mono text-muted-foreground">
                  {meta?.icon || key[0].toUpperCase()}
                </span>
                <span className="flex-1 text-sm font-medium">{meta?.label || key}</span>
                <span className={`text-xs tabular-nums ${cat.score >= 80 ? 'text-green-400' : cat.score >= 50 ? 'text-amber-400' : 'text-red-400'}`}>
                  {cat.score}%
                </span>
                {failing.length > 0 && (
                  <span className="text-xs text-muted-foreground">
                    {failing.length} issue{failing.length > 1 ? 's' : ''}
                  </span>
                )}
                <span className="text-xs text-muted-foreground/50">{isExpanded ? '-' : '+'}</span>
              </button>

              {isExpanded && (
                <div className="border-t border-border/30 px-3 py-2 space-y-1.5 bg-surface-1/30">
                  {cat.checks.map(check => (
                    <div key={check.id} className="flex items-start gap-2 py-1">
                      <span className={`font-mono text-xs mt-0.5 w-4 shrink-0 ${STATUS_COLOR[check.status]}`}>
                        [{STATUS_ICON[check.status]}]
                      </span>
                      <div className="flex-1 min-w-0">
                        <div className="flex items-center gap-2">
                          <span className="text-sm">{check.name}</span>
                          {check.severity && (
                            <span className={`text-2xs px-1 py-0.5 rounded font-mono leading-none ${SEVERITY_BADGE[check.severity].className}`}>
                              {SEVERITY_BADGE[check.severity].label}
                            </span>
                          )}
                        </div>
                        <p className="text-xs text-muted-foreground">{check.detail}</p>
                        {check.fix && check.status !== 'pass' && (
                          <div className="flex items-center gap-1.5 mt-0.5">
                            <p className="text-xs text-void-cyan/70 flex-1 min-w-0">Fix: {check.fix}</p>
                            {FIXABLE_IDS.has(check.id) && (
                              <button
                                onClick={(e) => { e.stopPropagation(); runFix([check.id]) }}
                                disabled={fixing !== null}
                                className="shrink-0 px-1.5 py-0.5 text-2xs rounded border border-void-cyan/30 text-void-cyan hover:bg-void-cyan/10 transition-colors disabled:opacity-50"
                                title={FIX_SAFETY[check.id] === 'requires-review' ? 'Requires review — may affect running services' : FIX_SAFETY[check.id] === 'requires-restart' ? 'Requires restart to take effect' : 'Auto-fix this issue'}
                              >
                                {fixing === check.id ? 'Fixing...' : FIX_SAFETY[check.id] === 'requires-review' ? 'Fix *' : 'Fix'}
                              </button>
                            )}
                            <button
                              onClick={(e) => { e.stopPropagation(); copyFix(check.fix, check.id) }}
                              className="shrink-0 px-1.5 py-0.5 text-2xs rounded border border-border/50 text-muted-foreground hover:text-foreground hover:border-border transition-colors"
                              title="Copy fix command"
                            >
                              {copiedFix === check.id ? 'Copied' : 'Copy'}
                            </button>
                          </div>
                        )}
                      </div>
                    </div>
                  ))}
                </div>
              )}
            </div>
          )
        })}
      </div>
    </div>
  )
}
