import Observability from '@launchdarkly/observability'
import SessionReplay from '@launchdarkly/session-replay'
import {
    createApiConfig,
    useInitApi,
} from '@atlanhq/atlan-js/vue-common/useInitApi'
import { createHead } from '@vueuse/head'
import { LDPlugin } from 'launchdarkly-vue-client-sdk'
import { createPinia } from 'pinia'
import VueDOMPurifyHTML from 'vue-dompurify-html'
import { createApp, h } from 'vue'
import { createRouter, createWebHistory } from 'vue-router'
// eslint-disable-next-line import/no-unresolved
import { setupLayouts } from 'virtual:generated-layouts'
// eslint-disable-next-line import/no-unresolved
import generatedRoutes from 'virtual:generated-pages'
import type { UserModule } from './types'
import { createPiniaPlugin } from './api-vue/common/pinia'
import {
    AtlanApiHeraclesConfigSymbol,
    AtlanApiMetastoreConfigSymbol,
    AtlanMemoryLeakWarningSymbol,
    createApiConfig as createApiConfigOld,
    useInitApi as useInitApiOld,
} from './api-vue/common/useInitApi'
import { getApiBasePath } from './modules/__env'
import { authDirective } from './utils/directives/auth'
import { keycloakInstance } from './utils/keycloakInstance'
import { featureFlagDirective } from '~/utils/directives/feature-flags'
import { inputFocusDirective } from '~/utils/directives/input-focus'
import {
    recordLaunchDarklyErrorWithStandaloneContext,
    startLaunchDarklyObservabilityEarly,
} from '~/utils/launchdarkly'
import AppBootstrap from './AppBootstrap.vue'
import './panda.css'
import '~/styles/index.css'

// Maintianed to make the paralell migration
const apiConfigOld = createApiConfigOld({
    basePath: `${getApiBasePath()}/api`,
    accessToken: () => keycloakInstance.token,
})

// SDK instance to maintain the service config symbol
const apiConfig = createApiConfig({
    basePath: `${getApiBasePath()}/api`,
    accessToken: () => keycloakInstance.token,
})

const app = createApp({
    setup() {
        useInitApi(apiConfig)
        useInitApiOld(apiConfigOld)
    },
    render: () => h(AppBootstrap),
})

if (import.meta.env.DEV) {
    app.provide(AtlanMemoryLeakWarningSymbol, true)
}

app.provide(AtlanApiHeraclesConfigSymbol, apiConfig.heracles)
app.provide(AtlanApiMetastoreConfigSymbol, apiConfig.metastore)

// pinia
const pinia = createPinia()
pinia.use(createPiniaPlugin(apiConfigOld))
app.use(pinia)

// vue-head
const head = createHead()
app.use(head)

const routes = setupLayouts(generatedRoutes)
const router = createRouter({
    history: createWebHistory(),
    routes,
})

const LDKey = import.meta.env.VITE_LAUNCH_DARKLY_KEY ?? 'fallback' // default case is kept a string so that LD throws a error

Object.values(
    import.meta.glob<{ install: UserModule }>('./modules/*.ts', { eager: true })
).forEach((i) => i.install?.({ app, router, routes }))

app.use(LDPlugin, {
    clientSideID: LDKey,
    deferInitialization: true,
    options: {
        plugins: [
            new Observability({
                manualStart: true,
                version:
                    import.meta.env.VITE_COMMIT_SHA ||
                    import.meta.env.PACKAGE_VERSION, // For source map correlation
                networkRecording: {
                    enabled: true,
                    networkBodyKeysToRedact: [
                        'access_token',
                        'authorization',
                        'id_token',
                        'refresh_token',
                        'token',
                    ],
                    networkHeadersToRedact: [
                        'authorization',
                        'cookie',
                        'proxy-authorization',
                        'set-cookie',
                    ],
                    recordHeadersAndBody: true,
                },
                consoleMethodsToRecord: ['error'], // Only track errors
            }),
            new SessionReplay({
                manualStart: true,
                privacySetting: 'strict', // Obscures all text content
            }),
        ],
    },
})

void startLaunchDarklyObservabilityEarly()

app.config.errorHandler = (error, _instance, info) => {
    const normalizedError =
        error instanceof Error ? error : new Error(String(error))
    console.error('Vue error', normalizedError, info)
    void recordLaunchDarklyErrorWithStandaloneContext(normalizedError, {
        info: String(info),
        source: 'vue_error_handler',
    })
}

inputFocusDirective(app)
authDirective(app)
featureFlagDirective(app)

app.use(VueDOMPurifyHTML, {
    default: {
        ADD_ATTR: ['target'],
    },
})

app.use(router).mount('#app')

const loadLocalCSS = (href: string) => {
    const link = document.createElement('link')
    link.rel = 'stylesheet'
    link.href = href
    link.media = 'print'
    link.onload = () => {
        link.media = 'all'
    }
    document.head.appendChild(link)
}

const loadPackageCSS = async (cssPath: string) => {
    import(cssPath).catch((error) => {
        console.warn(`Failed to load package CSS: ${cssPath}`, error)
    })
}

requestAnimationFrame(() => {
    loadLocalCSS('/src/styles/plugins/regular-table.css')
    loadLocalCSS('/src/styles/plugins/emoji-picker.css')

    // Load package CSS files
    loadPackageCSS('vue-diff/dist/index.css')
})
