'use client'

/**
 * DriftPanel — 配置漂移偵測面板 (不含 AppLayout)
 * ==================================================
 * Sprint 5: 從 /drift/page.tsx 抽取
 * 供原始頁面和整合頁面 (/automation) 共用
 *
 * 建立時間: 2026-04-09 (台北時區)
 */

import { useState, useEffect, useCallback } from 'react'
import { useTranslations } from 'next-intl'
import { cn } from '@/lib/utils'
import {
  Diff, RefreshCw, AlertTriangle, CheckCircle2,
  Clock, Terminal, GitMerge, Info, Fingerprint, GitPullRequest,
} from 'lucide-react'

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

interface DriftReport {
  report_id: string
  scanned_at: string
  namespace: string
  triggered_by: string
  high_count: number
  medium_count: number
  info_count: number
  interpretation: DriftInterpretationValue
  status: 'pending' | 'resolved' | 'acknowledged' | 'rolled_back' | 'adopted' | 'ignored'
  created_at: string
  resolved_at: string | null
}

interface ScanResult {
  report_id: string
  summary: string
  high_count: number
  medium_count: number
  info_count: number
  has_critical_drift: boolean
  interpretation: DriftInterpretationValue
}

type DriftInterpretationValue =
  | string
  | {
      intent?: string | null
      explanation?: string | null
      risk?: string | null
      confidence?: number | null
    }
  | null

interface DriftFingerprintState {
  namespace?: string
  fingerprint?: string
  latest_report_id?: string
  latest_status?: string
  summary?: string
  occurrences_12h?: number
  fsm_state?: string
  next_step?: string
  high_count?: number
  medium_count?: number
  info_count?: number
  open_pr?: {
    number?: number | string | null
    state?: string | null
    file_count?: number | null
    commit_count?: number | null
    is_zero_diff?: boolean | null
    lookup_error?: string | null
  } | null
  latest_handoff?: {
    handoff_status?: string | null
  } | null
  latest_remediation?: {
    remediation_kind?: string | null
    remediation_status?: string | null
    verification_report_id?: string | null
    verification_summary?: {
      summary?: string | null
      is_no_drift?: boolean | null
    } | null
    note?: string | null
    created_at?: string | null
  } | null
  p0_escalation?: {
    suppresses_repeated_p0?: boolean | null
    dedup_window_hours?: number | null
  } | null
  writes_drift_status?: boolean | null
  writes_incident_state?: boolean | null
  writes_auto_repair_result?: boolean | null
  writes_ticket?: boolean | null
}

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

const getApiBase = () => {
  if (typeof window === 'undefined') return ''
  return process.env.NEXT_PUBLIC_API_URL ?? ''
}

const fmtTime = (iso: string) => {
  try {
    return new Date(iso).toLocaleString('zh-TW', {
      year: 'numeric', month: '2-digit', day: '2-digit',
      hour: '2-digit', minute: '2-digit',
    })
  } catch {
    return iso
  }
}

const formatInterpretation = (value: DriftInterpretationValue) => {
  if (!value) return null
  if (typeof value === 'string') return value
  const meta = [
    value.intent,
    value.risk,
    typeof value.confidence === 'number' ? `${Math.round(value.confidence * 100)}%` : null,
  ].filter(Boolean).join(' / ')
  const explanation = value.explanation || ''
  if (meta && explanation) return `${meta} — ${explanation}`
  return meta || explanation || null
}

// =============================================================================
// Sub-components
// =============================================================================

function DriftLevelBadge({ high, medium, info, t }: {
  high: number; medium: number; info: number
  t: (k: string) => string
}) {
  if (high === 0 && medium === 0 && info === 0) {
    return (
      <span className="inline-flex items-center gap-1 px-2 py-0.5 rounded text-[11px] font-medium bg-status-healthy/10 text-status-healthy border border-status-healthy/20">
        <CheckCircle2 size={10} />
        {t('noDrift')}
      </span>
    )
  }
  return (
    <div className="flex items-center gap-1.5">
      {high > 0 && (
        <span className="inline-flex items-center gap-1 px-2 py-0.5 rounded text-[11px] font-medium bg-status-critical/10 text-status-critical border border-status-critical/20">
          <AlertTriangle size={10} />
          {t('highCount')} {high}
        </span>
      )}
      {medium > 0 && (
        <span className="inline-flex items-center gap-1 px-2 py-0.5 rounded text-[11px] font-medium bg-status-warning/10 text-status-warning border border-status-warning/20">
          <Info size={10} />
          {t('mediumCount')} {medium}
        </span>
      )}
      {info > 0 && (
        <span className="inline-flex items-center gap-1 px-2 py-0.5 rounded text-[11px] font-medium bg-neutral-100 text-neutral-500 border border-neutral-200">
          {t('infoCount')} {info}
        </span>
      )}
    </div>
  )
}

function StatusBadge({ status, t }: { status: DriftReport['status']; t: (k: string) => string }) {
  const styles: Record<string, string> = {
    pending:  'bg-status-warning/10 text-status-warning border-status-warning/20',
    resolved: 'bg-status-healthy/10 text-status-healthy border-status-healthy/20',
    acknowledged: 'bg-neutral-100 text-neutral-500 border-neutral-200',
    rolled_back: 'bg-status-healthy/10 text-status-healthy border-status-healthy/20',
    adopted: 'bg-status-healthy/10 text-status-healthy border-status-healthy/20',
    ignored:  'bg-neutral-100 text-neutral-400 border-neutral-200',
  }
  return (
    <span className={cn(
      'inline-flex items-center px-2 py-0.5 rounded text-[11px] font-medium border',
      styles[status] ?? styles.ignored
    )}>
      {t(status)}
    </span>
  )
}

function DriftFingerprintStateCard({
  state,
  t,
}: {
  state: DriftFingerprintState | null
  t: (k: string, values?: Record<string, string | number>) => string
}) {
  if (!state) return null
  return (
    <div className="mx-6 mt-4 border border-neutral-200 bg-neutral-50 px-4 py-3">
      <div className="flex flex-wrap items-start justify-between gap-3">
        <div className="flex min-w-0 items-start gap-2">
          <Fingerprint size={15} className="mt-0.5 shrink-0 text-neutral-500" />
          <div className="min-w-0">
            <p className="text-[12px] font-semibold text-neutral-800">
              {t('fingerprintState.title')}
            </p>
            <p className="mt-1 truncate font-mono text-[11px] text-neutral-500">
              {state.fingerprint ?? '--'}
            </p>
          </div>
        </div>
        <span className="border border-status-warning/20 bg-status-warning/10 px-2 py-0.5 text-[11px] font-medium text-status-warning">
          {t('fingerprintState.occurrences', { count: state.occurrences_12h ?? 0 })}
        </span>
      </div>
      <div className="mt-3 grid gap-2 text-[11px] text-neutral-500 md:grid-cols-2">
        <p>{t('fingerprintState.report', { report: state.latest_report_id ?? '--' })}</p>
        <p>{t('fingerprintState.state', { state: state.fsm_state ?? '--' })}</p>
        <p>{t('fingerprintState.next', { step: state.next_step ?? '--' })}</p>
        <p>
          {t('fingerprintState.writes', {
            drift: String(state.writes_drift_status ?? false),
            incident: String(state.writes_incident_state ?? false),
            repair: String(state.writes_auto_repair_result ?? false),
            ticket: String(state.writes_ticket ?? false),
          })}
        </p>
      </div>
      <div className="mt-3 flex flex-wrap items-center gap-2 text-[11px] text-neutral-500">
        <span className="inline-flex items-center gap-1 border border-neutral-200 bg-white px-2 py-0.5">
          <GitPullRequest size={11} />
          {t('fingerprintState.pr', {
            pr: state.open_pr?.number ?? '--',
            zeroDiff: String(state.open_pr?.is_zero_diff ?? false),
          })}
        </span>
        <span className="border border-neutral-200 bg-white px-2 py-0.5">
          {t('fingerprintState.p0Dedup', {
            hours: state.p0_escalation?.dedup_window_hours ?? 24,
          })}
        </span>
        <span className="border border-status-healthy/20 bg-status-healthy/10 px-2 py-0.5 text-status-healthy">
          {t('fingerprintState.remediation', {
            status: state.latest_remediation?.remediation_status ?? '--',
            report: state.latest_remediation?.verification_report_id ?? '--',
          })}
        </span>
      </div>
      {state.latest_remediation ? (
        <div className="mt-3 border border-neutral-200 bg-white px-3 py-2 text-[11px] leading-5 text-neutral-500">
          <p>
            {t('fingerprintState.remediationKind', {
              kind: state.latest_remediation.remediation_kind ?? '--',
            })}
          </p>
          <p>
            {t('fingerprintState.remediationVerification', {
              summary: state.latest_remediation.verification_summary?.summary ?? '--',
            })}
          </p>
          <p>
            {t('fingerprintState.remediationNote', {
              note: state.latest_remediation.note ?? '--',
            })}
          </p>
        </div>
      ) : null}
    </div>
  )
}

// =============================================================================
// DriftPanel
// =============================================================================

export function DriftPanel() {
  const t = useTranslations('drift')
  const [reports, setReports] = useState<DriftReport[]>([])
  const [loading, setLoading] = useState(true)
  const [scanning, setScanning] = useState(false)
  const [scanResult, setScanResult] = useState<ScanResult | null>(null)
  const [fingerprintState, setFingerprintState] = useState<DriftFingerprintState | null>(null)
  const [error, setError] = useState<string | null>(null)

  const fetchReports = useCallback(async () => {
    setLoading(true)
    setError(null)
    try {
      const res = await fetch(`${getApiBase()}/api/v1/drift/reports?limit=20`)
      if (!res.ok) throw new Error(`HTTP ${res.status}`)
      const data = await res.json()
      const nextReports = data.items ?? []
      setReports(nextReports)
      const latestReportId = nextReports[0]?.report_id
      if (latestReportId) {
        const stateRes = await fetch(
          `${getApiBase()}/api/v1/drift/fingerprints/state?report_id=${encodeURIComponent(latestReportId)}`
        )
        setFingerprintState(stateRes.ok ? await stateRes.json() : null)
      } else {
        setFingerprintState(null)
      }
    } catch (e) {
      setError(e instanceof Error ? e.message : 'Failed to fetch')
    } finally {
      setLoading(false)
    }
  }, [])

  useEffect(() => { fetchReports() }, [fetchReports])

  const handleScan = async () => {
    setScanning(true)
    setScanResult(null)
    try {
      const res = await fetch(`${getApiBase()}/api/v1/drift/scan`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ namespaces: ['awoooi-prod'], triggered_by: 'web_manual' }),
      })
      if (!res.ok) throw new Error(`HTTP ${res.status}`)
      const data: ScanResult = await res.json()
      setScanResult(data)
      await fetchReports()
    } catch (e) {
      setError(e instanceof Error ? e.message : 'Scan failed')
    } finally {
      setScanning(false)
    }
  }

  return (
    <div className="flex flex-col h-full overflow-auto bg-white">
      {/* Header */}
      <div className="flex items-center justify-between px-6 py-4 border-b border-neutral-100">
        <div className="flex items-center gap-3">
          <Diff size={18} className="text-neutral-400" />
          <div>
            <h1 className="text-[13px] font-semibold text-neutral-800 leading-tight">
              {t('title')}
            </h1>
            <p className="text-[11px] text-neutral-400 leading-tight mt-0.5">
              {t('subtitle')}
            </p>
          </div>
        </div>
        <div className="flex items-center gap-2">
          <button
            onClick={fetchReports}
            disabled={loading}
            className="p-1.5 rounded text-neutral-400 hover:text-neutral-600 hover:bg-neutral-50 transition-colors disabled:opacity-40"
          >
            <RefreshCw size={13} className={loading ? 'animate-spin' : ''} />
          </button>
          <button
            onClick={handleScan}
            disabled={scanning}
            className={cn(
              'flex items-center gap-1.5 px-3 py-1.5 rounded text-[11px] font-medium transition-colors',
              scanning
                ? 'bg-neutral-100 text-neutral-400 cursor-not-allowed'
                : 'bg-neutral-900 text-white hover:bg-neutral-700'
            )}
          >
            {scanning ? (
              <>
                <RefreshCw size={11} className="animate-spin" />
                {t('scanning')}
              </>
            ) : (
              <>
                <GitMerge size={11} />
                {t('scan')}
              </>
            )}
          </button>
        </div>
      </div>

      {/* Scan Result Banner */}
      {scanResult && (
        <div className={cn(
          'mx-6 mt-4 px-4 py-3 rounded border text-[12px]',
          scanResult.has_critical_drift
            ? 'bg-status-critical/5 border-status-critical/20 text-status-critical'
            : 'bg-status-healthy/5 border-status-healthy/20 text-status-healthy'
        )}>
          <div className="flex items-center gap-2 font-medium">
            {scanResult.has_critical_drift
              ? <AlertTriangle size={13} />
              : <CheckCircle2 size={13} />
            }
            {scanResult.summary}
            {(scanResult.high_count > 0 || scanResult.medium_count > 0) && (
              <span className="ml-2 text-neutral-500 font-normal">
                — {t('highCount')} {scanResult.high_count}, {t('mediumCount')} {scanResult.medium_count}
              </span>
            )}
          </div>
          {formatInterpretation(scanResult.interpretation) && (
            <p className="mt-1.5 text-neutral-600 font-normal pl-5">
              {formatInterpretation(scanResult.interpretation)}
            </p>
          )}
        </div>
      )}

      {/* Error */}
      {error && (
        <div className="mx-6 mt-4 px-4 py-3 rounded border border-status-critical/20 bg-status-critical/5 text-status-critical text-[12px]">
          {error}
        </div>
      )}

      <DriftFingerprintStateCard state={fingerprintState} t={t} />

      {/* Content */}
      <div className="flex-1 px-6 py-4">
        {loading && reports.length === 0 ? (
          <div className="flex items-center justify-center h-32 text-neutral-400">
            <RefreshCw size={16} className="animate-spin mr-2" />
            <span className="text-[12px]">{t('loading')}</span>
          </div>
        ) : reports.length === 0 ? (
          <div className="flex flex-col items-center justify-center h-48 text-neutral-400">
            <Terminal size={32} className="mb-3 opacity-30" />
            <p className="text-[13px] font-medium text-neutral-500">{t('noReports')}</p>
            <p className="text-[11px] text-neutral-400 mt-1 text-center max-w-xs">{t('noReportsHint')}</p>
          </div>
        ) : (
          <div className="space-y-2">
            {reports.map((report) => (
              <div
                key={report.report_id}
                className="border border-neutral-100 rounded-lg px-4 py-3 hover:border-neutral-200 transition-colors"
              >
                <div className="flex items-center justify-between gap-3">
                  <div className="flex items-center gap-3 min-w-0">
                    <code className="text-[11px] font-mono text-neutral-500 bg-neutral-50 px-1.5 py-0.5 rounded shrink-0">
                      {report.report_id.slice(0, 8)}
                    </code>
                    <DriftLevelBadge
                      high={report.high_count}
                      medium={report.medium_count}
                      info={report.info_count}
                      t={t}
                    />
                  </div>
                  <div className="flex items-center gap-2 shrink-0">
                    <StatusBadge status={report.status} t={t} />
                    <span className="text-[11px] text-neutral-400 flex items-center gap-1">
                      <Clock size={10} />
                      {fmtTime(report.scanned_at)}
                    </span>
                  </div>
                </div>
                {formatInterpretation(report.interpretation) && (
                  <p className="mt-2 text-[11px] text-neutral-500 pl-1 border-l-2 border-neutral-100">
                    {formatInterpretation(report.interpretation)}
                  </p>
                )}
                <div className="flex items-center gap-4 mt-2 text-[10px] text-neutral-400">
                  <span>{t('namespace')}: <span className="font-mono">{report.namespace}</span></span>
                  <span>{t('triggeredBy')}: {report.triggered_by}</span>
                </div>
              </div>
            ))}
          </div>
        )}
      </div>
    </div>
  )
}
