<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 { apiClient, API } from '../router/api'
import { useAgentStore } from '../stores/agentStore'
import type {
    OnboardingFlow,
    OnboardingPage,
    OnboardingSession,
    OnboardingSessionSummary,
    OnboardingFlowSummary,
} from '../types/onboarding'

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

const marked = new Marked()
const route = useRoute()
const router = useRouter()
const agentStore = useAgentStore()

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)
// 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 renderedBody = computed(() => {
    if (!currentPage.value?.body) return ''
    return DOMPurify.sanitize(marked.parse(currentPage.value.body) as string)
})

const getSessionRoleUuid = (sessionData: OnboardingSessionSummary): string | undefined => {
    if (typeof sessionData.role === 'string') return sessionData.role
    return sessionData.role?.uuid
}

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

const findCompletedSessionForRole = async (): Promise<OnboardingSessionSummary | null> => {
    const sessionRes = await apiClient.get<OnboardingSessionSummary[]>(API.onboarding.sessions.list(), {
        params: { 'role__uuid': roleId.value },
    })
    return (
        sessionRes.data.find(
            (item) => item.status === 'completed' && getSessionRoleUuid(item) === roleId.value,
        ) || null
    )
}

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

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

        flowDetails.value = null
        session.value = null
        currentPageIndex.value = 0
        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
                return
            }

            flowDetails.value = matchingFlow

            const completedSession = await findCompletedSessionForRole()
            if (completedSession) {
                session.value = completedSession as unknown as OnboardingSession
                currentPageIndex.value = 0
                Object.keys(formState).forEach((k) => delete formState[k])
                return
            }

            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
        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
    }

    hydrateFormState()
}

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

const onSubmitPage = async () => {
    if (!currentPage.value || !session.value) return
    try {
        await apiClient.post(API.onboarding.sessions.interact(session.value.uuid), {
            page_uuid: currentPage.value.uuid,
            responses: formState,
        })

        if (hasNext.value) {
            currentPageIndex.value++
            hydrateFormState()
            window.scrollTo(0, 0)
        } else {
            await apiClient.post(API.onboarding.sessions.complete(session.value.uuid))
            message.success('Onboarding Finished!')
            router.push('/organization')
        }
    } catch {
        message.error('Failed to save progress')
    }
}

onMounted(() => initOnboarding())
onUnmounted(() => agentStore.disconnect())
</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>

            <Card v-else-if="flowDetails" class="dark-panel content-card">
                <div v-if="session?.status === 'completed'" 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, or delete this flow to regenerate a new one.
                    </Typography.Paragraph>

                    <div class="completed-actions">
                        <Button @click="router.push('/organization')">
                            Return to Organization
                        </Button>
                        <Popconfirm
                            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>

                <template v-else>
                    <div class="flow-header-row">
                        <Typography.Title :level="2" class="white-text flow-title">
                            {{ flowDetails.title }}
                        </Typography.Title>
                        <Popconfirm
                            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: #334155" />

                    <div 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: #334155" />

                        <Form layout="vertical" :model="formState" @finish="onSubmitPage">
                            <Form.Item
                                v-for="field in currentPage.fields"
                                :key="field.uuid"
                                :label="field.label"
                                class="white-label"
                            >
                                <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]"
                                />
                            </Form.Item>

                            <div class="form-actions">
                                <Button :disabled="!hasPrev" @click="currentPageIndex--">
                                    Back
                                </Button>
                                <Button type="primary" html-type="submit" size="large">
                                    {{ hasNext ? 'Next Module' : 'Complete Onboarding' }}
                                </Button>
                            </div>
                        </Form>
                    </div>
                </template>
            </Card>

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

<style scoped>
.page-container {
    max-width: 900px;
    margin: 2rem auto;
    padding: 0 1rem;
}
.dark-panel {
    background: #0f172a;
    border: 1px solid #1e293b;
    color: #f1f5f9;
}
.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;
}

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

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

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

.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;
}
.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: #94a3b8 !important;
}
:deep(.ant-steps-item-active .ant-steps-item-title) {
    color: #ffffff !important;
}
</style>
