import { useEffect, useState, useRef, useCallback, useMemo } from 'react'
import { useParams, useNavigate, useSearchParams } from 'react-router-dom'
import React, { Suspense } from 'react'

const EditorPanel = React.lazy(() => import('../components/editor/EditorPanel').then(m => ({ default: m.EditorPanel })))
const EditorCollaborationPanel = React.lazy(() => import('../components/editor/EditorCollaborationPanel').then(m => ({ default: m.EditorCollaborationPanel })))
const PDFPreviewPanel = React.lazy(() => import('../components/editor/PDFPreviewPanel').then(m => ({ default: m.PDFPreviewPanel })))
const NativePdfPanelShell = React.lazy(() => import('../components/editor/NativePdfPanelShell').then(m => ({ default: m.NativePdfPanelShell })))
const ConflictResolutionModal = React.lazy(() => import('../components/ConflictResolutionModal').then(m => ({ default: m.ConflictResolutionModal })))
const ReasoningHistoryModal = React.lazy(() => import('../components/ReasoningHistoryModal').then(m => ({ default: m.ReasoningHistoryModal })))
import { useEditorStore } from '../stores/editorStore'
import { familiarosClient } from '../services/familiaros-client'
import type {
  CollaborationDocumentConflictResolution,
  CorpusCompileTaskPayload,
  CorpusIntegrityReportResponse,
  CorpusIntegritySummary,
  CorpusEntity,
  CorpusLocalHistoryTaskPayload,
  CorpusMigrationPortabilityTaskPayload,
  CorpusUvRuntimeTaskPayload,
} from '../services/familiaros-client'
import { notifications } from '../services/notifications'
import { subscribeScriptoriumCommand } from '../services/command-bus'
import { recordUxTelemetryEvent } from '../services/ux-telemetry'
const MemoryInspector = React.lazy(() => import('../components/memory/MemoryInspector').then(m => ({ default: m.MemoryInspector })))
import { Activity, FileText, GripVertical, Network, Pin, PinOff } from 'lucide-react'
const DocumentOutlinePanel = React.lazy(() => import('../components/editor/DocumentOutlinePanel').then(m => ({ default: m.DocumentOutlinePanel })))
import type { FileNode } from '../components/FileTree'
const FileTree = React.lazy(() => import('../components/FileTree').then(m => ({ default: m.FileTree })))
import {
  buildEntityPinnedMetadata,
  derivePinnedEntityIds,
  isEntityPinned,
  loadPinnedEntityIdsFromStorage,
  persistPinnedEntityIdsToStorage,
} from '../components/editor/context-scope-control'
import {
  type EditorRightPaneTab,
  type EditorWorkspaceContext,
  loadEditorWorkspaceState,
  persistEditorWorkspaceState,
} from '../utils/editor-workspace'
import {
  buildNativePdfBytesCacheKey,
  nativePdfDocumentStore,
} from '../services/native-pdf-document-store'
import {
  buildFallbackSyncTexEntries,
  resolveCompileArtifactContext,
  type CompileArtifactContext,
} from '../utils/compile-artifact-routing'
import {
  buildCrossDocumentCompareFilterPresets,
  buildCrossDocumentCompareSummary,
  buildCrossDocumentCompareLineRows,
  buildCrossDocumentCompareIssueSummary,
  filterCrossDocumentCompareLineRows,
  flattenFileTreeToCompareCandidates,
  resolveAdjacentCompareIssueLine,
  resolveCompareIssueContextAtLine,
  type CrossDocumentCompareFilterPreset,
  type CrossDocumentCompareLineRow,
  type CrossDocumentCompareLineFilterMode,
  type CrossDocumentCompareIssueKind,
  type CrossDocumentCompareCandidate,
} from '../utils/cross-document-compare'
import {
  buildEditorCompareContextParams,
  buildEditorFocusedIssueContextParams,
  buildEditorFocusedIssueRemediationParams,
  buildEditorIssueBucketContextParams,
  buildEditorIssueBucketRemediationParams,
  deriveEditorCompareIssueFilterMode,
  parseEditorCompareRouteContext,
  resolveCompareIssueRemediationRoute,
  resolveCompareCandidateFromRouteContext,
} from '../utils/editor-compare-route-context'
import { buildCollaborationDocumentOperationEnvelope } from '../utils/collaboration-document-ops'
import {
  clearPendingCollaborationSync,
  listPendingCollaborationSyncs,
  writePendingCollaborationSync,
  type PendingCollaborationDocumentSync,
} from '../utils/collaboration-pending-sync'

const COMPARE_ISSUE_KINDS: CrossDocumentCompareIssueKind[] = ['different', 'primary_only', 'secondary_only']

function compareIssueKindLabel(kind: CrossDocumentCompareIssueKind) {
  if (kind === 'different') return 'Changed lines'
  if (kind === 'primary_only') return 'Draft-only lines'
  return 'Compare-only lines'
}

function compareIssueKindFilterMode(kind: CrossDocumentCompareIssueKind): CrossDocumentCompareLineFilterMode {
  return kind === 'different' ? 'different' : 'one_sided'
}

export function buildEditorVideoStudioHandoffState(
  searchParams: Pick<URLSearchParams, 'get'>,
  routeProjectId?: string | null,
) {
  const source = String(searchParams.get('source') || '').trim()
  const active = source === 'video_studio'
  const preflightId = active ? String(searchParams.get('preflight_id') || '').trim() : ''
  const projectId = active ? String(routeProjectId || '').trim() : ''

  return {
    active,
    projectId,
    preflightId,
    videoStudioHref: '/app/remotion',
    note: active
      ? `Video Studio handoff loaded${preflightId ? ` from preflight ${preflightId}` : ''}. Continue refining the workspace here or jump back to Video Studio before execution.`
      : '',
  }
}

export function buildEditorDiagramStudioHandoffState(
  searchParams: Pick<URLSearchParams, 'get'>,
  routeProjectId?: string | null,
) {
  const source = String(searchParams.get('source') || '').trim()
  const active = source === 'diagram_studio'
  const projectId = active ? String(routeProjectId || '').trim() : ''
  const runId = active ? String(searchParams.get('run_id') || '').trim() : ''
  const artifactId = active ? String(searchParams.get('artifact_id') || '').trim() : ''
  const sceneId = active ? String(searchParams.get('scene_id') || '').trim() : ''
  const nextAiDrawIoHref = '/app/nextaidrawio'
  const reviewParams = new URLSearchParams({ source: 'diagram_studio' })
  if (projectId) reviewParams.set('project_id', projectId)
  if (sceneId) reviewParams.set('scene_id', sceneId)

  return {
    active,
    projectId,
    runId,
    artifactId,
    sceneId,
    nextAiDrawIoHref,
    reviewHref: `/app/excalidraw?${reviewParams.toString()}`,
    note: active
      ? `AI Diagram Studio handoff loaded${sceneId ? ` for scene ${sceneId}` : ''}${runId ? ` from run ${runId}` : ''}. Continue refining the linked workspace here or jump back to AI Diagram Studio for publish and review controls.`
      : '',
  }
}

export function buildEditorMindMapHandoffState(
  searchParams: Pick<URLSearchParams, 'get'>,
  routeProjectId?: string | null,
) {
  const source = String(searchParams.get('source') || '').trim()
  const active = source === 'mindmap'
  const projectId = active ? String(routeProjectId || '').trim() : ''
  const sceneId = active ? String(searchParams.get('mindmap_scene_id') || '').trim() : ''
  const nodeId = active ? String(searchParams.get('mindmap_node_id') || '').trim() : ''
  const topic = active ? String(searchParams.get('mindmap_topic') || '').trim() : ''
  const entityType = active ? String(searchParams.get('mindmap_entity_type') || '').trim() : ''
  const entityId = active ? String(searchParams.get('mindmap_entity_id') || '').trim() : ''

  return {
    active,
    projectId,
    sceneId,
    nodeId,
    topic,
    entityType,
    entityId,
    mindMapHref: '/app/mindmap',
    note: active
      ? `MindMap handoff loaded${topic ? ` for topic ${topic}` : ''}${nodeId ? ` from node ${nodeId}` : ''}. Continue editing the linked project here or return to the knowledge map for surrounding corpus context.`
      : '',
  }
}

type CompareProposalReviewDecision = 'accept' | 'reject'

function buildDraftFromCompareProposalReview(
  rows: CrossDocumentCompareLineRow[],
  decisions: Record<number, CompareProposalReviewDecision>
) {
  const nextLines: string[] = []
  for (const row of rows) {
    const decision = decisions[row.lineNumber]
    const useSecondary = decision === 'accept'
    if (useSecondary) {
      if (row.status === 'primary_only') continue
      nextLines.push(row.secondaryText || '')
      continue
    }
    if (row.status === 'secondary_only') continue
    nextLines.push(row.primaryText || '')
  }
  return nextLines.join('\n')
}

type CompareIntegrityIssueField = keyof Pick<
  CorpusIntegritySummary,
  | 'relation_violations'
  | 'citation_link_mismatches'
