'use client'

/**
 * SloTab — SLO 儀表 Tab
 * ======================
 * 消費：GET /api/v1/ai/slo + GET /api/v1/ai/governance/summary?days=30
 *
 * 內容：
 *   1. 三 KPI 卡片（水平排列，mobile 堆疊）
 *   2. 30d 違反次數時序圖（Recharts BarChart stacked）
 *   3. 整體合規率副資訊
 *
 * @updated 2026-05-02 Claude Sonnet 4.6 — governance PR 3-5 填入真實內容
 */

import { useEffect, useState } from 'react'
import { useTranslations } from 'next-intl'
import { ShieldCheck, AlertTriangle, PlayCircle, SearchCheck, CheckCircle2, Clock3, Wrench } from 'lucide-react'
import { SloKpiCard, type SloMetric } from '@/components/governance/slo-kpi-card'
import { SloViolationChart, type ViolationDataPoint } from '@/components/governance/slo-violation-chart'
import { GlassCard } from '@/components/ui/glass-card'

// =============================================================================
// Config
// =============================================================================

const API_BASE = process.env.NEXT_PUBLIC_API_URL ?? ''

// =============================================================================
// Types
// =============================================================================

interface SloApiResponse {
  metrics?: Array<{
    name: SloMetric['name']
    value: number | null
    threshold: number
    direction: 'above' | 'below'
    sample_count: number
    violated: boolean
  }> | {
    decision_accuracy?: { current: number; target: number; status: string; sparkline?: number[] }
    km_growth_rate?:    { current: number; target: number; status: string; sparkline?: number[] }
    mcp_call_diversity?: { current: number; target: number; status: string; sparkline?: number[] }
  }
  adr100?: {
    overall_status?: string
    overall_compliance?: number | null
    verification_coverage?: Adr100VerificationCoverage
    metrics?: Array<{
      name: SloMetric['name']
      value: number | null
      target: number
      status: 'ok' | 'warning' | 'violated' | 'skipped_low_volume' | 'no_data' | 'error'
      unit: 'percent' | 'count'
      sample_count?: number | null
      window?: string
      reason?: string | null
    }>
  }
  overall_compliance?: number
  computed_at?: string
  diagnostics?: {
    auto_execute_success_rate?: AutoExecuteDiagnostics
  }
}

interface AutoExecuteDiagnostics {
  schema_version?: string
  status?: string
  summary?: {
    total?: number
    success?: number
    failed?: number
    rate?: number | null
    threshold?: number
    window_days?: number
    min_samples?: number
  }
  top_failure_groups?: AutoExecuteFailureGroup[]
  sealed_failure_group_count?: number
  open_failure_group_count?: number
  immediate_successes_needed?: number
  projected_green_at?: string | null
  projection_reason?: string | null
  next_action?: string | null
}

interface AutoExecuteFailureGroup {
  alertname?: string | null
  playbook_id?: string | null
  playbook_name?: string | null
  count?: number
  closure_status?: string | null
  closure_label?: string | null
  recommended_action?: string | null
  first_seen?: string | null
  last_seen?: string | null
}

interface Adr100VerificationCoverage {
  status: 'ok' | 'warning' | 'violated' | 'skipped_low_volume' | 'no_data' | 'error'
  reason?: string | null
  window?: string
  total_auto: number
  successful_auto: number
  verified_auto: number
  verified_success: number
  verified_non_success: number
  unverified_auto: number
  coverage_rate?: number | null
  verification_success_rate?: number | null
  last_auto_at?: string | null
  last_verified_auto_at?: string | null
  latest_auto_age_seconds?: number | null
  last_verified_auto_age_seconds?: number | null
  recent_unverified?: Array<{
    id: string
    incident_id: string
    success: boolean
    created_at?: string | null
  }>
  recent_non_success?: Array<{
    auto_repair_id: string
    incident_id: string
    incident_status: string
    incident_severity: string
    alert_category?: string | null
    alertname?: string | null
    auto_success: boolean
    playbook_id?: string | null
    playbook_name?: string | null
    triggered_by?: string | null
    risk_level?: string | null
    verification_result: string
    failure_class: string
    next_step: string
    remediation_status?: string | null
    remediation_action?: string | null
    remediation_owner?: string | null
    remediation_reason?: string | null
    auto_error_excerpt?: string | null
    evidence_excerpt?: string | null
    auto_created_at?: string | null
    verification_collected_at?: string | null
  }>
  non_success_breakdown?: {
    by_verification_result?: Array<{ name: string; count: number }>
    by_failure_class?: Array<{ name: string; count: number }>
    by_remediation_status?: Array<{ name: string; count: number }>
  }
  remediation_queue?: {
    total: number
    ready_for_ai: number
    needs_human: number
    items?: Array<{
      work_item_id: string
      incident_id?: string | null
      auto_repair_id?: string | null
      alertname?: string | null
      playbook_id?: string | null
      failure_class?: string | null
      verification_result?: string | null
      remediation_status?: string | null
      remediation_action?: string | null
      remediation_owner?: string | null
      remediation_reason?: string | null
      source?: string | null
      auto_created_at?: string | null
      verification_collected_at?: string | null
    }>
    by_status?: Array<{ name: string; count: number }>
    by_action?: Array<{ name: string; count: number }>
  }
}

interface SummaryApiResponse {
  data?: ViolationDataPoint[]
  event_types?: string[]
  days?: number
}

interface RemediationDryRunResponse {
  mode?: string
  allowed?: boolean
  executed?: boolean
  verification_result_preview?: string
  post_state_summary?: {
    tool_count?: number
    tools?: string[]
    has_state?: boolean
  }
  mcp_route?: {
    agent_id?: string
    tool_name?: string
    required_scope?: string
  } | null
  history?: {
    recorded?: boolean
  }
}

interface RemediationHistoryWorkItemSummary {
  work_item_id?: string | null
  incident_id?: string | null
  count: number
  latest_at?: string | null
  latest_preview?: string | null
  latest_mode?: string | null
  latest_agent_id?: string | null
  latest_tool_name?: string | null
  required_scope?: string | null
}

interface RemediationHistoryResponse {
  schema_version?: string
  total?: number
  by_work_item?: RemediationHistoryWorkItemSummary[]
}

interface RemediationActionState {
  status: 'loading' | 'done' | 'error'
  data?: RemediationDryRunResponse
}

// =============================================================================
// Helpers
// =============================================================================

function mapStatus(s: string): SloMetric['status'] {
  if (s === 'healthy' || s === 'ok') return 'healthy'
  if (s === 'warning') return 'warning'
  if (s === 'skipped_low_volume') return 'syncing'
  if (s === 'no_data') return 'idle'
  return 'critical'
}

function coverageTone(status?: Adr100VerificationCoverage['status']): string {
  if (status === 'ok') return '#22C55E'
  if (status === 'warning') return '#F59E0B'
  if (!status || status === 'skipped_low_volume' || status === 'no_data') return '#87867f'
  return '#FF3300'
}

function coverageReasonKey(reason?: string | null): string {
  if (reason === 'no_auto_repair_executions_24h') return reason
  if (reason === 'verification_backlog_present') return reason
  if (reason === 'non_success_verification_present') return reason
  if (reason === 'postgresql_query_error') return reason
  return 'none'
}

function formatPercent(value?: number | null): string {
  return value == null ? '--' : `${(value * 100).toFixed(1)}%`
}

function autoExecuteStatusKey(value?: string | null): string {
  if (value === 'green') return value
  if (value === 'sealed_waiting_window') return value
  if (value === 'needs_investigation') return value
  if (value === 'insufficient_diagnostics') return value
  if (value === 'diagnostics_unavailable') return value
  return 'unknown'
}

function autoExecuteNextActionKey(value?: string | null): string {
  if (value === 'keep_monitoring') return value
  if (value === 'observe_rolling_window_no_manual_restart') return value
  if (value === 'investigate_open_failure_groups') return value
  if (value === 'refresh_truth_chain_and_execution_logs') return value
  return 'refresh_truth_chain_and_execution_logs'
}

function closureStatusKey(value?: string | null): string {
  if (value === 'sealed_by_mcp_grant') return value
  if (value === 'sealed_by_external_site_guard') return value
  if (value === 'open_failure_source') return value
  return 'unknown'
}

function diagnosticTone(status?: string | null, openGroups = 0): string {
  if (openGroups > 0 || status === 'needs_investigation') return '#FF3300'
  if (status === 'green') return '#22C55E'
  if (status === 'sealed_waiting_window' && openGroups === 0) return '#0EA5E9'
  if (status === 'diagnostics_unavailable') return '#87867f'
  return '#F59E0B'
}

function failureClassKey(value?: string | null): string {
  if (value === 'unsupported_action_scheme') return value
  if (value === 'verifier_missing_promql') return value
  if (value === 'verifier_target_missing_pod') return value
  if (value === 'auto_repair_execution_failed') return value
  if (value === 'verification_failed') return value
  if (value === 'verification_timeout') return value
  if (value === 'verification_degraded') return value
  return 'unknown'
}

function nextStepKey(value?: string | null): string {
  if (value === 'normalize_playbook_executor') return value
  if (value === 'add_verifier_query_template') return value
  if (value === 'map_verifier_target') return value
  if (value === 'review_auto_repair_execution') return value
  if (value === 'escalate_verification_failure') return value
  if (value === 'review_degraded_verification') return value
  return 'review_degraded_verification'
}

function remediationStatusKey(value?: string | null): string {
  if (value === 'ready_for_replay') return value
  if (value === 'ready_for_reverify') return value
  if (value === 'needs_target_mapping') return value
  if (value === 'needs_playbook_ticket') return value
  if (value === 'manual_review') return value
  return 'unknown'
}

function remediationActionKey(value?: string | null): string {
  if (value === 'replay_with_supported_executor') return value
  if (value === 'reverify_with_promql_template') return value
  if (value === 'map_target_and_reverify') return value
  if (value === 'create_playbook_ticket') return value
  if (value === 'escalate_verification_failure') return value
  if (value === 'inspect_degraded_evidence') return value
  return 'inspect_degraded_evidence'
}

function compactLabel(value?: string | null, fallback = '--'): string {
  if (!value) return fallback
  return value.length > 54 ? `${value.slice(0, 54)}...` : value
}

async function requestRemediationDryRun(workItemId: string): Promise<RemediationDryRunResponse> {
  const response = await fetch(`${API_BASE}/api/v1/ai/slo/remediation/dry-run`, {
    method: 'POST',
    headers: { 'content-type': 'application/json' },
    body: JSON.stringify({ work_item_id: workItemId, mode: 'auto' }),
  })
  if (!response.ok) throw new Error(`dry_run_failed:${response.status}`)
  return response.json()
}

async function requestRemediationHistory(): Promise<RemediationHistoryResponse> {
  const params = new URLSearchParams({ limit: '80' })
  const response = await fetch(`${API_BASE}/api/v1/ai/slo/remediation/history?${params}`)
  if (!response.ok) throw new Error(`history_failed:${response.status}`)
  return response.json()
}

function formatShortDateTime(value?: string | null): string {
  if (!value) return '--'
  const date = new Date(value)
  if (Number.isNaN(date.getTime())) return value
  return date.toLocaleString(undefined, {
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit',
  })
}

function formatShortDate(value?: string | null): string {
  if (!value) return '--'
  const date = new Date(value)
  if (Number.isNaN(date.getTime())) return '--'
  const pad = (input: number) => String(input).padStart(2, '0')
  return `${pad(date.getMonth() + 1)}/${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}`
}

function historyRouteLabel(summary: RemediationHistoryWorkItemSummary): string {
  return compactLabel(
    [summary.latest_agent_id, summary.latest_tool_name]
      .filter(Boolean)
      .join('/') || summary.required_scope || '--',
    '--',
  )
}

function buildMetrics(api: SloApiResponse): SloMetric[] {
  const adr100Metrics = api.adr100?.metrics
  if (adr100Metrics?.length) {
    const order: SloMetric['name'][] = ['autonomy_rate', 'decision_accuracy', 'confidence_calibration', 'km_growth_rate']
    const byName = new Map(adr100Metrics.map(metric => [metric.name, metric]))
    const built: SloMetric[] = []
    order.forEach(name => {
      const entry = byName.get(name)
      if (!entry) return
      built.push({
        name,
        current: entry.value ?? null,
        target: entry.target,
        status: mapStatus(entry.status),
        state: entry.status,
        unit: entry.unit === 'count' ? 'count' : '%',
        sparkline: [],
        sampleCount: entry.sample_count ?? null,
        window: entry.window,
        reason: entry.reason ?? null,
      })
    })
    return built
  }

  if (Array.isArray(api.metrics)) {
    return api.metrics.map(entry => ({
      name: entry.name,
      current: entry.value,
      target: entry.threshold,
      status: entry.value == null ? 'syncing' : entry.violated ? 'critical' : 'healthy',
      state: entry.value == null ? 'skipped_low_volume' : entry.violated ? 'violated' : 'ok',
      unit: '%',
      sparkline: [],
      sampleCount: entry.sample_count,
    }))
  }

  const m = api.metrics ?? {}
  if (Array.isArray(m)) return []
  const names: Array<'decision_accuracy' | 'km_growth_rate' | 'mcp_call_diversity'> = ['decision_accuracy', 'km_growth_rate', 'mcp_call_diversity']
  return names.map((name): SloMetric => {
    const entry = m[name]
    return {
      name,
      current: entry?.current ?? null,
      target: entry?.target ?? 0.9,
      status: mapStatus(entry?.status ?? 'warning'),
      unit: '%',
      sparkline: entry?.sparkline ?? [],
    }
  })
}

function AutoExecuteDiagnosticsPanel({ diagnostics }: { diagnostics?: AutoExecuteDiagnostics }) {
  const t = useTranslations('governance.slo.autoExecute')
  const summary = diagnostics?.summary
  if (!summary) return null

  const rate = summary.rate ?? null
  const threshold = summary.threshold ?? 0.85
  const total = summary.total ?? 0
  const success = summary.success ?? 0
  const failed = summary.failed ?? Math.max(total - success, 0)
  const sealedGroups = diagnostics?.sealed_failure_group_count ?? 0
  const openGroups = diagnostics?.open_failure_group_count ?? 0
  const tone = diagnosticTone(diagnostics?.status, openGroups)
  const progress = Math.max(0, Math.min(100, (rate ?? 0) * 100))
  const thresholdPosition = Math.max(0, Math.min(100, threshold * 100))
  const groups = diagnostics?.top_failure_groups ?? []
  const statusKey = autoExecuteStatusKey(diagnostics?.status)
  const nextActionKey = autoExecuteNextActionKey(diagnostics?.next_action)
  const projectedAt = formatShortDate(diagnostics?.projected_green_at)
  const rateLabel = rate == null ? '--' : `${(rate * 100).toFixed(1)}%`
  const thresholdLabel = `${(threshold * 100).toFixed(0)}%`
  const observationOnly = diagnostics?.status === 'sealed_waiting_window' && openGroups === 0

  const statItems = [
    { key: 'successRate', icon: CheckCircle2, value: rateLabel, detail: t('stat.successRateDetail', { success, total }) },
    { key: 'sealedGroups', icon: Wrench, value: String(sealedGroups), detail: t('stat.sealedGroupsDetail') },
    { key: 'openGroups', icon: AlertTriangle, value: String(openGroups), detail: t('stat.openGroupsDetail') },
    {
      key: 'greenAt',
      icon: Clock3,
      value: projectedAt,
      detail: diagnostics?.immediate_successes_needed
        ? t('stat.greenAtDetailWithNeed', { count: diagnostics.immediate_successes_needed })
        : t('stat.greenAtDetail'),
    },
  ]

  return (
    <GlassCard variant="subtle" padding="md">
      <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
        <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 12 }}>
          <div style={{ minWidth: 0 }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
              <AlertTriangle size={15} style={{ color: tone, flexShrink: 0 }} />
              <div style={{ fontFamily: 'Syne, sans-serif', fontSize: 13, fontWeight: 700, color: '#141413' }}>
                {t('title')}
              </div>
            </div>
            <div style={{ marginTop: 5, fontFamily: "'DM Mono', monospace", fontSize: 10, color: '#87867f', lineHeight: 1.45 }}>
              {t('subtitle', { window: summary.window_days ?? 7 })}
            </div>
          </div>
          <div style={{
            flexShrink: 0,
            minHeight: 26,
            display: 'inline-flex',
            alignItems: 'center',
            padding: '4px 8px',
            borderRadius: 6,
            border: `0.5px solid ${tone}40`,
            background: `${tone}12`,
            fontFamily: "'DM Mono', monospace",
            fontSize: 10,
            color: tone,
          }}>
            {t(`status.${statusKey}`)}
          </div>
        </div>

        {observationOnly && (
          <div style={{
            display: 'grid',
            gridTemplateColumns: 'auto minmax(0, 1fr)',
            gap: 10,
            alignItems: 'center',
            padding: '10px 11px',
            borderRadius: 6,
            border: `0.5px solid ${tone}40`,
            background: `${tone}10`,
          }}>
            <ShieldCheck size={16} style={{ color: tone, flexShrink: 0 }} />
            <div style={{ minWidth: 0 }}>
              <div style={{ fontFamily: 'Syne, sans-serif', fontSize: 12, fontWeight: 700, color: '#141413' }}>
                {t('observation.title')}
              </div>
              <div style={{ marginTop: 3, fontFamily: "'DM Mono', monospace", fontSize: 10, color: '#4b5563', lineHeight: 1.45 }}>
                {t('observation.detail', { greenAt: projectedAt || t('observation.greenAtFallback') })}
              </div>
            </div>
          </div>
        )}

        <div style={{ display: 'grid', gridTemplateColumns: 'minmax(220px, 1.1fr) minmax(260px, 1.8fr)', gap: 14 }} className="slo-auto-diagnostics-grid">
          <div style={{ minWidth: 0 }}>
            <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', gap: 10, marginBottom: 8 }}>
              <div style={{ fontFamily: 'Syne, sans-serif', fontSize: 30, fontWeight: 700, color: tone, letterSpacing: 0, lineHeight: 1 }}>
                {rateLabel}
              </div>
              <div style={{ fontFamily: "'DM Mono', monospace", fontSize: 10, color: '#87867f' }}>
                {t('threshold', { target: thresholdLabel })}
              </div>
            </div>
            <div style={{
              position: 'relative',
              height: 10,
              borderRadius: 5,
              background: 'rgba(20,20,19,0.08)',
              overflow: 'hidden',
            }}>
              <div style={{ width: `${progress}%`, height: '100%', background: tone, borderRadius: 5 }} />
              <div style={{
                position: 'absolute',
                left: `${thresholdPosition}%`,
                top: 0,
                bottom: 0,
                width: 2,
                background: '#141413',
                opacity: 0.45,
              }} />
            </div>
            <div style={{ marginTop: 7, fontFamily: "'DM Mono', monospace", fontSize: 10, color: '#87867f', lineHeight: 1.45 }}>
              {t('windowSummary', { success, failed, total })}
            </div>
          </div>

          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, minmax(0, 1fr))', gap: 8 }} className="slo-auto-stat-grid">
            {statItems.map(item => {
              const Icon = item.icon
              return (
                <div key={item.key} style={{
                  minWidth: 0,
                  padding: '8px 9px',
                  borderRadius: 6,
                  border: '0.5px solid rgba(20,20,19,0.08)',
                  background: 'rgba(255,255,255,0.58)',
                }}>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 5 }}>
                    <Icon size={13} style={{ color: item.key === 'openGroups' && openGroups > 0 ? '#FF3300' : tone, flexShrink: 0 }} />
                    <div style={{ fontFamily: "'DM Mono', monospace", fontSize: 9, color: '#87867f' }}>
                      {t(`stat.${item.key}`)}
                    </div>
                  </div>
                  <div style={{ fontFamily: 'Syne, sans-serif', fontSize: 18, fontWeight: 700, color: '#141413', letterSpacing: 0 }}>
                    {item.value}
                  </div>
                  <div style={{ marginTop: 2, fontFamily: "'DM Mono', monospace", fontSize: 9, color: '#87867f', lineHeight: 1.35 }}>
                    {item.detail}
                  </div>
                </div>
              )
            })}
          </div>
        </div>

        {groups.length > 0 && (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
            <div style={{ fontFamily: 'Syne, sans-serif', fontSize: 11, fontWeight: 700, color: '#141413' }}>
              {t('groupsTitle')}
            </div>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 7 }}>
              {groups.slice(0, 5).map(group => {
                const closureKey = closureStatusKey(group.closure_status)
                const closureTone = closureKey === 'open_failure_source' ? '#FF3300' : '#22C55E'
                return (
                  <div key={`${group.alertname}-${group.playbook_id}-${closureKey}`} style={{
                    display: 'grid',
                    gridTemplateColumns: 'minmax(130px, 0.75fr) minmax(180px, 1fr) minmax(150px, 0.8fr) minmax(150px, 1fr)',
                    gap: 10,
                    alignItems: 'center',
                    minWidth: 0,
                    padding: '7px 0',
                    borderTop: '0.5px solid rgba(20,20,19,0.08)',
                  }} className="slo-auto-group-row">
                    <div style={{ minWidth: 0 }}>
                      <div style={{ fontFamily: "'DM Mono', monospace", fontSize: 10, color: '#141413', overflowWrap: 'anywhere' }}>
                        {compactLabel(group.alertname)}
                      </div>
                      <div style={{ fontFamily: "'DM Mono', monospace", fontSize: 9, color: '#87867f', marginTop: 2 }}>
                        {t('groupCount', { count: group.count ?? 0 })}
                      </div>
                    </div>
                    <div style={{ minWidth: 0 }}>
                      <div style={{ fontFamily: "'DM Mono', monospace", fontSize: 10, color: '#141413', overflowWrap: 'anywhere' }}>
                        {compactLabel(group.playbook_id)}
                      </div>
                      <div style={{ fontFamily: "'DM Mono', monospace", fontSize: 9, color: '#87867f', marginTop: 2, overflowWrap: 'anywhere' }}>
                        {compactLabel(group.playbook_name)}
                      </div>
                    </div>
                    <div style={{
                      width: 'fit-content',
                      minHeight: 24,
                      display: 'inline-flex',
                      alignItems: 'center',
                      padding: '3px 7px',
                      borderRadius: 6,
                      border: `0.5px solid ${closureTone}40`,
                      background: `${closureTone}12`,
                      fontFamily: "'DM Mono', monospace",
                      fontSize: 9,
                      color: closureTone,
                    }}>
                      {t(`closure.${closureKey}`)}
                    </div>
                    <div style={{ minWidth: 0, fontFamily: "'DM Mono', monospace", fontSize: 9, color: '#87867f', lineHeight: 1.4, overflowWrap: 'anywhere' }}>
                      {group.recommended_action || group.closure_label || '--'}
                    </div>
                  </div>
                )
              })}
            </div>
          </div>
        )}

        <div style={{ display: 'flex', alignItems: 'center', gap: 7, fontFamily: "'DM Mono', monospace", fontSize: 10, color: '#4b5563', lineHeight: 1.45 }}>
          <SearchCheck size={13} style={{ color: tone, flexShrink: 0 }} />
          <span>{t(`nextAction.${nextActionKey}`)}</span>
        </div>
      </div>
    </GlassCard>
  )
}

function VerificationCoveragePanel({ coverage }: { coverage?: Adr100VerificationCoverage }) {
  const t = useTranslations('governance.slo.coverage')
  const [actionState, setActionState] = useState<Record<string, RemediationActionState>>({})
  const [remediationHistory, setRemediationHistory] = useState<RemediationHistoryResponse | null>(null)
  const color = coverageTone(coverage?.status)
  const rows = [
    { label: t('totalAuto'), value: String(coverage?.total_auto ?? '--') },
    { label: t('verifiedAuto'), value: String(coverage?.verified_auto ?? '--') },
    { label: t('unverifiedAuto'), value: String(coverage?.unverified_auto ?? '--') },
    { label: t('coverageRate'), value: formatPercent(coverage?.coverage_rate) },
  ]
  const failureBreakdown = coverage?.non_success_breakdown?.by_failure_class ?? []
  const recentFindings = coverage?.recent_non_success ?? []
  const remediationQueue = coverage?.remediation_queue
  const remediationQueueTotal = remediationQueue?.total ?? 0
  const historyByWorkItem = new Map(
    (remediationHistory?.by_work_item ?? [])
      .filter(item => item.work_item_id)
      .map(item => [item.work_item_id as string, item]),
  )

  useEffect(() => {
    let cancelled = false
    if (remediationQueueTotal === 0) {
      setRemediationHistory(null)
      return () => { cancelled = true }
    }
    requestRemediationHistory()
      .then(data => {
        if (!cancelled) setRemediationHistory(data)
      })
      .catch(() => {
        if (!cancelled) setRemediationHistory(null)
      })
    return () => { cancelled = true }
  }, [remediationQueueTotal])

  const handleDryRun = async (workItemId: string) => {
    setActionState(prev => ({
      ...prev,
      [workItemId]: { status: 'loading' },
    }))
    try {
      const data = await requestRemediationDryRun(workItemId)
      setActionState(prev => ({
        ...prev,
        [workItemId]: { status: 'done', data },
      }))
      requestRemediationHistory()
        .then(setRemediationHistory)
        .catch(() => undefined)
    } catch {
      setActionState(prev => ({
        ...prev,
        [workItemId]: { status: 'error' },
      }))
    }
  }

  return (
    <GlassCard variant="subtle" padding="md">
      <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
        <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 12 }}>
          <div style={{ minWidth: 0 }}>
            <div style={{ fontFamily: 'Syne, sans-serif', fontSize: 13, fontWeight: 700, color: '#141413' }}>
              {t('title')}
            </div>
            <div style={{ marginTop: 4, fontFamily: "'DM Mono', monospace", fontSize: 10, color: '#87867f', lineHeight: 1.45 }}>
              {t('subtitle', { window: coverage?.window ?? '24h' })}
            </div>
          </div>
          <div style={{
            flexShrink: 0,
            display: 'inline-flex',
            alignItems: 'center',
            minHeight: 26,
            padding: '4px 8px',
            borderRadius: 6,
            border: `0.5px solid ${color}40`,
            background: `${color}12`,
            fontFamily: "'DM Mono', monospace",
            fontSize: 10,
            color,
          }}>
            {t(`state.${coverage?.status ?? 'no_data'}`)}
          </div>
        </div>

        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, minmax(120px, 1fr))', gap: 10 }} className="slo-coverage-grid">
          {rows.map(row => (
            <div key={row.label} style={{ minWidth: 0 }}>
              <div style={{ fontFamily: "'DM Mono', monospace", fontSize: 9, color: '#87867f', marginBottom: 3 }}>
                {row.label}
              </div>
              <div style={{ fontFamily: 'Syne, sans-serif', fontSize: 18, fontWeight: 700, color: '#141413', letterSpacing: 0 }}>
                {row.value}
              </div>
            </div>
          ))}
        </div>

        <div style={{ display: 'flex', flexWrap: 'wrap', gap: '8px 14px', fontFamily: "'DM Mono', monospace", fontSize: 10, color: '#87867f', lineHeight: 1.45 }}>
          <span>{t('reasonLabel')} {t(`reason.${coverageReasonKey(coverage?.reason)}`)}</span>
          <span>{t('successRate')} {formatPercent(coverage?.verification_success_rate)}</span>
          <span>{t('lastVerified')} {coverage?.last_verified_auto_at ?? '--'}</span>
        </div>

        {failureBreakdown.length > 0 && (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 7 }}>
            <div style={{ fontFamily: 'Syne, sans-serif', fontSize: 11, fontWeight: 700, color: '#141413' }}>
              {t('failureBreakdown')}
            </div>
            <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
              {failureBreakdown.map(item => (
                <span key={item.name} style={{
                  display: 'inline-flex',
                  alignItems: 'center',
                  minHeight: 24,
                  padding: '3px 7px',
                  borderRadius: 6,
                  border: '0.5px solid #F59E0B40',
                  background: 'rgba(245,158,11,0.08)',
                  fontFamily: "'DM Mono', monospace",
                  fontSize: 10,
                  color: '#7c5a10',
                }}>
                  {t(`failureClass.${failureClassKey(item.name)}`)} · {item.count}
                </span>
              ))}
            </div>
          </div>
        )}

        {remediationQueue && remediationQueue.total > 0 && (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
            <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 10 }}>
              <div style={{ fontFamily: 'Syne, sans-serif', fontSize: 11, fontWeight: 700, color: '#141413' }}>
                {t('remediationQueue')}
              </div>
              <div style={{ fontFamily: "'DM Mono', monospace", fontSize: 10, color: '#87867f' }}>
                {t('queueSummary', {
                  total: remediationQueue.total,
                  ready: remediationQueue.ready_for_ai,
                  human: remediationQueue.needs_human,
                })}
              </div>
            </div>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 7 }}>
              {(remediationQueue.items ?? []).slice(0, 4).map(item => {
                const historySummary = historyByWorkItem.get(item.work_item_id)
                return (
                <div key={item.work_item_id} style={{
                  display: 'grid',
                  gridTemplateColumns: 'minmax(130px, 0.8fr) minmax(180px, 1fr) minmax(150px, 0.9fr) minmax(150px, 0.8fr)',
                  gap: 10,
                  alignItems: 'center',
                  minWidth: 0,
                  padding: '7px 0',
                  borderTop: '0.5px solid rgba(20,20,19,0.08)',
                }} className="slo-remediation-row">
                  <div style={{ minWidth: 0 }}>
                    <div style={{ fontFamily: "'DM Mono', monospace", fontSize: 10, color: '#141413' }}>
                      {item.incident_id ?? '--'}
                    </div>
                    <div style={{ fontFamily: "'DM Mono', monospace", fontSize: 9, color: '#87867f', marginTop: 2 }}>
                      {t(`remediationStatus.${remediationStatusKey(item.remediation_status)}`)}
                    </div>
                  </div>
                  <div style={{ minWidth: 0 }}>
                    <div style={{ fontFamily: "'DM Mono', monospace", fontSize: 10, color: '#7c5a10' }}>
                      {t(`remediationAction.${remediationActionKey(item.remediation_action)}`)}
                    </div>
                    <div style={{ fontFamily: "'DM Mono', monospace", fontSize: 9, color: '#87867f', marginTop: 2, overflowWrap: 'anywhere' }}>
                      {compactLabel(item.alertname)} · {compactLabel(item.playbook_id)}
                    </div>
                  </div>
                  <div style={{ minWidth: 0 }}>
                    <div style={{ fontFamily: "'DM Mono', monospace", fontSize: 10, color: '#141413' }}>
                      {item.remediation_owner ?? '--'}
                    </div>
                    <div style={{ fontFamily: "'DM Mono', monospace", fontSize: 9, color: '#87867f', marginTop: 2, overflowWrap: 'anywhere' }}>
                      {compactLabel(item.remediation_reason)}
                    </div>
                  </div>
                  <div style={{ minWidth: 0, display: 'flex', flexDirection: 'column', gap: 5 }}>
                    <button
                      type="button"
                      onClick={() => { void handleDryRun(item.work_item_id) }}
                      disabled={actionState[item.work_item_id]?.status === 'loading'}
                      title={t('dryRunButton')}
                      style={{
                        width: 'fit-content',
                        minHeight: 28,
                        display: 'inline-flex',
                        alignItems: 'center',
                        gap: 6,
                        padding: '5px 9px',
                        borderRadius: 6,
                        border: '0.5px solid rgba(20,20,19,0.14)',
                        background: actionState[item.work_item_id]?.status === 'loading'
                          ? 'rgba(135,134,127,0.08)'
                          : 'rgba(34,197,94,0.08)',
                        color: '#141413',
                        fontFamily: "'DM Mono', monospace",
                        fontSize: 10,
                        cursor: actionState[item.work_item_id]?.status === 'loading' ? 'wait' : 'pointer',
                      }}
                    >
                      <PlayCircle size={13} style={{ color: '#22C55E', flexShrink: 0 }} />
                      <span>{actionState[item.work_item_id]?.status === 'loading' ? t('dryRunLoading') : t('dryRunButton')}</span>
                    </button>
                    {actionState[item.work_item_id]?.status === 'done' && (
                      <>
                        <div style={{
                          display: 'flex',
                          alignItems: 'flex-start',
                          gap: 5,
                          fontFamily: "'DM Mono', monospace",
                          fontSize: 9,
                          color: actionState[item.work_item_id].data?.allowed === false ? '#7c5a10' : '#166534',
                          lineHeight: 1.4,
                          overflowWrap: 'anywhere',
                        }}>
                          <SearchCheck size={12} style={{ flexShrink: 0, marginTop: 1 }} />
                          <span>
                            {actionState[item.work_item_id].data?.allowed === false
                              ? t('dryRunBlocked')
                              : t('dryRunResult', {
                                  mode: actionState[item.work_item_id].data?.mode ?? '--',
                                  result: actionState[item.work_item_id].data?.verification_result_preview ?? '--',
                                  tools: actionState[item.work_item_id].data?.post_state_summary?.tool_count ?? 0,
                                })}
                          </span>
                        </div>
                        {actionState[item.work_item_id].data?.history?.recorded && (
                          <div style={{
                            fontFamily: "'DM Mono', monospace",
                            fontSize: 9,
                            color: '#166534',
                            lineHeight: 1.4,
                            overflowWrap: 'anywhere',
                          }}>
                            {t('dryRunHistoryRecorded')}
                          </div>
                        )}
                      </>
                    )}
                    {historySummary && (
                      <div style={{
                        fontFamily: "'DM Mono', monospace",
                        fontSize: 9,
                        color: '#4b5563',
                        lineHeight: 1.4,
                        overflowWrap: 'anywhere',
                      }}>
                        {t('dryRunHistorySummary', {
                          count: historySummary.count,
                          time: formatShortDateTime(historySummary.latest_at),
                          route: historyRouteLabel(historySummary),
                        })}
                      </div>
                    )}
                    {actionState[item.work_item_id]?.status === 'error' && (
                      <div style={{ fontFamily: "'DM Mono', monospace", fontSize: 9, color: '#FF3300', lineHeight: 1.4 }}>
                        {t('dryRunError')}
                      </div>
                    )}
                  </div>
                </div>
                )
              })}
            </div>
          </div>
        )}

        {recentFindings.length > 0 && (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
            <div style={{ fontFamily: 'Syne, sans-serif', fontSize: 11, fontWeight: 700, color: '#141413' }}>
              {t('recentFindings')}
            </div>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 7 }}>
              {recentFindings.slice(0, 5).map(item => (
                <div key={`${item.auto_repair_id}-${item.incident_id}`} style={{
                  display: 'grid',
                  gridTemplateColumns: 'minmax(120px, 0.8fr) minmax(180px, 1.4fr) minmax(160px, 1fr)',
                  gap: 10,
                  alignItems: 'center',
                  minWidth: 0,
                  paddingTop: 7,
                  borderTop: '0.5px solid rgba(20,20,19,0.08)',
                }} className="slo-finding-row">
                  <div style={{ minWidth: 0 }}>
                    <div style={{ fontFamily: "'DM Mono', monospace", fontSize: 10, color: '#141413' }}>
                      {item.incident_id}
                    </div>
                    <div style={{ fontFamily: "'DM Mono', monospace", fontSize: 9, color: '#87867f', marginTop: 2 }}>
                      {item.incident_status} · {item.verification_result}
                    </div>
                  </div>
                  <div style={{ minWidth: 0 }}>
                    <div style={{ fontFamily: "'DM Mono', monospace", fontSize: 10, color: '#7c5a10' }}>
                      {t(`failureClass.${failureClassKey(item.failure_class)}`)}
                    </div>
                    <div style={{ fontFamily: "'DM Mono', monospace", fontSize: 9, color: '#87867f', marginTop: 2, overflowWrap: 'anywhere' }}>
                      {compactLabel(item.alertname)} · {compactLabel(item.playbook_name)}
                    </div>
                  </div>
                  <div style={{ minWidth: 0 }}>
                    <div style={{ fontFamily: "'DM Mono', monospace", fontSize: 10, color: '#141413' }}>
                      {t(`nextStep.${nextStepKey(item.next_step)}`)}
                    </div>
                    <div style={{ fontFamily: "'DM Mono', monospace", fontSize: 9, color: '#87867f', marginTop: 2, overflowWrap: 'anywhere' }}>
                      {compactLabel(item.auto_error_excerpt ?? item.evidence_excerpt)}
                    </div>
                  </div>
                </div>
              ))}
            </div>
          </div>
        )}
      </div>
    </GlassCard>
  )
}

// =============================================================================
// Component
// =============================================================================

export function SloTab() {
  const t = useTranslations('governance')

  const [sloData, setSloData] = useState<SloApiResponse | null>(null)
  const [summaryData, setSummaryData] = useState<SummaryApiResponse | null>(null)
  const [sloLoading, setSloLoading] = useState(true)
  const [summaryLoading, setSummaryLoading] = useState(true)
  const [sloError, setSloError] = useState(false)
  const [summaryError, setSummaryError] = useState(false)

  // Fetch SLO
  useEffect(() => {
    let cancelled = false
    setSloLoading(true)
    fetch(`${API_BASE}/api/v1/ai/slo`)
      .then(r => r.ok ? r.json() : Promise.reject(r.status))
      .then(d => { if (!cancelled) { setSloData(d); setSloError(false) } })
      .catch(() => { if (!cancelled) setSloError(true) })
      .finally(() => { if (!cancelled) setSloLoading(false) })
    return () => { cancelled = true }
  }, [])

  // Fetch 30d summary
  useEffect(() => {
    let cancelled = false
    setSummaryLoading(true)
    fetch(`${API_BASE}/api/v1/ai/governance/summary?days=30`)
      .then(r => r.ok ? r.json() : Promise.reject(r.status))
      .then(d => { if (!cancelled) { setSummaryData(d); setSummaryError(false) } })
      .catch(() => { if (!cancelled) setSummaryError(true) })
      .finally(() => { if (!cancelled) setSummaryLoading(false) })
    return () => { cancelled = true }
  }, [])

  const metrics = sloData ? buildMetrics(sloData) : []
  const compliance = sloData?.adr100?.overall_compliance ?? sloData?.overall_compliance ?? null
  const verificationCoverage = sloData?.adr100?.verification_coverage
  const autoExecuteDiagnostics = sloData?.diagnostics?.auto_execute_success_rate

  const chartData: ViolationDataPoint[] = summaryData?.data ?? []
  const eventTypes: string[] = summaryData?.event_types ?? []

  return (
    <div style={{ padding: '20px', display: 'flex', flexDirection: 'column', gap: 16 }}>

      {/* SLO Error banner */}
      {sloError && (
        <GlassCard variant="subtle" padding="sm">
          <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
            <AlertTriangle size={14} style={{ color: '#F59E0B', flexShrink: 0 }} />
            <span style={{ fontFamily: "'DM Mono', monospace", fontSize: 11, color: '#87867f' }}>
              {t('slo.kpi.error')}
            </span>
          </div>
        </GlassCard>
      )}

      {/* Overall compliance — inline badge row */}
      {!sloLoading && compliance !== null && (
        <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
          <div style={{
            display: 'inline-flex', alignItems: 'center', gap: 6,
            padding: '5px 10px',
            borderRadius: 6,
            background: compliance >= 0.95 ? 'rgba(34,197,94,0.08)' : 'rgba(245,158,11,0.08)',
            border: `0.5px solid ${compliance >= 0.95 ? '#22C55E40' : '#F59E0B40'}`,
          }}>
            <ShieldCheck size={13} style={{ color: compliance >= 0.95 ? '#22C55E' : '#F59E0B' }} />
            <span style={{
              fontFamily: 'Syne, sans-serif',
              fontSize: 13,
              fontWeight: 700,
              color: compliance >= 0.95 ? '#22C55E' : '#F59E0B',
            }}>
              {(compliance * 100).toFixed(1)}%
            </span>
            <span style={{ fontFamily: "'DM Mono', monospace", fontSize: 10, color: '#87867f' }}>
              {t('slo.compliance.title')}
            </span>
          </div>
          <span style={{ fontFamily: "'DM Mono', monospace", fontSize: 10, color: '#b8b4aa' }}>
            {t('slo.compliance.target')}
          </span>
        </div>
      )}

      {/* KPI cards — horizontal on desktop, stacked on mobile */}
      <div style={{
        display: 'flex',
        flexWrap: 'wrap',
        gap: 12,
      }}
      className="slo-kpi-grid"
      >
        {sloLoading
          ? [0, 1, 2, 3].map(i => <SloKpiCard key={i} metric={{ name: 'decision_accuracy', current: null, target: 0.9, status: 'warning' }} loading />)
          : metrics.map(m => <SloKpiCard key={m.name} metric={m} />)
        }
      </div>

      {!sloLoading && <AutoExecuteDiagnosticsPanel diagnostics={autoExecuteDiagnostics} />}

      {!sloLoading && <VerificationCoveragePanel coverage={verificationCoverage} />}

      {/* Violation timeline chart */}
      <SloViolationChart
        data={chartData}
        eventTypes={eventTypes}
        loading={summaryLoading}
        error={summaryError}
      />

      {/* Responsive helpers */}
      <style>{`
          .slo-kpi-grid > * { flex: 1; min-width: 200px; }
        @media (max-width: 640px) {
          .slo-kpi-grid > * { flex: 0 0 100%; min-width: 0; }
          .slo-coverage-grid { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
          .slo-auto-diagnostics-grid { grid-template-columns: 1fr !important; }
          .slo-auto-stat-grid { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
          .slo-auto-group-row { grid-template-columns: 1fr !important; }
          .slo-finding-row { grid-template-columns: 1fr !important; }
          .slo-remediation-row { grid-template-columns: 1fr !important; }
        }
      `}</style>
    </div>
  )
}
