'use client'

/**
 * AutomationEvidenceCard — homepage AI automation truth-chain snapshot.
 *
 * Shows the operator whether alerts are persisted, deduped, investigated by
 * MCP, auto-repaired, or blocked by human work items using existing AwoooP
 * read APIs. No fallback sample data is rendered.
 */

import { useEffect, useMemo, useState } from 'react'
import { useTranslations } from 'next-intl'
import {
  Activity,
  AlertTriangle,
  CheckCircle2,
  GitBranch,
  Route,
  SearchCheck,
  ShieldCheck,
} from 'lucide-react'

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

interface AutomationQualitySummary {
  evaluated_total: number
  verified_auto_repair_total: number
  average_score: number
  score_buckets?: {
    green?: number
    yellow?: number
    red?: number
  }
  production_claim?: {
    can_claim_full_auto_repair?: boolean
    reason?: string
  }
  gate_failures?: Array<{
    gate: string
    total: number
  }>
  execution_backend_summary?: {
    operation_records_total?: number
    effective_execution_records_total?: number
    audit_only_operation_records_total?: number
    auto_repair_execution_records_total?: number
    ansible_considered_total?: number
    ansible_audit_record_total?: number
    ansible_candidate_total?: number
    ansible_check_mode_total?: number
    ansible_apply_total?: number
    ansible_pending_check_mode_total?: number
  }
  ansible_runtime?: {
    ansible_playbook_binary_present?: boolean
    playbook_root_present?: boolean
    inventory_present?: boolean
    playbook_count?: number
    can_run_check_mode?: boolean
    blockers?: string[]
  }
}

interface DossierCoverageResponse {
  summary?: {
    source_count?: number
    missing_source_refs_total?: number
    duplicate_total?: number
    latest_received_at?: string | null
  }
}

interface EventRecurrenceResponse {
  summary?: {
    recurrence_group_total?: number
    recurrent_group_total?: number
    duplicate_event_total?: number
    linked_run_total?: number
    auto_repair_linked_total?: number
    verified_repair_group_total?: number
    open_work_item_group_total?: number
    automation_gap_group_total?: number
    latest_received_at?: string | null
  }
}

interface RunSummary {
  remediation_summary?: {
    mcp_observation_total?: number
    mcp_observation_success?: number
    mcp_observation_failed?: number
    latest_route?: string | null
    latest_mcp_server?: string | null
  } | null
}

interface RunsResponse {
  runs?: RunSummary[]
  items?: RunSummary[]
}

interface AiRoutePolicyItem {
  provider_name: string
  role?: string | null
  runtime?: string | null
}

interface AiRouteHealthItem {
  status?: string | null
  latency_ms?: number | null
  reason?: string | null
  checked?: boolean
}

interface AiRouteStatusResponse {
  policy_order?: AiRoutePolicyItem[]
  selected_provider?: string | null
  selected_model?: string | null
  fallback_chain?: AiRoutePolicyItem[]
  route_reason?: string | null
  route_error?: string | null
  health?: Record<string, AiRouteHealthItem>
  lane_mode?: string | null
  skipped_lanes?: Array<{ provider_name?: string | null }>
  operator_action?: {
    action?: string | null
    human_required?: boolean
  } | null
  repair_evidence?: {
    target_resource?: string | null
    access_blockers?: string[]
    source_ref_count?: number | null
  } | null
}

interface EvidenceSnapshot {
  quality: AutomationQualitySummary | null
  coverage: DossierCoverageResponse | null
  recurrence: EventRecurrenceResponse | null
  runs: RunSummary[]
  route: AiRouteStatusResponse | null
}

type Tone = 'good' | 'warn' | 'neutral'

function metricToneClass(tone: Tone) {
  if (tone === 'good') return 'border-[#9bc7a4] bg-[#f0faf2] text-[#17602a]'
  if (tone === 'warn') return 'border-[#d9b36f] bg-[#fff7e8] text-[#8a5a08]'
  return 'border-[#d8d3c7] bg-[#faf9f3] text-[#5f5b52]'
}

function formatTime(value?: string | null) {
  if (!value) return '--'
  const date = new Date(value)
  if (Number.isNaN(date.getTime())) return '--'
  return date.toLocaleTimeString('zh-TW', { hour: '2-digit', minute: '2-digit' })
}

function gateLabelKey(gate?: string) {
  switch (gate) {
    case 'source_persisted':
      return 'gates.sourcePersisted'
    case 'outbound_recorded':
      return 'gates.outboundRecorded'
    case 'evidence_collected':
      return 'gates.evidenceCollected'
    case 'mcp_gateway_observed':
      return 'gates.mcpGatewayObserved'
    case 'approval_state':
      return 'gates.approvalState'
    case 'execution_recorded':
      return 'gates.executionRecorded'
    case 'auto_repair_recorded':
      return 'gates.autoRepairRecorded'
    case 'verification_recorded':
      return 'gates.verificationRecorded'
    case 'learning_recorded':
      return 'gates.learningRecorded'
    case 'timeline_recorded':
      return 'gates.timelineRecorded'
    default:
      return 'gates.unknown'
  }
}

function routeHealthLabelKey(status?: string | null) {
  if (
    status === 'healthy' ||
    status === 'slow' ||
    status === 'degraded' ||
    status === 'offline' ||
    status === 'not_checked'
  ) {
    return `routeHealth.${status}`
  }
  return 'routeHealth.unknown'
}

function routeLaneModeLabelKey(mode?: string | null) {
  if (
    mode === 'primary' ||
    mode === 'degraded_failover' ||
    mode === 'cloud_fallback' ||
    mode === 'unavailable'
  ) {
    return `routeLaneMode.${mode}`
  }
  return 'routeLaneMode.unknown'
}

function providerDisplayName(provider?: string | null) {
  switch (provider) {
    case 'ollama_gcp_a':
      return 'GCP-A'
    case 'ollama_gcp_b':
      return 'GCP-B'
    case 'ollama_local':
      return '111'
    case 'gemini':
      return 'Gemini'
    default:
      return provider || '--'
  }
}

function routeTone(route: AiRouteStatusResponse | null): Tone {
  if (!route?.selected_provider || route.route_error) return 'warn'
  const primaryProvider = route.policy_order?.[0]?.provider_name
  if (primaryProvider && route.selected_provider !== primaryProvider) return 'warn'
  const primaryStatus = primaryProvider ? route.health?.[primaryProvider]?.status : null
  return primaryStatus === 'healthy' ? 'good' : 'warn'
}

async function fetchJson<T>(path: string, signal: AbortSignal): Promise<T | null> {
  const response = await fetch(`${API_BASE}${path}`, { signal })
  if (!response.ok) return null
  return response.json() as Promise<T>
}

function EvidenceMetric({
  label,
  value,
  detail,
  tone,
  icon: Icon,
}: {
  label: string
  value: string | number
  detail: string
  tone: Tone
  icon: typeof Activity
}) {
  return (
    <div style={{ background: '#fff', padding: '10px 12px', minHeight: 94 }}>
      <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 10 }}>
        <div style={{ minWidth: 0 }}>
          <div style={{ fontSize: 10, color: '#77736a', fontWeight: 700, letterSpacing: 0.4, textTransform: 'uppercase' }}>
            {label}
          </div>
          <div style={{ marginTop: 5, fontFamily: "'JetBrains Mono', monospace", fontSize: 22, fontWeight: 700, color: '#141413', lineHeight: 1 }}>
            {value}
          </div>
        </div>
        <span className={`flex h-8 w-8 shrink-0 items-center justify-center border ${metricToneClass(tone)}`}>
          <Icon className="h-4 w-4" aria-hidden="true" />
        </span>
      </div>
      <div style={{ marginTop: 8, fontSize: 11, color: '#5f5b52', lineHeight: 1.45 }}>
        {detail}
      </div>
    </div>
  )
}

export function AutomationEvidenceCard() {
  const t = useTranslations('dashboard.automationEvidence')
  const tQuality = useTranslations('awooop.home.quality')
  const [snapshot, setSnapshot] = useState<EvidenceSnapshot | null>(null)
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)

  useEffect(() => {
    if (!API_BASE) {
      setError(t('missingApiBase'))
      setLoading(false)
      return
    }

    const controller = new AbortController()

    async function load() {
      try {
        setError(null)
        const [coverage, recurrence, runs, route] = await Promise.all([
          fetchJson<DossierCoverageResponse>('/api/v1/platform/events/dossier/coverage?project_id=awoooi&limit=100', controller.signal),
          fetchJson<EventRecurrenceResponse>('/api/v1/platform/events/dossier/recurrence?project_id=awoooi&limit=100', controller.signal),
          fetchJson<RunsResponse>('/api/v1/platform/runs/list?project_id=awoooi&per_page=25', controller.signal),
          fetchJson<AiRouteStatusResponse>('/api/v1/platform/ai-route-status?workload_type=deep_rca', controller.signal),
        ])

        setSnapshot((current) => ({
          quality: current?.quality ?? null,
          coverage,
          recurrence,
          runs: Array.isArray(runs?.runs) ? runs.runs : Array.isArray(runs?.items) ? runs.items : [],
          route,
        }))
        setLoading(false)

        try {
          const quality = await fetchJson<AutomationQualitySummary>(
            '/api/v1/platform/truth-chain/quality/summary?project_id=awoooi&hours=24&limit=200',
            controller.signal
          )
          if (!controller.signal.aborted) {
            setSnapshot((current) => ({
              quality: quality ?? current?.quality ?? null,
              coverage: current?.coverage ?? coverage,
              recurrence: current?.recurrence ?? recurrence,
              runs: current?.runs ?? (Array.isArray(runs?.runs) ? runs.runs : Array.isArray(runs?.items) ? runs.items : []),
              route: current?.route ?? route,
            }))
          }
        } catch {
          if (!controller.signal.aborted) {
            setSnapshot((current) => current ?? {
              quality: null,
              coverage,
              recurrence,
              runs: Array.isArray(runs?.runs) ? runs.runs : Array.isArray(runs?.items) ? runs.items : [],
              route,
            })
          }
        }
      } catch (err) {
        if (!controller.signal.aborted) {
          setError(err instanceof Error ? err.message : t('loadFailed'))
          setLoading(false)
        }
      } finally {
        if (!controller.signal.aborted) setLoading(false)
      }
    }

    load()
    const timer = setInterval(load, 30_000)
    return () => {
      controller.abort()
      clearInterval(timer)
    }
  }, [t])

  const derived = useMemo(() => {
    const quality = snapshot?.quality
    const coverage = snapshot?.coverage?.summary
    const recurrence = snapshot?.recurrence?.summary
    const runEvidence = (snapshot?.runs ?? []).reduce(
      (acc, run) => {
        const summary = run.remediation_summary
        acc.total += summary?.mcp_observation_total ?? 0
        acc.success += summary?.mcp_observation_success ?? 0
        acc.failed += summary?.mcp_observation_failed ?? 0
        if (!acc.route && summary?.latest_route) acc.route = summary.latest_route
        if (!acc.server && summary?.latest_mcp_server) acc.server = summary.latest_mcp_server
        return acc
      },
      { total: 0, success: 0, failed: 0, route: null as string | null, server: null as string | null }
    )

    const topGate = quality?.gate_failures?.[0]
    const executionBackend = quality?.execution_backend_summary ?? null
    const ansibleRuntime = quality?.ansible_runtime ?? null
    const qualityLoaded = Boolean(quality)
    const claimReady = Boolean(quality?.production_claim?.can_claim_full_auto_repair)
    const route = snapshot?.route ?? null
    const primaryProvider = route?.policy_order?.[0]?.provider_name ?? null
    const primaryStatus = primaryProvider ? route?.health?.[primaryProvider]?.status : null
    const selectedProvider = providerDisplayName(route?.selected_provider)
    const laneMode = route?.lane_mode ?? null
    const skippedLanes = route?.skipped_lanes
      ?.map((lane) => providerDisplayName(lane.provider_name))
      .join(' -> ')
    const fallback = route?.fallback_chain
      ?.map((item) => item.provider_name)
      .map(providerDisplayName)
      .join(' -> ')
    const routeSummary = route?.route_error
      ? t('routeErrorDetail', { error: route.route_error })
      : t('routeDetail', {
        model: route?.selected_model ?? '--',
        selected: selectedProvider,
        primary: providerDisplayName(primaryProvider),
        primaryStatus: t(routeHealthLabelKey(primaryStatus) as never),
        fallback: fallback || t('routeNoFallback'),
      })
    const laneDetail = laneMode && laneMode !== 'primary'
      ? t('routeLaneDetail', {
        mode: t(routeLaneModeLabelKey(laneMode) as never),
        skipped: skippedLanes || '--',
      })
      : null
    const repairEvidence = route?.repair_evidence ?? null
    const repairBlockers = repairEvidence?.access_blockers?.slice(0, 2).join(', ')
    const repairDetail = repairEvidence
      ? t('routeRepairDetail', {
        target: repairEvidence.target_resource ?? '--',
        blockers: repairBlockers || '--',
        sourceRefs: repairEvidence.source_ref_count ?? 0,
      })
      : null
    const routeDetail = route?.route_reason && !route.route_error
      ? `${routeSummary}${laneDetail ? t('routeReasonSeparator') + laneDetail : ''}${repairDetail ? t('routeReasonSeparator') + repairDetail : ''}${t('routeReasonSeparator')}${t('routeReason', { reason: route.route_reason })}`
      : routeSummary

    return {
      quality,
      coverage,
      recurrence,
      runEvidence,
      topGate,
      qualityLoaded,
      claimReady,
      selectedProvider,
      fallback,
      routeDetail,
      routeTone: routeTone(route),
      executionBackend,
      ansibleRuntime,
    }
  }, [snapshot, t])

  const hasData = Boolean(
    snapshot?.quality ||
    snapshot?.coverage ||
    snapshot?.recurrence ||
    snapshot?.route ||
    (snapshot?.runs?.length ?? 0) > 0
  )

  return (
    <div style={{
      background: '#fff',
      border: '0.5px solid #e0ddd4',
      borderRadius: 12,
      overflow: 'hidden',
      boxShadow: '0 1px 4px rgba(0,0,0,0.05)',
      flexShrink: 0,
    }}>
      <div style={{
        padding: '10px 14px',
        borderBottom: '0.5px solid #e0ddd4',
        fontSize: 14,
        fontWeight: 700,
        color: '#141413',
        letterSpacing: '0.5px',
        fontFamily: 'var(--font-body), monospace',
        background: '#faf9f3',
        display: 'flex',
        alignItems: 'center',
        gap: 8,
      }}>
        <div style={{
          width: 6,
          height: 6,
          borderRadius: '50%',
          background: !derived.qualityLoaded ? '#9CA3AF' : derived.claimReady ? '#22C55E' : '#F59E0B',
          flexShrink: 0,
        }} />
        {t('title')}
        <span style={{
          marginLeft: 'auto',
          fontSize: 10,
          color: !derived.qualityLoaded ? '#77736a' : derived.claimReady ? '#17602a' : '#8a5a08',
          fontWeight: 700,
        }}>
          {!derived.qualityLoaded ? t('claimChecking') : derived.claimReady ? t('claimReady') : t('claimBlocked')}
        </span>
      </div>

      {loading ? (
        <div style={{ padding: 14, fontSize: 12, color: '#77736a' }}>{t('loading')}</div>
      ) : error ? (
        <div style={{ padding: 14, fontSize: 12, color: '#9f2f25' }}>{t('error', { error })}</div>
      ) : !hasData ? (
        <div style={{ padding: 14, fontSize: 12, color: '#77736a' }}>{t('empty')}</div>
      ) : (
        <>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 1, background: '#e0ddd4' }}>
            <EvidenceMetric
              label={t('sourcePersisted')}
              value={derived.coverage?.source_count ?? '--'}
              detail={t('sourceDetail', {
                missing: derived.coverage?.missing_source_refs_total ?? 0,
                latest: formatTime(derived.coverage?.latest_received_at),
              })}
              tone={(derived.coverage?.missing_source_refs_total ?? 0) === 0 ? 'good' : 'warn'}
              icon={CheckCircle2}
            />
            <EvidenceMetric
              label={t('recurrence')}
              value={`${derived.recurrence?.recurrent_group_total ?? 0}/${derived.recurrence?.recurrence_group_total ?? 0}`}
              detail={t('recurrenceDetail', {
                duplicates: derived.recurrence?.duplicate_event_total ?? 0,
                workItems: derived.recurrence?.open_work_item_group_total ?? 0,
              })}
              tone={(derived.recurrence?.open_work_item_group_total ?? 0) > 0 ? 'warn' : 'good'}
              icon={GitBranch}
            />
            <EvidenceMetric
              label={t('mcpInvestigation')}
              value={derived.runEvidence.total || '--'}
              detail={t('mcpDetail', {
                success: derived.runEvidence.success,
                failed: derived.runEvidence.failed,
                server: derived.runEvidence.server ?? '--',
              })}
              tone={derived.runEvidence.failed > 0 ? 'warn' : 'good'}
              icon={SearchCheck}
            />
            <EvidenceMetric
              label={t('autoRepair')}
              value={derived.quality ? `${derived.quality.verified_auto_repair_total}/${derived.quality.evaluated_total}` : '--'}
              detail={derived.quality
                ? t('qualityDetail', {
                  score: derived.quality.average_score.toFixed(1),
                  red: derived.quality.score_buckets?.red ?? 0,
                })
                : t('qualityPending')}
              tone={!derived.qualityLoaded ? 'neutral' : derived.claimReady ? 'good' : 'warn'}
              icon={Activity}
            />
            <EvidenceMetric
              label={t('humanGap')}
              value={derived.recurrence?.automation_gap_group_total ?? 0}
              detail={derived.topGate
                ? t('humanGapDetail', {
                  gate: tQuality(gateLabelKey(derived.topGate.gate) as never),
                  count: derived.topGate.total,
                })
                : derived.qualityLoaded ? t('humanGapClear') : t('qualityPending')}
              tone={(derived.recurrence?.automation_gap_group_total ?? 0) > 0 ? 'warn' : 'good'}
              icon={ShieldCheck}
            />
            <EvidenceMetric
              label={t('modelRoute')}
              value={derived.selectedProvider}
              detail={derived.routeDetail}
              tone={derived.routeTone}
              icon={Route}
            />
          </div>

          {derived.executionBackend && (
            <div
              data-testid="automation-execution-backend-evidence"
              style={{
                borderTop: '0.5px solid #e0ddd4',
                background: '#fbfaf6',
                padding: '8px 14px',
                display: 'flex',
                alignItems: 'center',
                gap: 8,
                fontSize: 11,
                color: '#555550',
                lineHeight: 1.45,
              }}
            >
              <Activity className="h-3.5 w-3.5 shrink-0" aria-hidden="true" />
              <span style={{ minWidth: 0 }}>
                {t('executionBackendDetail', {
                  operations: derived.executionBackend.operation_records_total ?? 0,
                  effective: derived.executionBackend.effective_execution_records_total ?? 0,
                  auditOnly: derived.executionBackend.audit_only_operation_records_total ?? 0,
                  autoRepair: derived.executionBackend.auto_repair_execution_records_total ?? 0,
                  ansibleRecords: derived.executionBackend.ansible_audit_record_total ?? 0,
                  ansibleCandidates: derived.executionBackend.ansible_candidate_total ?? 0,
                  checkMode: derived.executionBackend.ansible_check_mode_total ?? 0,
                  apply: derived.executionBackend.ansible_apply_total ?? 0,
                  pending: derived.executionBackend.ansible_pending_check_mode_total ?? 0,
                  runtime: derived.ansibleRuntime?.can_run_check_mode
                    ? t('ansibleRuntimeReady')
                    : t('ansibleRuntimeBlocked', {
                      blockers: (derived.ansibleRuntime?.blockers ?? []).slice(0, 2).join(', ') || '--',
                    }),
                })}
              </span>
            </div>
          )}

          {derived.topGate && (
            <div style={{
              borderTop: '0.5px solid #e0ddd4',
              background: 'rgba(245,158,11,0.08)',
              padding: '8px 14px',
              display: 'flex',
              alignItems: 'center',
              gap: 8,
              fontSize: 11,
              color: '#8a5a08',
              lineHeight: 1.45,
            }}>
              <AlertTriangle className="h-3.5 w-3.5 shrink-0" aria-hidden="true" />
              {t('topGap', {
                gate: tQuality(gateLabelKey(derived.topGate.gate) as never),
                count: derived.topGate.total,
              })}
            </div>
          )}
        </>
      )}
    </div>
  )
}
