/**
 * Session Migration - Handles importing sessions when switching between SDK and Native modes
 * 
 * This module caches SDK session data to localStorage so it can be imported to Native mode
 * when the user switches modes.
 */

import { nativeSessionApi } from "../lib/lite-mode"
import { sessions } from "./session-state"
import { getLogger } from "../lib/logger"
import type { Session } from "../types/session"

const log = getLogger("session-migration")

// LocalStorage key prefix for cached SDK sessions
const SDK_SESSION_CACHE_PREFIX = "nomadarch_sdk_sessions_"

// Track which workspaces have already been migrated to prevent duplicate migrations
const migratedWorkspaces = new Set<string>()

export interface CachedSession {
    id: string
    title?: string
    parentId?: string | null
    createdAt?: number
    updatedAt?: number
    model?: { providerId: string; modelId: string }
    agent?: string
}

export interface MigrationResult {
    success: boolean
    imported: number
    skipped: number
    error?: string
}

/**
 * Cache SDK sessions to localStorage for later migration
 * This should be called whenever sessions are fetched in SDK mode
 */
export function cacheSDKSessions(workspaceId: string, sessionList: Session[]): void {
    if (sessionList.length === 0) return

    try {
        const cached: CachedSession[] = sessionList.map(s => ({
            id: s.id,
            title: s.title,
            parentId: s.parentId,
            createdAt: s.time?.created,
            updatedAt: s.time?.updated,
            model: s.model,
            agent: s.agent
        }))

        const key = SDK_SESSION_CACHE_PREFIX + workspaceId
        localStorage.setItem(key, JSON.stringify(cached))
        log.info({ workspaceId, count: cached.length }, "Cached SDK sessions for migration")
    } catch (error) {
        log.error({ workspaceId, error }, "Failed to cache SDK sessions")
    }
}

/**
 * Get cached SDK sessions from localStorage
 */
export function getCachedSDKSessions(workspaceId: string): CachedSession[] {
    try {
        const key = SDK_SESSION_CACHE_PREFIX + workspaceId
        const cached = localStorage.getItem(key)
        if (!cached) return []

        const sessions = JSON.parse(cached) as CachedSession[]
        log.info({ workspaceId, count: sessions.length }, "Retrieved cached SDK sessions")
        return sessions
    } catch (error) {
        log.error({ workspaceId, error }, "Failed to retrieve cached SDK sessions")
        return []
    }
}

/**
 * Get ALL cached sessions from localStorage across all workspace IDs
 * This is useful for migrating sessions when workspace IDs have changed
 */
export function getAllCachedSessions(): { workspaceId: string; sessions: CachedSession[] }[] {
    const results: { workspaceId: string; sessions: CachedSession[] }[] = []

    try {
        for (let i = 0; i < localStorage.length; i++) {
            const key = localStorage.key(i)
            if (key && key.startsWith(SDK_SESSION_CACHE_PREFIX)) {
                const workspaceId = key.substring(SDK_SESSION_CACHE_PREFIX.length)
                const cached = localStorage.getItem(key)
                if (cached) {
                    try {
                        const sessions = JSON.parse(cached) as CachedSession[]
                        if (sessions.length > 0) {
                            results.push({ workspaceId, sessions })
                            log.info({ workspaceId, count: sessions.length }, "Found cached sessions")
                        }
                    } catch (e) {
                        // Invalid JSON, skip
                    }
                }
            }
        }
    } catch (error) {
        log.error({ error }, "Failed to scan localStorage for cached sessions")
    }

    return results
}

/**
 * Clear cached SDK sessions after successful migration
 */
export function clearCachedSDKSessions(workspaceId: string): void {
    try {
        const key = SDK_SESSION_CACHE_PREFIX + workspaceId
        localStorage.removeItem(key)
        log.info({ workspaceId }, "Cleared cached SDK sessions")
    } catch (error) {
        log.error({ workspaceId, error }, "Failed to clear cached SDK sessions")
    }
}

/**
 * Check if a workspace needs session migration
 */
export function needsMigration(workspaceId: string): boolean {
    return !migratedWorkspaces.has(workspaceId)
}

/**
 * Mark a workspace as migrated
 */
export function markMigrated(workspaceId: string): void {
    migratedWorkspaces.add(workspaceId)
}

/**
 * Get existing SDK sessions for a workspace from the local store
 */
export function getExistingSdkSessions(instanceId: string): Session[] {
    const instanceSessions = sessions().get(instanceId)
    if (!instanceSessions) return []
    return Array.from(instanceSessions.values())
}

/**
 * Migrate sessions from SDK mode to Native mode
 * This should be called when the user switches from an SDK binary to native mode
 */
export async function migrateSessionsToNative(
    workspaceId: string,
    sdkSessions: Array<{
        id: string
        title?: string
        parentId?: string | null
        createdAt?: number
        updatedAt?: number
        time?: { created?: number; updated?: number }
        model?: { providerId: string; modelId: string }
        agent?: string
        messages?: Array<{
            id: string
            role: "user" | "assistant" | "system" | "tool"
            content?: string
            timestamp?: number
        }>
    }>
): Promise<MigrationResult> {
    if (sdkSessions.length === 0) {
        log.info({ workspaceId }, "No sessions to migrate")
        markMigrated(workspaceId)
        return { success: true, imported: 0, skipped: 0 }
    }

    try {
        log.info({ workspaceId, count: sdkSessions.length }, "Starting session migration to native mode")

        // Transform to the format expected by the native API
        const sessionsToImport = sdkSessions.map(s => ({
            id: s.id,
            title: s.title,
            parentId: s.parentId,
            createdAt: s.createdAt || s.time?.created,
            updatedAt: s.updatedAt || s.time?.updated,
            model: s.model,
            agent: s.agent,
            messages: s.messages?.map(m => ({
                id: m.id,
                role: m.role,
                content: m.content,
                createdAt: m.timestamp
            }))
        }))

        const result = await nativeSessionApi.importSessions(workspaceId, sessionsToImport)

        log.info({ workspaceId, ...result }, "Session migration completed")
        markMigrated(workspaceId)

        // Clear the cache after successful migration
        if (result.success) {
            clearCachedSDKSessions(workspaceId)
        }

        return {
            success: result.success,
            imported: result.imported,
            skipped: result.skipped
        }
    } catch (error) {
        log.error({ workspaceId, error }, "Session migration failed")
        return {
            success: false,
            imported: 0,
            skipped: 0,
            error: error instanceof Error ? error.message : String(error)
        }
    }
}

/**
 * Auto-import cached SDK sessions to native mode
 * This is the main entry point for automatic migration on startup
 */
export async function autoImportCachedSessions(workspaceId: string): Promise<MigrationResult> {
    if (!needsMigration(workspaceId)) {
        return { success: true, imported: 0, skipped: 0 }
    }

    // First, try to get cached sessions for this specific workspace ID
    let cachedSessions = getCachedSDKSessions(workspaceId)

    // If no sessions found for this workspace, check ALL cached sessions
    // This handles the case where workspace IDs changed (e.g., after the deterministic ID fix)
    if (cachedSessions.length === 0) {
        const allCached = getAllCachedSessions()
        if (allCached.length > 0) {
            log.info({ allCached: allCached.map(c => ({ id: c.workspaceId, count: c.sessions.length })) },
                "Found cached sessions from other workspace IDs, importing all")

            // Combine all cached sessions
            for (const cache of allCached) {
                cachedSessions = cachedSessions.concat(cache.sessions)
            }
        }
    }

    if (cachedSessions.length === 0) {
        // Also check in-memory sessions as a fallback
        const memorySessions = getExistingSdkSessions(workspaceId)
        if (memorySessions.length > 0) {
            const migrationData = memorySessions.map(s => ({
                id: s.id,
                title: s.title,
                parentId: s.parentId,
                time: s.time,
                model: s.model,
                agent: s.agent
            }))
            return migrateSessionsToNative(workspaceId, migrationData)
        }

        markMigrated(workspaceId)
        return { success: true, imported: 0, skipped: 0 }
    }

    return migrateSessionsToNative(workspaceId, cachedSessions)
}

/**
 * Clear migration status (for testing or when user explicitly wants to re-migrate)
 */
export function clearMigrationStatus(workspaceId: string): void {
    migratedWorkspaces.delete(workspaceId)
}

/**
 * Clear all migration statuses
 */
export function clearAllMigrationStatuses(): void {
    migratedWorkspaces.clear()
}
