"use client" import { AlertTriangleIcon, ArrowRightIcon, CheckCircle2Icon, ExternalLinkIcon, Loader2Icon, PlayIcon, RefreshCwIcon, ShieldAlertIcon, SparklesIcon, UserCheckIcon, XCircleIcon, } from "lucide-react" import Link from "next/link" import { useCallback, useEffect, useMemo, useState } from "react" import { toast } from "sonner" import { DashboardPage } from "@/components/dashboard-page" import { notifySetupReadinessUpdated, SETUP_READINESS_UPDATED_EVENT, } from "@/components/operator-readiness-indicator" import { OptionCombobox } from "@/components/option-combobox" import { Badge } from "@/components/ui/badge" import { Button } from "@/components/ui/button" import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table" import { useI18n } from "@/i18n/provider" import { applySetupQuickFix, fetchSetupReadiness, simulateSetupRoute, type SetupQuickFixAction, type SetupReadinessResponse, type SetupSimulateRouteResponse, type SetupStepStatus, } from "@/lib/api/setup-readiness" import { cn } from "@/lib/utils" function StatusIcon({ status }: { status: SetupStepStatus }) { if (status === "ok") { return ( ) } if (status === "warning") { return ( ) } return ( ) } function StatusBadge({ status }: { status: SetupStepStatus }) { const t = useI18n() if (status === "ok") { return ( {t("setupWizard.stepBadgeOk")} ) } if (status === "warning") { return ( {t("setupWizard.stepBadgeWarning")} ) } return ( {t("setupWizard.stepBadgeError")} ) } export function SetupWizardView() { const t = useI18n() const [readiness, setReadiness] = useState(null) const [loading, setLoading] = useState(true) const [fixingAction, setFixingAction] = useState(null) const [selectedChannelId, setSelectedChannelId] = useState("") const [simulation, setSimulation] = useState(null) const [simulating, setSimulating] = useState(false) const runSimulation = useCallback(async (channelIdNum?: number) => { setSimulating(true) try { const sim = await simulateSetupRoute({ channel_id: channelIdNum && channelIdNum > 0 ? channelIdNum : undefined, bypass_ai: true, }) setSimulation(sim) if (sim.channel_id > 0) { setSelectedChannelId(String(sim.channel_id)) } } catch (error) { toast.error( error instanceof Error ? error.message : t("common.operationFailed"), ) } finally { setSimulating(false) } }, [t]) const loadAll = useCallback(async () => { setLoading(true) try { const data = await fetchSetupReadiness() setReadiness(data) const currentNum = Number(selectedChannelId) const targetChannelId = currentNum > 0 ? currentNum : data.channels.find((ch) => ch.status === 0)?.id ?? data.channels[0]?.id ?? 0 if (targetChannelId > 0) { setSelectedChannelId(String(targetChannelId)) } await runSimulation(targetChannelId) } catch (error) { toast.error( error instanceof Error ? error.message : t("common.loadFailed"), ) } finally { setLoading(false) } }, [runSimulation, selectedChannelId, t]) useEffect(() => { void loadAll() const handleUpdated = () => { void loadAll() } window.addEventListener(SETUP_READINESS_UPDATED_EVENT, handleUpdated) return () => { window.removeEventListener(SETUP_READINESS_UPDATED_EVENT, handleUpdated) } }, [loadAll]) async function handleQuickFix( action: SetupQuickFixAction, entityId?: number, ) { const key = entityId ? `${action}:${entityId}` : action setFixingAction(key) try { const res = await applySetupQuickFix({ action, entity_id: entityId }) setReadiness(res.readiness) notifySetupReadinessUpdated() toast.success(t("setupWizard.quickFixSuccess")) const targetChannelId = Number(selectedChannelId) || res.readiness.channels.find((ch) => ch.status === 0)?.id || 0 await runSimulation(targetChannelId) } catch (error) { toast.error( error instanceof Error ? error.message : t("common.operationFailed"), ) } finally { setFixingAction(null) } } const canQuickSetupAll = useMemo(() => { return ( readiness?.steps.some((s) => s.quick_fix_actions.includes("quick_setup_all"), ) ?? false ) }, [readiness]) const canEnableMyProfile = useMemo(() => { return ( readiness?.steps.some((s) => s.quick_fix_actions.includes("enable_my_operator_profile"), ) ?? false ) }, [readiness]) const channelOptions = useMemo(() => { if (!readiness) { return [] } return readiness.channels.map((ch) => ({ value: String(ch.id), label: `${ch.name} (${ch.channel_type})`, })) }, [readiness]) if (loading && !readiness) { return (
{t("common.loadingData")}
) } if (!readiness) { return null } const progressPercent = Math.round( (readiness.ready_steps / Math.max(readiness.total_steps, 1)) * 100, ) return ( {/* Top Overview Header */}

{t("setupWizard.title")}

{readiness.can_receive_requests_now ? t("setupWizard.statusReady") : t("setupWizard.statusNeedsSetup", { ready: readiness.ready_steps, total: readiness.total_steps, })}

{t("setupWizard.description")}

{canQuickSetupAll ? ( ) : null}
{/* Progress Bar */}
{t("setupWizard.stepsProgress", { ready: readiness.ready_steps, total: readiness.total_steps, })} {progressPercent}%
{/* Current Operator Personal Diagnostic Card */}

{t("setupWizard.currentOperatorTitle")}:{" "} {readiness.current_operator.nickname || readiness.current_operator.username}

{t("setupWizard.currentOperatorTeam", { team: readiness.current_operator.team_name || t("setupWizard.currentOperatorNoTeam"), })} {t("setupWizard.currentOperatorLoad", { active: readiness.current_operator.active_conversation_count, max: readiness.current_operator.max_concurrent_count, })}
{readiness.current_operator.can_receive_now ? (

{t("setupWizard.currentOperatorReady")}

) : (

{t("setupWizard.currentOperatorBlocked")}

{readiness.current_operator.blocker_codes.map((code) => ( {t(`setupWizard.operatorBlockers.${code}`)} ))}
)}
{!readiness.current_operator.can_receive_now && canEnableMyProfile ? (
) : null}
{/* 6-Step Checklist Grid */}

{t("setupWizard.checklistSectionTitle")}

{readiness.steps.map((step) => { const primaryQuickFix = step.quick_fix_actions[0] return (

{step.step_number}.{" "} {t(`setupWizard.steps.${step.key}.title`)}

{t("setupWizard.readyCountLabel", { ready: step.ready_count, total: step.total_count, })}

{t(`setupWizard.steps.${step.key}.description`)}

{step.issues.length > 0 ? (
{step.issues.map((issue, idx) => (
{issue.entity_name ? ( [{issue.entity_name}]{" "} ) : null} {t(`setupWizard.issues.${issue.code}`)}
))}
) : null}
{step.key !== "end_to_end" ? ( ) : null} {primaryQuickFix ? ( ) : null}
) })}
{/* Interactive Route Simulator */}

{t("setupWizard.simulator.title")}

{t("setupWizard.simulator.description")}

{channelOptions.length > 0 ? ( { setSelectedChannelId(val) void runSimulation(Number(val)) }} placeholder={t("setupWizard.simulator.selectChannelPlaceholder")} triggerClassName="w-64 rounded-md" /> ) : null}
{simulation ? (
{/* Outcome Banner */}
{simulation.will_reach_operator ? ( ) : ( )} {simulation.will_reach_operator ? t("setupWizard.simulator.outcomeSuccess", { operator: simulation.matched_operator?.display_name ?? "", }) : t("setupWizard.simulator.outcomeBlocked")}
{t( `setupWizard.simulator.outcomes.${simulation.final_outcome_code}`, )}
{/* 5-Hop Visual Trace Pipeline */}
{simulation.hops.map((hop, idx) => (
{idx + 1}.{" "} {t(`setupWizard.simulator.hops.${hop.hop_key}`)}
{hop.entity_name ? (

{hop.entity_name}

) : null}

{t(`setupWizard.simulator.hopReasons.${hop.reason_code}`)}

{hop.quick_fix_action && hop.status !== "ok" ? ( ) : null}
))}
{/* Candidate Operators Evaluation Table */} {simulation.candidate_operators.length > 0 ? (

{t("setupWizard.simulator.candidateTableTitle")}

{t("setupWizard.simulator.colOperator")} {t("setupWizard.simulator.colTeam")} {t("setupWizard.simulator.colStatus")} {t("setupWizard.simulator.colAutoAssign")} {t("setupWizard.simulator.colLoad")} {t("setupWizard.simulator.colResult")} {simulation.candidate_operators.map((cand) => ( {cand.display_name} {cand.team_name || t("setupWizard.currentOperatorNoTeam")} {cand.service_status === 0 ? t("setupWizard.simulator.statusIdle") : t("setupWizard.simulator.statusBusy")} {cand.auto_assign_enabled ? t("common.enabled") : t("common.disabled")} {cand.active_count} / {cand.max_concurrent_count} {cand.eligible ? ( {t("setupWizard.simulator.eligibleBadge")} ) : ( {t( `setupWizard.simulator.skipReasons.${cand.skip_reason_code}`, )} )} ))}
) : null}
) : null}
) } export { ArrowRightIcon }