<script setup lang="ts">
import { ref, computed, onMounted, onUnmounted, watch, reactive } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import {
    Card,
    Typography,
    Button,
    Spin,
    Select,
    Form,
    Input,
    Switch,
    Divider,
    message,
    Empty,
    Steps,
    Tag,
    Popconfirm,
} from 'ant-design-vue'
import { CheckCircleOutlined, CloseCircleOutlined } from '@ant-design/icons-vue'
import { apiClient, API, isAxiosError } from '../router/api'
import { useOnboardingAgentStore } from '../stores/onboardingAgentStore'
import { useUserStore } from '../stores/userStore'
import type {
    OnboardingFlow,
    OnboardingPage,
    OnboardingSession,
    OnboardingFlowSummary,
} from '../types/onboarding'

import { Marked } from 'marked'
import DOMPurify from 'dompurify'

const marked = new Marked()
const route = useRoute()
const router = useRouter()
const agentStore = useOnboardingAgentStore()
const userStore = useUserStore()

const roleId = computed(() => route.params.roleId as string)
const flowDetails = ref<OnboardingFlow | null>(null)
const session = ref<OnboardingSession | null>(null)
const currentPageIndex = ref(0)
const loading = ref(false)
const isAutoGenerating = ref(false)
const generationHandled = ref(false)
const deletingFlow = ref(false)
const visitedPageUuids = ref<string[]>([])
type QuizGradingDetail = {
    key?: string
    correct?: boolean | string | number
    reason?: string
}

type QuizResult = {
    score_percentage: number
    pass_mark: number
    correct_count: number
    gradable_count: number
    missing_required_keys?: string[]
    grading_details?: QuizGradingDetail[]
}

const quizResult = ref<QuizResult | null>(null)
const kaQuestion = ref('')
const kaLoading = ref(false)
const kaMode = ref<'separate' | 'update_page'>('separate')
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const formState = reactive<Record<string, any>>({})

const pages = computed<OnboardingPage[]>(() => flowDetails.value?.pages ?? [])
const currentPage = computed<OnboardingPage | null>(
    () => pages.value[currentPageIndex.value] || null,
)
const hasNext = computed(() => currentPageIndex.value < pages.value.length - 1)
const hasPrev = computed(() => currentPageIndex.value > 0)
const isError = computed(() => agentStore.executionStatus === 'failed')
const canDeleteFlow = computed(() => Boolean(userStore.isGeneralManager))

const completedModules = computed<string[]>(() => {
    const state = (session.value as unknown as { state?: Record<string, unknown> } | null)?.state
    const raw = state?.completed_modules
    return Array.isArray(raw) ? raw.map((item) => String(item)) : []
})

const pageHelpByPage = computed<
    Record<string, Array<{ question: string; answer: string; timestamp: string }>>
>(() => {
    const state = (session.value as unknown as { state?: Record<string, unknown> } | null)?.state
    const raw = state?.page_help
    return raw && typeof raw === 'object'
        ? (raw as Record<string, Array<{ question: string; answer: string; timestamp: string }>>)
        : {}
})

const currentPageHelp = computed(() => {
    if (!currentPage.value) return []
    return pageHelpByPage.value[currentPage.value.uuid] || []
})

const currentPageBody = computed(() => {
    const baseBody = currentPage.value?.body || ''
    const sessionState = (session.value as unknown as { state?: Record<string, unknown> } | null)?.state
    const overridesRaw = sessionState?.page_overrides
    if (!currentPage.value || !overridesRaw || typeof overridesRaw !== 'object') {
        return baseBody
    }

    const override = (overridesRaw as Record<string, unknown>)[currentPage.value.uuid]
    return typeof override === 'string' && override.trim() ? override : baseBody
})

const renderedBody = computed(() => {
    if (!currentPageBody.value) return ''
    return DOMPurify.sanitize(marked.parse(currentPageBody.value) as string)
})

const isAnswerCorrect = (value: unknown) => {
    if (typeof value === 'boolean') return value
    if (typeof value === 'number') return value === 1
    if (typeof value === 'string') return value.trim().toLowerCase() === 'true'
    return false
}

const quizQuestionResults = computed(() => {
    const details = quizResult.value?.grading_details ?? []
    return details.map((detail, index) => {
        const key = String(detail.key || `question_${index + 1}`)
        const field = currentPage.value?.fields?.find((candidate) => candidate.key === key)
        return {
            key,
            label: field?.label || key,
            correct: isAnswerCorrect(detail.correct),
            reason: typeof detail.reason === 'string' ? detail.reason : '',
        }
    })
})

const quizQuestionResultByKey = computed(() => {
    const byKey: Record<string, { correct: boolean; reason: string }> = {}
    quizQuestionResults.value.forEach((item) => {
        byKey[item.key] = { correct: item.correct, reason: item.reason }
    })
    return byKey
})

const getFieldMarking = (fieldKey: string) => {
    return quizQuestionResultByKey.value[fieldKey] ?? null
}

const getFlowRoleUuid = (flowData: OnboardingFlowSummary): string | undefined => {
    if (typeof flowData.role === 'string') return flowData.role
    return flowData.role?.uuid
}

const getPageIndexByUuid = (pageUuid?: string | null): number => {
    if (!pageUuid) return -1
    return pages.value.findIndex((page) => String(page.uuid) === String(pageUuid))
}

const restorePageProgressFromSession = () => {
    const sessionState = (session.value as unknown as { state?: Record<string, unknown> } | null)?.state

    const visitedRaw = sessionState?.visited_pages
    visitedPageUuids.value = Array.isArray(visitedRaw)
        ? visitedRaw.map((uuid) => String(uuid)).filter((uuid) => getPageIndexByUuid(uuid) >= 0)
        : []

    const lastPageIndex = getPageIndexByUuid(
        typeof sessionState?.last_page_uuid === 'string' ? sessionState.last_page_uuid : undefined,
    )

    const visitedMaxIndex = Array.isArray(visitedRaw)
        ? visitedRaw.reduce((maxIndex, pageUuid) => {
              const pageIndex = getPageIndexByUuid(String(pageUuid))
              return pageIndex > maxIndex ? pageIndex : maxIndex
          }, -1)
        : -1

    const completedModulesRaw = sessionState?.completed_modules
    const completedMaxIndex = Array.isArray(completedModulesRaw)
        ? completedModulesRaw.reduce((maxIndex, pageUuid) => {
              const pageIndex = getPageIndexByUuid(String(pageUuid))
              return pageIndex > maxIndex ? pageIndex : maxIndex
          }, -1)
        : -1

    const inferredInProgressIndex =
        completedMaxIndex >= 0 && completedMaxIndex < pages.value.length - 1
            ? completedMaxIndex + 1
            : completedMaxIndex

    const responsesRaw = sessionState?.responses
    const responseMaxIndex = responsesRaw && typeof responsesRaw === 'object'
        ? Object.keys(responsesRaw as Record<string, unknown>).reduce((maxIndex, pageUuid) => {
              const pageIndex = getPageIndexByUuid(String(pageUuid))
              return pageIndex > maxIndex ? pageIndex : maxIndex
          }, -1)
        : -1

    const resumeIndex = Math.max(
        0,
        lastPageIndex,
        visitedMaxIndex,
        responseMaxIndex,
        completedMaxIndex,
        inferredInProgressIndex,
    )

    if (pages.value.length === 0) {
        currentPageIndex.value = 0
        return
    }

    currentPageIndex.value = Math.min(resumeIndex, pages.value.length - 1)
}

const retryGeneration = async () => {
    loading.value = true
    generationHandled.value = false

    try {
        const response = await apiClient.get<OnboardingFlow[]>(API.onboarding.flows.list(), {
            params: { role_uuid: roleId.value },
        })

        if (response.data && response.data.length > 0) {
            for (const flow of response.data) {
                await apiClient.delete(API.onboarding.flows.byId(flow.uuid))
            }
        }

        agentStore.clearLog()
        agentStore.executionStatus = 'idle'

        await startAgenticGeneration()
    } catch {
        message.error('Failed to reset generation')
    } finally {
        loading.value = false
    }
}

const resetCurrentFlow = async () => {
    if (!flowDetails.value || deletingFlow.value) return
    if (!canDeleteFlow.value) {
        message.error('Only managers can delete onboarding flows.')
        return
    }

    deletingFlow.value = true
    try {
        await apiClient.delete(API.onboarding.flows.byId(flowDetails.value.uuid))

        flowDetails.value = null
        session.value = null
        currentPageIndex.value = 0
        visitedPageUuids.value = []
        quizResult.value = null
        Object.keys(formState).forEach((k) => delete formState[k])

        generationHandled.value = false
        isAutoGenerating.value = false
        agentStore.disconnect()
        agentStore.clearLog()

        message.success('Onboarding flow deleted. Generating a fresh flow...')
        await initOnboarding()
    } catch {
        message.error('Failed to delete onboarding flow')
    } finally {
        deletingFlow.value = false
    }
}

const initOnboarding = async () => {
    if (loading.value) return
    loading.value = true
    try {
        const response = await apiClient.get<OnboardingFlow[]>(API.onboarding.flows.list(), {
            params: { role_uuid: roleId.value },
        })

        if (response.data && response.data.length > 0) {
            const matchingFlow = response.data.find((item) => getFlowRoleUuid(item) === roleId.value)
            if (!matchingFlow) {
                flowDetails.value = null
                session.value = null
                visitedPageUuids.value = []
                return
            }

            flowDetails.value = matchingFlow

            await loadFlow(matchingFlow.uuid)
        } else {
            if (!generationHandled.value) {
                await startAgenticGeneration()
            }
        }
    } catch {
        message.error('Could not load onboarding context')
    } finally {
        loading.value = false
    }
}

const startAgenticGeneration = async () => {
    isAutoGenerating.value = true
    generationHandled.value = false
    agentStore.clearLog()
    agentStore.connect(roleId.value)

    const checkInterval = setInterval(() => {
        if (agentStore.isConnected && agentStore.socket) {
            agentStore.socket.send(
                JSON.stringify({
                    action: 'start_full_onboarding',
                    role_uuid: roleId.value,
                }),
            )
            clearInterval(checkInterval)
        }
    }, 500)
}

watch(
    () => agentStore.executionStatus,
    async (status) => {
        if (status === 'completed' && isAutoGenerating.value && !generationHandled.value) {
            generationHandled.value = true
            message.success('AI Generation Complete!')

            setTimeout(async () => {
                isAutoGenerating.value = false
                agentStore.disconnect()
                await initOnboarding()
            }, 1500)
        }
    },
)

watch(
    () => roleId.value,
    async () => {
        flowDetails.value = null
        session.value = null
        currentPageIndex.value = 0
        visitedPageUuids.value = []
        quizResult.value = null
        generationHandled.value = false
        isAutoGenerating.value = false
        Object.keys(formState).forEach((k) => delete formState[k])
        agentStore.disconnect()
        agentStore.clearLog()
        await initOnboarding()
    },
)

const loadFlow = async (flowUuid: string) => {
    const response = await apiClient.get<OnboardingFlow>(API.onboarding.flows.byId(flowUuid))
    flowDetails.value = response.data
    const sessionRes = await apiClient.post<OnboardingSession>(
        API.onboarding.flows.startSession(flowUuid),
    )
    session.value = sessionRes.data

    if (session.value?.status === 'completed') {
        message.info('You have already completed this onboarding.')
        return
    }

    restorePageProgressFromSession()
    syncVisitedPages()
    hydrateFormState()
    await persistCurrentPageVisit()
}

const hydrateFormState = () => {
    if (!currentPage.value) return

    const sessionState = (session.value as unknown as { state?: Record<string, unknown> } | null)?.state
    const storedResponsesRaw = sessionState?.responses
    const pageStoredResponses =
        storedResponsesRaw &&
        typeof storedResponsesRaw === 'object' &&
        currentPage.value.uuid in (storedResponsesRaw as Record<string, unknown>)
            ? ((storedResponsesRaw as Record<string, unknown>)[
                  currentPage.value.uuid
              ] as Record<string, unknown>)
            : {}

    Object.keys(formState).forEach((k) => delete formState[k])
    currentPage.value.fields?.forEach((f) => {
        if (pageStoredResponses && f.key in pageStoredResponses) {
            formState[f.key] = pageStoredResponses[f.key]
            return
        }
        formState[f.key] = f.default_value ?? ''
    })
}

const buildCurrentResponses = () => {
    const response: Record<string, unknown> = {}
    currentPage.value?.fields?.forEach((field) => {
        response[field.key] = formState[field.key]
    })
    return response
}

const syncVisitedPages = () => {
    const nextVisited = new Set<string>(visitedPageUuids.value)

    const sessionState = (session.value as unknown as { state?: Record<string, unknown> } | null)?.state
    const visitedRaw = sessionState?.visited_pages
    if (Array.isArray(visitedRaw)) {
        visitedRaw.forEach((pageUuid) => {
            nextVisited.add(String(pageUuid))
        })
    }

    completedModules.value.forEach((pageUuid) => {
        nextVisited.add(String(pageUuid))
    })

    const storedResponsesRaw = sessionState?.responses
    if (storedResponsesRaw && typeof storedResponsesRaw === 'object') {
        Object.keys(storedResponsesRaw as Record<string, unknown>).forEach((pageUuid) => {
            nextVisited.add(String(pageUuid))
        })
    }

    const currentUuid = currentPage.value?.uuid
    if (currentUuid) {
        nextVisited.add(String(currentUuid))
    }

    visitedPageUuids.value = Array.from(nextVisited)
}

const persistCurrentPageVisit = async () => {
    if (!session.value || !currentPage.value || session.value.status === 'completed') return

    try {
        const response = await apiClient.post<{
            status: string
            session_state?: Record<string, unknown>
        }>(API.onboarding.sessions.interact(session.value.uuid), {
            page_uuid: currentPage.value.uuid,
        })

        const apiSessionState = response.data?.session_state
        if (apiSessionState && session.value) {
            ;(session.value as unknown as { state?: Record<string, unknown> }).state = apiSessionState
            syncVisitedPages()
        }
    } catch {
        // Avoid noisy errors for background navigation sync attempts.
    }
}

const getPageStatus = (page: OnboardingPage, index: number) => {
    if (completedModules.value.includes(page.uuid)) return 'Completed'
    if (index === currentPageIndex.value) return 'In Progress'
    if (visitedPageUuids.value.includes(page.uuid)) return 'In Progress'
    return 'Not Started'
}

const getPageStatusColor = (page: OnboardingPage, index: number) => {
    const status = getPageStatus(page, index)
    if (status === 'Completed') return 'green'
    if (status === 'In Progress') return 'blue'
    return 'default'
}

const canNavigateToPage = (targetIndex: number) => {
    if (targetIndex <= currentPageIndex.value) return true
    for (let index = 0; index < targetIndex; index += 1) {
        const previousPage = pages.value[index]
        if (!previousPage) return false
        if (!completedModules.value.includes(previousPage.uuid)) return false
    }
    return true
}

const jumpToPage = (index: number) => {
    if (!canNavigateToPage(index)) {
        message.warning('Complete required attempts on earlier modules first.')
        return
    }
    currentPageIndex.value = index
    window.scrollTo(0, 0)
}

const goBackPage = () => {
    if (!hasPrev.value) return
    currentPageIndex.value -= 1
    window.scrollTo(0, 0)
}

const onSubmitPage = async () => {
    if (!currentPage.value || !session.value) return

    try {
        const response = await apiClient.post<{
            status: string
            session_state?: Record<string, unknown>
        }>(API.onboarding.sessions.interact(session.value.uuid), {
            page_uuid: currentPage.value.uuid,
            responses: buildCurrentResponses(),
        })

        const apiSessionState = response.data?.session_state
        if (apiSessionState && session.value) {
            ;(session.value as unknown as { state?: Record<string, unknown> }).state = apiSessionState
        }

        syncVisitedPages()

        quizResult.value = null

        if (hasNext.value) {
            currentPageIndex.value++
            window.scrollTo(0, 0)
            return
        }

        const completeResponse = await apiClient.post<{
            message: string
            quiz_result?: QuizResult
        }>(API.onboarding.sessions.complete(session.value.uuid))

        if (completeResponse.data?.quiz_result) {
            quizResult.value = completeResponse.data.quiz_result
        }

        message.success('Onboarding Finished!')
        router.push('/organization')
    } catch (error: unknown) {
        if (isAxiosError<{ error?: string; quiz_result?: QuizResult }>(error)) {
            const data = error.response?.data
            if (data?.quiz_result) {
                quizResult.value = data.quiz_result
                message.error(
                    `${data.error || 'Final quiz not passed.'} Score: ${data.quiz_result.score_percentage}% (required ${data.quiz_result.pass_mark}%).`,
                )
                return
            }
        }
        message.error('Failed to save progress')
    }
}

const askKnowledgeAgent = async () => {
    if (!session.value || !currentPage.value || !kaQuestion.value.trim()) return

    kaLoading.value = true
    try {
        const response = await apiClient.post<{
            status: string
            answer: string
            updated_page: boolean
            revised_page_body?: string | null
            session_state?: Record<string, unknown>
        }>(API.onboarding.sessions.askKa(session.value.uuid), {
            page_uuid: currentPage.value.uuid,
            message: kaQuestion.value,
            mode: kaMode.value,
        })

        const apiSessionState = response.data?.session_state
        if (apiSessionState && session.value) {
            ;(session.value as unknown as { state?: Record<string, unknown> }).state = apiSessionState
        }

        syncVisitedPages()
        kaQuestion.value = ''
    } catch {
        message.error('Could not retrieve clarification right now')
    } finally {
        kaLoading.value = false
    }
}

onMounted(() => initOnboarding())
onUnmounted(() => agentStore.disconnect())

watch(
    () => currentPageIndex.value,
    async () => {
        kaQuestion.value = ''
        syncVisitedPages()
        hydrateFormState()
        await persistCurrentPageVisit()
    },
)
</script>

<template>
    <div class="page-container">
        <Spin :spinning="loading" tip="Loading...">
            <Card v-if="isAutoGenerating" class="dark-panel pipeline-card">
                <template #title>
                    <div class="pipeline-header">
                        <Spin size="small" />
                        <span class="pulse white-text">AI is Architecting your Onboarding...</span>
                    </div>
                </template>

                <div class="orchestrator-logs">
                    <div v-for="(log, i) in agentStore.eventLog" :key="i" class="log-entry">
                        <Tag :color="log.type.includes('tool') ? 'green' : 'blue'" class="log-tag">
                            {{ log.type.toUpperCase() }}
                        </Tag>
                        <span class="log-time">
                            {{ new Date(log.timestamp).toLocaleTimeString() }}
                        </span>
                        <div class="log-msg white-text">{{ log.message }}</div>
                    </div>
                    <Empty
                        v-if="!agentStore.eventLog.length"
                        description="Initializing Pipeline..."
                    />
                </div>

                <div v-if="isError" class="error-retry-zone">
                    <Typography.Text type="danger" class="error-text">
                        The Agentic Pipeline encountered an issue. This could be due to a GPU
                        timeout or a RAG retrieval error.
                    </Typography.Text>
                    <Button type="primary" danger @click="retryGeneration">Retry Generation</Button>
                </div>

                <div class="pipeline-status">
                    <Steps size="small" :current="agentStore.executionStatus === 'running' ? 1 : 2">
                        <Steps.Step title="Curriculum" />
                        <Steps.Step title="Knowledge" />
                        <Steps.Step title="Assessment" />
                    </Steps>
                </div>
            </Card>

            <template v-else-if="flowDetails">
                <Card v-if="session?.status === 'completed'" class="dark-panel content-card">
                    <div class="completed-card">
                    <Typography.Title :level="3" class="white-text">
                        Onboarding Already Completed
                    </Typography.Title>
                    <Typography.Paragraph class="white-text" style="opacity: 0.8">
                        You have already completed this onboarding flow. You can return to your
                        organization page and wait for your manager to review your onboarding results.
                    </Typography.Paragraph>

                    <div class="completed-actions">
                        <Button @click="router.push('/organization')">
                            Return to Organization
                        </Button>
                        <Popconfirm
                            v-if="canDeleteFlow"
                            title="Delete this onboarding flow and regenerate it?"
                            ok-text="Delete"
                            cancel-text="Cancel"
                            @confirm="resetCurrentFlow"
                        >
                            <Button danger :loading="deletingFlow">
                                Delete Flow
                            </Button>
                        </Popconfirm>
                    </div>
                    </div>
                </Card>

                <div v-else class="flow-shell">
                    <Card class="dark-panel toc-card">
                        <aside>
                            <Typography.Title :level="5" class="white-text toc-title">
                                Contents
                            </Typography.Title>
                            <div class="toc-list">
                                <button
                                    v-for="(page, index) in pages"
                                    :key="page.uuid"
                                    type="button"
                                    class="toc-item"
                                    :class="{
                                        active: index === currentPageIndex,
                                        blocked: !canNavigateToPage(index),
                                    }"
                                    @click="jumpToPage(index)"
                                >
                                    <span class="toc-index">{{ index + 1 }}</span>
                                    <span class="toc-text">{{ page.title }}</span>
                                    <Tag :color="getPageStatusColor(page, index)">
                                        {{ getPageStatus(page, index) }}
                                    </Tag>
                                </button>
                            </div>
                        </aside>
                    </Card>

                    <Card class="dark-panel content-card main-content-card">
                        <div class="flow-header-row">
                            <Typography.Title :level="2" class="white-text flow-title">
                                {{ flowDetails.title }}
                            </Typography.Title>
                            <Popconfirm
                                v-if="canDeleteFlow"
                                title="Delete this onboarding flow and regenerate it?"
                                ok-text="Delete"
                                cancel-text="Cancel"
                                @confirm="resetCurrentFlow"
                            >
                                <Button danger :loading="deletingFlow">
                                    Delete Flow
                                </Button>
                            </Popconfirm>
                        </div>
                        <Typography.Paragraph class="white-text" style="opacity: 0.8">
                            {{ flowDetails.description }}
                        </Typography.Paragraph>
                        <Divider style="border-color: #dbe3ec" />

                        <section class="flow-content" v-if="currentPage">
                            <Typography.Title :level="4" class="white-text">
                                {{ currentPage.title }}
                            </Typography.Title>
                            <div class="markdown-body" v-html="renderedBody"></div>
                            <Divider dashed style="border-color: #dbe3ec" />

                            <Form layout="vertical" :model="formState" @finish="onSubmitPage">
                                <Form.Item
                                    v-for="(field, fieldIndex) in currentPage.fields"
                                    :key="field.uuid"
                                    class="white-label"
                                >
                                    <template #label>
                                        <span class="field-label-inline">
                                            <span>{{ `${fieldIndex + 1}. ${field.label}` }}</span>
                                            <span
                                                v-if="getFieldMarking(field.key)"
                                                class="field-marking-inline"
                                            >
                                                <CheckCircleOutlined
                                                    v-if="getFieldMarking(field.key)?.correct"
                                                    class="answer-icon correct"
                                                />
                                                <CloseCircleOutlined
                                                    v-else
                                                    class="answer-icon incorrect"
                                                />
                                                <Tag
                                                    :color="
                                                        getFieldMarking(field.key)?.correct
                                                            ? 'green'
                                                            : 'red'
                                                    "
                                                >
                                                    {{
                                                        getFieldMarking(field.key)?.correct
                                                            ? 'Correct'
                                                            : 'Incorrect'
                                                    }}
                                                </Tag>
                                            </span>
                                        </span>
                                    </template>

                                    <Input
                                        v-if="field.field_type === 'text'"
                                        v-model:value="formState[field.key]"
                                    />
                                    <Input.TextArea
                                        v-else-if="field.field_type === 'textarea'"
                                        v-model:value="formState[field.key]"
                                    />
                                    <Select
                                        v-else-if="field.field_type === 'select'"
                                        v-model:value="formState[field.key]"
                                        :options="
                                            field.options?.map((o) => ({
                                                label: String(o),
                                                value: String(o),
                                            }))
                                        "
                                    />
                                    <Switch
                                        v-else-if="field.field_type === 'boolean'"
                                        v-model:checked="formState[field.key]"
                                    />

                                    <Typography.Text
                                        v-if="
                                            getFieldMarking(field.key) &&
                                            !getFieldMarking(field.key)?.correct &&
                                            getFieldMarking(field.key)?.reason
                                        "
                                        class="field-marking-reason"
                                    >
                                        {{ getFieldMarking(field.key)?.reason }}
                                    </Typography.Text>
                                </Form.Item>

                                <div class="form-actions">
                                    <Button :disabled="!hasPrev" @click="goBackPage">
                                        Back
                                    </Button>
                                    <Button type="primary" html-type="submit" size="large">
                                        {{ hasNext ? 'Next Module' : 'Submit Quiz & Complete' }}
                                    </Button>
                                </div>

                                <div v-if="quizResult && !hasNext" class="feedback-box">
                                    <Typography.Title :level="5" class="white-text">
                                        Final Quiz Result
                                    </Typography.Title>
                                    <Typography.Paragraph
                                        class="white-text"
                                        style="opacity: 0.8"
                                    >
                                        Score: {{ quizResult.score_percentage }}% | Pass mark:
                                        {{ quizResult.pass_mark }}% | Correct:
                                        {{ quizResult.correct_count }}/{{ quizResult.gradable_count }}
                                    </Typography.Paragraph>
                                    <Typography.Paragraph
                                        v-if="quizResult.missing_required_keys?.length"
                                        class="white-text"
                                        style="opacity: 0.8"
                                    >
                                        Missing required answers:
                                        {{ quizResult.missing_required_keys.join(', ') }}
                                    </Typography.Paragraph>

                                </div>

                                <template v-if="hasNext">
                                    <Divider dashed style="border-color: #dbe3ec" />

                                    <div class="ka-help-box">
                                        <Typography.Title
                                            :level="5"
                                            class="white-text"
                                            style="margin-bottom: 8px"
                                        >
                                            Need clarification?
                                        </Typography.Title>
                                        <Typography.Paragraph class="white-text" style="opacity: 0.8">
                                            Ask the Knowledge Agent to explain this page or refine the page content.
                                        </Typography.Paragraph>
                                        <Input.TextArea
                                            v-model:value="kaQuestion"
                                            :auto-size="{ minRows: 2, maxRows: 5 }"
                                            placeholder="Ask what you don’t understand about this module..."
                                        />
                                        <div class="ka-actions">
                                            <Select
                                                v-model:value="kaMode"
                                                :options="[
                                                    {
                                                        label: 'Show separate answer below (will not save)',
                                                        value: 'separate',
                                                    },
                                                    {
                                                        label: 'Update current page content',
                                                        value: 'update_page',
                                                    },
                                                ]"
                                                style="min-width: 280px"
                                            />
                                            <Button
                                                type="default"
                                                :loading="kaLoading"
                                                :disabled="!kaQuestion.trim()"
                                                @click="askKnowledgeAgent"
                                            >
                                                Ask KA
                                            </Button>
                                        </div>

                                        <div v-if="currentPageHelp.length" class="ka-thread">
                                            <div
                                                v-for="(entry, idx) in currentPageHelp"
                                                :key="`${entry.timestamp}-${idx}`"
                                                class="ka-thread-item"
                                            >
                                                <Typography.Text class="white-text" strong>
                                                    You:
                                                </Typography.Text>
                                                <Typography.Paragraph
                                                    class="white-text"
                                                    style="opacity: 0.9; margin-bottom: 6px"
                                                >
                                                    {{ entry.question }}
                                                </Typography.Paragraph>
                                                <Typography.Text class="white-text" strong>
                                                    KA:
                                                </Typography.Text>
                                                <div
                                                    class="markdown-body"
                                                    v-html="DOMPurify.sanitize(marked.parse(entry.answer) as string)"
                                                ></div>
                                            </div>
                                        </div>
                                    </div>
                                </template>

                            </Form>
                        </section>
                    </Card>
                </div>
            </template>

            <Empty v-else-if="!loading" description="Role Context Missing" />
        </Spin>
    </div>
</template>

<style scoped>
.page-container {
    max-width: 1280px;
    margin: 2rem auto;
    padding: 0 1rem;
}
.dark-panel {
    background: #ffffff;
    border: 1px solid #dbe3ec;
    color: #1f2937;
}
.pipeline-header {
    display: flex;
    align-items: center;
    gap: 1rem;
}
.flow-header-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
}
.flow-title {
    margin: 0 !important;
}
.completed-card {
    padding: 0.5rem 0;
}
.completed-actions {
    display: flex;
    gap: 0.75rem;
    margin-top: 1rem;
}

.flow-shell {
    display: grid;
    grid-template-columns: 280px minmax(0, 1fr);
    gap: 1rem;
    align-items: start;
}

.toc-card {
    position: sticky;
    top: 1rem;
    align-self: start;
}

.main-content-card {
    width: min(900px, 100%);
    justify-self: center;
}

.toc-title {
    margin-bottom: 0.75rem !important;
}

.toc-list {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.toc-item {
    width: 100%;
    display: flex;
    align-items: center;
    gap: 0.6rem;
    background: #f8fafc;
    border: 1px solid #dbe3ec;
    border-radius: 8px;
    color: #1f2937;
    padding: 0.5rem 0.6rem;
    cursor: pointer;
    text-align: left;
}

.toc-item.active {
    border-color: #2563eb;
}

.toc-item.blocked {
    opacity: 0.7;
}

.toc-index {
    min-width: 1.5rem;
    font-weight: 600;
}

.toc-text {
    flex: 1;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.flow-content {
    min-width: 0;
}

.white-text {
    color: #1f2937 !important;
}
.white-label :deep(.ant-form-item-label > label) {
    color: #1f2937 !important;
}

.orchestrator-logs {
    background: #f8fafc;
    padding: 1.2rem;
    border-radius: 8px;
    height: 300px;
    overflow-y: auto;
    font-family: monospace;
    border: 1px solid #dbe3ec;
    display: flex;
    flex-direction: column-reverse;
    margin-bottom: 1rem;
}

.log-entry {
    margin-bottom: 0.8rem;
    padding-bottom: 0.5rem;
    border-bottom: 1px solid #dbe3ec;
}
.log-msg {
    margin-top: 4px;
}
.markdown-body {
    line-height: 1.7;
    color: #1f2937;
}
.markdown-body :deep(h1),
.markdown-body :deep(h2),
.markdown-body :deep(h3),
.markdown-body :deep(h4) {
    color: #1f2937;
    margin-top: 1rem;
}
.markdown-body :deep(p),
.markdown-body :deep(li) {
    color: #374151;
}

.error-retry-zone {
    margin-bottom: 1.5rem;
    padding: 1.5rem;
    background: rgba(255, 77, 79, 0.15);
    border: 1px solid #ff4d4f;
    border-radius: 8px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
    position: relative;
    z-index: 10;
}

.error-text {
    color: #ff7875 !important;
    text-align: center;
    font-weight: 500;
}
.form-actions {
    display: flex;
    justify-content: space-between;
    margin-top: 2rem;
}

.feedback-box {
    margin-top: 1rem;
    padding: 1rem;
    border: 1px solid #dbe3ec;
    border-radius: 8px;
    background: #f8fafc;
}

.field-label-inline {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
}

.field-marking-inline {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
}

.field-marking-reason {
    display: block;
    margin-top: 0.4rem;
    color: #4b5563;
}

.answer-icon {
    font-size: 1rem;
}

.answer-icon.correct {
    color: #16a34a;
}

.answer-icon.incorrect {
    color: #dc2626;
}

.ka-help-box {
    margin-top: 1rem;
    padding: 1rem;
    border: 1px solid #dbe3ec;
    border-radius: 8px;
    background: #f8fafc;
}

.ka-actions {
    margin-top: 0.75rem;
    display: flex;
    gap: 0.75rem;
    align-items: center;
    flex-wrap: wrap;
}

.ka-thread {
    margin-top: 1rem;
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.ka-thread-item {
    border: 1px solid #dbe3ec;
    border-radius: 8px;
    padding: 0.75rem;
    background: #ffffff;
}
.pulse {
    animation: pulse 2s infinite;
}
@keyframes pulse {
    0%,
    100% {
        opacity: 1;
    }
    50% {
        opacity: 0.5;
    }
}

:deep(.ant-steps-item-title),
:deep(.ant-steps-item-description) {
    color: #6b7280 !important;
}
:deep(.ant-steps-item-active .ant-steps-item-title) {
    color: #1f2937 !important;
}

@media (max-width: 992px) {
    .flow-shell {
        grid-template-columns: 1fr;
    }

    .toc-card {
        position: static;
    }
}
</style>
