/* eslint-disable no-async-promise-executor, @typescript-eslint/ban-ts-comment */
import { html } from "lit";
import { customElement, property, state } from "lit/decorators.js";
import { createRef, Ref, ref } from "lit/directives/ref.js";
import { SketchTailwindElement } from "./sketch-tailwind-element.js";

// See https://rodydavis.com/posts/lit-monaco-editor for some ideas.

import type * as monaco from "monaco-editor";

// Monaco is loaded dynamically - see loadMonaco() function
declare global {
  interface Window {
    monaco?: typeof monaco;
  }
}

// Monaco hash will be injected at build time
declare const __MONACO_HASH__: string;

// Load Monaco editor dynamically
let monacoLoadPromise: Promise<any> | null = null;

function loadMonaco(): Promise<typeof monaco> {
  if (monacoLoadPromise) {
    return monacoLoadPromise;
  }

  if (window.monaco) {
    return Promise.resolve(window.monaco);
  }

  monacoLoadPromise = new Promise(async (resolve, reject) => {
    try {
      // Check if we're in development mode
      const isDev = __MONACO_HASH__ === "dev";

      if (isDev) {
        // In development mode, import Monaco directly
        const monaco = await import("monaco-editor");
        window.monaco = monaco;
        resolve(monaco);
      } else {
        // In production mode, load from external bundle
        const monacoHash = __MONACO_HASH__;

        // Try to load the external Monaco bundle
        const script = document.createElement("script");
        script.onload = () => {
          // The Monaco bundle should set window.monaco
          if (window.monaco) {
            resolve(window.monaco);
          } else {
            reject(new Error("Monaco not loaded from external bundle"));
          }
        };
        script.onerror = (error) => {
          console.warn("Failed to load external Monaco bundle:", error);
          reject(new Error("Monaco external bundle failed to load"));
        };

        // Don't set type="module" since we're using IIFE format
        script.src = `./static/monaco-standalone-${monacoHash}.js`;
        document.head.appendChild(script);
      }
    } catch (error) {
      reject(error);
    }
  });

  return monacoLoadPromise;
}

// Define Monaco CSS styles as a string constant
const monacoStyles = `
  /* Import Monaco editor styles */
  @import url('./static/monaco/min/vs/editor/editor.main.css');

  /* Codicon font is now defined globally in sketch-app-shell.css */

  /* Custom Monaco styles */
  .monaco-editor {
    width: 100%;
    height: 100%;
  }

  /* Ensure light theme colors */
  .monaco-editor, .monaco-editor-background, .monaco-editor .inputarea.ime-input {
    background-color: var(--monaco-editor-bg, #ffffff) !important;
  }

  .monaco-editor .margin {
    background-color: var(--monaco-editor-margin, #f5f5f5) !important;
  }

  /* Glyph decoration styles - only show on hover */
  .comment-glyph-decoration {
    width: 16px !important;
    height: 18px !important;
    cursor: pointer;
    opacity: 0;
    transition: opacity 0.2s ease;
  }

  .comment-glyph-decoration:before {
    content: '💬';
    font-size: 12px;
    line-height: 18px;
    width: 16px;
    height: 18px;
    display: block;
    text-align: center;
  }

  .comment-glyph-decoration.hover-visible {
    opacity: 1;
  }
`;

// Configure Monaco to use local workers with correct relative paths
// Monaco looks for this global configuration to determine how to load web workers
// @ts-ignore - MonacoEnvironment is added to the global scope at runtime
self.MonacoEnvironment = {
  getWorkerUrl: function (_moduleId, label) {
    if (label === "json") {
      return "./static/json.worker.js";
    }
    if (label === "css" || label === "scss" || label === "less") {
      return "./static/css.worker.js";
    }
    if (label === "html" || label === "handlebars" || label === "razor") {
      return "./static/html.worker.js";
    }
    if (label === "typescript" || label === "javascript") {
      return "./static/ts.worker.js";
    }
    return "./static/editor.worker.js";
  },
};

@customElement("sketch-monaco-view")
export class CodeDiffEditor extends SketchTailwindElement {
  // Editable state
  @property({ type: Boolean, attribute: "editable-right" })
  editableRight?: boolean;

  // Inline diff mode (for mobile)
  @property({ type: Boolean, attribute: "inline" })
  inline?: boolean;
  private container: Ref<HTMLElement> = createRef();
  editor?: monaco.editor.IStandaloneDiffEditor;

  // Save state properties
  @state() private saveState: "idle" | "modified" | "saving" | "saved" = "idle";
  @state() private debounceSaveTimeout: number | null = null;
  @state() private lastSavedContent: string = "";
  @property() originalCode?: string = "// Original code here";
  @property() modifiedCode?: string = "// Modified code here";
  @property() originalFilename?: string = "original.js";
  @property() modifiedFilename?: string = "modified.js";

  // Comment system state
  @state() private showCommentBox: boolean = false;
  @state() private commentText: string = "";
  @state() private selectedLines: {
    startLine: number;
    endLine: number;
    editorType: "original" | "modified";
    text: string;
  } | null = null;
  @state() private commentBoxPosition: { top: number; left: number } = {
    top: 0,
    left: 0,
  };
  @state() private isDragging: boolean = false;
  @state() private dragStartLine: number | null = null;
  @state() private dragStartEditor: "original" | "modified" | null = null;

  // Track visible glyphs to ensure proper cleanup
  private visibleGlyphs: Set<string> = new Set();

  // Custom event to request save action from external components
  private requestSave() {
    if (!this.editableRight || this.saveState !== "modified") return;

    this.saveState = "saving";

    // Get current content from modified editor
    const modifiedContent = this.modifiedModel?.getValue() || "";

    // Create and dispatch the save event
    const saveEvent = new CustomEvent("monaco-save", {
      detail: {
        path: this.modifiedFilename,
        content: modifiedContent,
      },
      bubbles: true,
      composed: true,
    });

    this.dispatchEvent(saveEvent);
  }

  // Method to be called from parent when save is complete
  public notifySaveComplete(success: boolean) {
    if (success) {
      this.saveState = "saved";
      // Update last saved content
      this.lastSavedContent = this.modifiedModel?.getValue() || "";
      // Reset to idle after a delay
      setTimeout(() => {
        this.saveState = "idle";
      }, 2000);
    } else {
      // Return to modified state on error
      this.saveState = "modified";
    }
  }

  // Rescue people with strong save-constantly habits
  private setupKeyboardShortcuts() {
    if (!this.editor) return;
    const modifiedEditor = this.editor.getModifiedEditor();
    if (!modifiedEditor) return;

    const monaco = window.monaco;
    if (!monaco) return;

    modifiedEditor.addCommand(
      monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyS,
      () => {
        this.requestSave();
      },
    );
  }

  // Setup content change listener for debounced save
  private setupContentChangeListener() {
    if (!this.editor || !this.editableRight) return;

    const modifiedEditor = this.editor.getModifiedEditor();
    if (!modifiedEditor || !modifiedEditor.getModel()) return;

    // Store initial content
    this.lastSavedContent = modifiedEditor.getModel()!.getValue();

    // Listen for content changes
    modifiedEditor.getModel()!.onDidChangeContent(() => {
      const currentContent = modifiedEditor.getModel()!.getValue();

      // Check if content has actually changed from last saved state
      if (currentContent !== this.lastSavedContent) {
        this.saveState = "modified";

        // Debounce save request
        if (this.debounceSaveTimeout) {
          window.clearTimeout(this.debounceSaveTimeout);
        }

        this.debounceSaveTimeout = window.setTimeout(() => {
          this.requestSave();
          this.debounceSaveTimeout = null;
        }, 1000); // 1 second debounce
      }

      // Update glyph decorations when content changes
      setTimeout(() => {
        if (this.editor && this.modifiedModel) {
          this.addGlyphDecorationsToEditor(
            this.editor.getModifiedEditor(),
            this.modifiedModel,
            "modified",
          );
        }
      }, 50);
    });
  }

  render() {
    // Set host element styles for layout (equivalent to :host styles)
    this.style.cssText = `
      --editor-width: 100%;
      --editor-height: 100%;
      display: flex;
      flex: none;
      min-height: 0;
      position: relative;
      width: 100%;
    `;

    return html`
      <style>
        ${monacoStyles}

        /* Custom animation for comment box fade-in */
        @keyframes fadeIn {
          from {
            opacity: 0;
          }
          to {
            opacity: 1;
          }
        }
        .animate-fade-in {
          animation: fadeIn 0.2s ease-in-out;
        }
      </style>

      <main
        ${ref(this.container)}
        class="w-full h-full border border-gray-300 flex-none min-h-[200px] relative block box-border"
      ></main>

      <!-- Save indicator - shown when editing -->
      ${this.editableRight
        ? html`
            <div
              class="absolute top-1 right-1 px-2 py-0.5 rounded text-xs font-sans text-white z-[100] opacity-90 pointer-events-none transition-opacity duration-300 ${this
                .saveState === "idle"
                ? "bg-gray-500"
                : this.saveState === "modified"
                  ? "bg-yellow-500"
                  : this.saveState === "saving"
                    ? "bg-blue-400"
                    : this.saveState === "saved"
                      ? "bg-green-500"
                      : "bg-gray-500"}"
            >
              ${this.saveState === "idle"
                ? "Editable"
                : this.saveState === "modified"
                  ? "Modified..."
                  : this.saveState === "saving"
                    ? "Saving..."
                    : this.saveState === "saved"
                      ? "Saved"
                      : ""}
            </div>
          `
        : ""}

      <!-- Comment box - shown when glyph is clicked -->
      ${this.showCommentBox
        ? html`
            <div
              class="fixed bg-white border border-gray-300 rounded shadow-lg p-3 z-[10001] w-[600px] animate-fade-in max-h-[80vh] overflow-y-auto"
              style="top: ${this.commentBoxPosition.top}px; left: ${this
                .commentBoxPosition.left}px;"
            >
              <div class="flex justify-between items-center mb-2">
                <h3 class="m-0 text-sm font-medium">Add comment</h3>
                <button
                  class="bg-none border-none cursor-pointer text-base text-gray-600 px-1.5 py-0.5 hover:text-gray-800"
                  @click="${this.closeCommentBox}"
                >
                  ×
                </button>
              </div>
              ${this.selectedLines
                ? html`
                    <div
                      class="bg-gray-100 border border-gray-200 rounded p-2 mb-2.5 font-mono text-xs overflow-y-auto whitespace-pre-wrap break-all leading-relaxed ${this.getPreviewCssClass() ===
                      "small-selection"
                        ? ""
                        : "max-h-[280px]"}"
                    >
                      ${this.selectedLines.text}
                    </div>
                  `
                : ""}
              <textarea
                class="w-full min-h-[80px] p-2 border border-gray-300 rounded resize-y font-inherit mb-2.5 box-border"
                placeholder="Type your comment here..."
                .value="${this.commentText}"
                @input="${this.handleCommentInput}"
                @keydown="${this.handleCommentKeydown}"
              ></textarea>
              <div class="flex justify-end gap-2">
                <button
                  class="px-3 py-1.5 rounded cursor-pointer text-xs bg-transparent border border-gray-300 hover:bg-gray-100"
                  @click="${this.closeCommentBox}"
                >
                  Cancel
                </button>
                <button
                  class="px-3 py-1.5 rounded cursor-pointer text-xs bg-blue-600 text-white border-none hover:bg-blue-700"
                  @click="${this.submitComment}"
                >
                  Add
                </button>
              </div>
            </div>
          `
        : ""}
    `;
  }

  /**
   * Handle changes to the comment text
   */
  private handleCommentInput(e: Event) {
    const target = e.target as HTMLTextAreaElement;
    this.commentText = target.value;
  }

  /**
   * Handle keyboard shortcuts in the comment textarea
   */
  private handleCommentKeydown(e: KeyboardEvent) {
    // Check for Command+Enter (Mac) or Ctrl+Enter (other platforms)
    if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
      e.preventDefault();
      this.submitComment();
    }
  }

  /**
   * Get CSS class for selected text preview based on number of lines
   */
  private getPreviewCssClass(): string {
    if (!this.selectedLines) {
      return "large-selection";
    }

    // Count the number of lines in the selected text
    const lineCount = this.selectedLines.text.split("\n").length;

    // If 10 lines or fewer, show all content; otherwise, limit height
    return lineCount <= 10 ? "small-selection" : "large-selection";
  }

  /**
   * Close the comment box
   */
  private closeCommentBox() {
    this.showCommentBox = false;
    this.commentText = "";
    this.selectedLines = null;
  }

  /**
   * Submit the comment
   */
  private submitComment() {
    try {
      if (!this.selectedLines || !this.commentText.trim()) {
        return;
      }

      // Store references before closing the comment box
      const selectedLines = this.selectedLines;
      const commentText = this.commentText;

      // Get the correct filename based on active editor
      const fileContext =
        selectedLines.editorType === "original"
          ? this.originalFilename || "Original file"
          : this.modifiedFilename || "Modified file";

      // Include editor info to make it clear which version was commented on
      const editorLabel =
        selectedLines.editorType === "original" ? "[Original]" : "[Modified]";

      // Add line number information
      let lineInfo = "";
      if (selectedLines.startLine === selectedLines.endLine) {
        lineInfo = ` (line ${selectedLines.startLine})`;
      } else {
        lineInfo = ` (lines ${selectedLines.startLine}-${selectedLines.endLine})`;
      }

      // Format the comment in a readable way
      const formattedComment = `\`\`\`\n${fileContext} ${editorLabel}${lineInfo}:\n${selectedLines.text}\n\`\`\`\n\n${commentText}`;

      // Close UI before dispatching to prevent interaction conflicts
      this.closeCommentBox();

      // Use setTimeout to ensure the UI has updated before sending the event
      setTimeout(() => {
        try {
          // Dispatch a custom event with the comment details
          const event = new CustomEvent("monaco-comment", {
            detail: {
              fileContext,
              selectedText: selectedLines.text,
              commentText: commentText,
              formattedComment,
              selectionRange: {
                startLineNumber: selectedLines.startLine,
                startColumn: 1,
                endLineNumber: selectedLines.endLine,
                endColumn: 1,
              },
              activeEditor: selectedLines.editorType,
            },
            bubbles: true,
            composed: true,
          });

          this.dispatchEvent(event);
        } catch (error) {
          console.error("Error dispatching comment event:", error);
        }
      }, 0);
    } catch (error) {
      console.error("Error submitting comment:", error);
      this.closeCommentBox();
    }
  }

  /**
   * Calculate the optimal position for the comment box to keep it in view
   */
  private calculateCommentBoxPosition(
    lineNumber: number,
    editorType: "original" | "modified",
  ): { top: number; left: number } {
    try {
      if (!this.editor) {
        return { top: 100, left: 100 };
      }

      const targetEditor =
        editorType === "original"
          ? this.editor.getOriginalEditor()
          : this.editor.getModifiedEditor();
      if (!targetEditor) {
        return { top: 100, left: 100 };
      }

      // Get position from editor
      const position = {
        lineNumber: lineNumber,
        column: 1,
      };

      // Use editor's built-in method for coordinate conversion
      const coords = targetEditor.getScrolledVisiblePosition(position);

      if (coords) {
        // Get accurate DOM position
        const editorDomNode = targetEditor.getDomNode();
        if (editorDomNode) {
          const editorRect = editorDomNode.getBoundingClientRect();

          // Calculate the actual screen position
          let screenLeft = editorRect.left + coords.left + 20; // Offset to the right
          let screenTop = editorRect.top + coords.top;

          // Get viewport dimensions
          const viewportWidth = window.innerWidth;
          const viewportHeight = window.innerHeight;

          // Estimated box dimensions (updated for wider box)
          const boxWidth = 600;
          const boxHeight = 400;

          // Check if box would go off the right edge
          if (screenLeft + boxWidth > viewportWidth) {
            screenLeft = viewportWidth - boxWidth - 20; // Keep 20px margin
          }

          // Check if box would go off the bottom
          if (screenTop + boxHeight > viewportHeight) {
            screenTop = Math.max(10, viewportHeight - boxHeight - 10);
          }

          // Ensure box is never positioned off-screen
          screenTop = Math.max(10, screenTop);
          screenLeft = Math.max(10, screenLeft);

          return { top: screenTop, left: screenLeft };
        }
      }
    } catch (error) {
      console.error("Error calculating comment box position:", error);
    }

    return { top: 100, left: 100 };
  }

  setOriginalCode(code: string, filename?: string) {
    this.originalCode = code;
    if (filename) {
      this.originalFilename = filename;
    }

    // Update the model if the editor is initialized
    if (this.editor) {
      const model = this.editor.getOriginalEditor().getModel();
      if (model) {
        model.setValue(code);
        if (filename) {
          window.monaco!.editor.setModelLanguage(
            model,
            this.getLanguageForFile(filename),
          );
        }
      }
    }
  }

  setModifiedCode(code: string, filename?: string) {
    this.modifiedCode = code;
    if (filename) {
      this.modifiedFilename = filename;
    }

    // Update the model if the editor is initialized
    if (this.editor) {
      const model = this.editor.getModifiedEditor().getModel();
      if (model) {
        model.setValue(code);
        if (filename) {
          window.monaco!.editor.setModelLanguage(
            model,
            this.getLanguageForFile(filename),
          );
        }
      }
    }
  }

  private _extensionToLanguageMap: Map<string, string> | null = null;

  private getLanguageForFile(filename: string): string {
    // Get the file extension (including the dot for exact matching)
    const extension = "." + (filename.split(".").pop()?.toLowerCase() || "");

    // Build the extension-to-language map on first use
    if (!this._extensionToLanguageMap) {
      this._extensionToLanguageMap = new Map();
      const languages = window.monaco!.languages.getLanguages();

      for (const language of languages) {
        if (language.extensions) {
          for (const ext of language.extensions) {
            // Monaco extensions already include the dot, so use them directly
            this._extensionToLanguageMap.set(ext.toLowerCase(), language.id);
          }
        }
      }
    }

    return this._extensionToLanguageMap.get(extension) || "plaintext";
  }

  /**
   * Setup glyph decorations for both editors
   */
  private setupGlyphDecorations() {
    if (!this.editor || !window.monaco) {
      return;
    }

    const originalEditor = this.editor.getOriginalEditor();
    const modifiedEditor = this.editor.getModifiedEditor();

    if (originalEditor && this.originalModel) {
      this.addGlyphDecorationsToEditor(
        originalEditor,
        this.originalModel,
        "original",
      );
      this.setupHoverBehavior(originalEditor);
    }

    if (modifiedEditor && this.modifiedModel) {
      this.addGlyphDecorationsToEditor(
        modifiedEditor,
        this.modifiedModel,
        "modified",
      );
      this.setupHoverBehavior(modifiedEditor);
    }
  }

  /**
   * Add glyph decorations to a specific editor
   */
  private addGlyphDecorationsToEditor(
    editor: monaco.editor.IStandaloneCodeEditor,
    model: monaco.editor.ITextModel,
    editorType: "original" | "modified",
  ) {
    if (!window.monaco) {
      return;
    }

    // Clear existing decorations
    if (editorType === "original" && this.originalDecorations) {
      this.originalDecorations.clear();
    } else if (editorType === "modified" && this.modifiedDecorations) {
      this.modifiedDecorations.clear();
    }

    // Create decorations for every line
    const lineCount = model.getLineCount();
    const decorations: monaco.editor.IModelDeltaDecoration[] = [];

    for (let lineNumber = 1; lineNumber <= lineCount; lineNumber++) {
      decorations.push({
        range: new window.monaco.Range(lineNumber, 1, lineNumber, 1),
        options: {
          isWholeLine: false,
          glyphMarginClassName: `comment-glyph-decoration comment-glyph-${editorType}-${lineNumber}`,
          glyphMarginHoverMessage: { value: "Comment line" },
          stickiness:
            window.monaco.editor.TrackedRangeStickiness
              .NeverGrowsWhenTypingAtEdges,
        },
      });
    }

    // Create or update decorations collection
    if (editorType === "original") {
      this.originalDecorations =
        editor.createDecorationsCollection(decorations);
    } else {
      this.modifiedDecorations =
        editor.createDecorationsCollection(decorations);
    }
  }

  /**
   * Setup hover and click behavior for glyph decorations
   */
  private setupHoverBehavior(editor: monaco.editor.IStandaloneCodeEditor) {
    if (!editor) {
      return;
    }

    let currentHoveredLine: number | null = null;
    const editorType =
      this.editor?.getOriginalEditor() === editor ? "original" : "modified";

    // Listen for mouse move events in the editor
    editor.onMouseMove((e) => {
      if (e.target.position) {
        const lineNumber = e.target.position.lineNumber;

        // Handle real-time drag preview updates
        if (
          this.isDragging &&
          this.dragStartLine !== null &&
          this.dragStartEditor === editorType &&
          this.showCommentBox
        ) {
          const startLine = Math.min(this.dragStartLine, lineNumber);
          const endLine = Math.max(this.dragStartLine, lineNumber);
          this.updateSelectedLinesPreview(startLine, endLine, editorType);
        }

        // Handle hover glyph visibility (only when not dragging)
        if (!this.isDragging) {
          // If we're hovering over a different line, update visibility
          if (currentHoveredLine !== lineNumber) {
            // Hide previous line's glyph
            if (currentHoveredLine !== null) {
              this.toggleGlyphVisibility(currentHoveredLine, false);
            }

            // Show current line's glyph
            this.toggleGlyphVisibility(lineNumber, true);
            currentHoveredLine = lineNumber;
          }
        }
      }
    });

    // Listen for mouse down events for click-to-comment and drag selection
    editor.onMouseDown((e) => {
      if (
        e.target.type ===
        window.monaco?.editor.MouseTargetType.GUTTER_GLYPH_MARGIN
      ) {
        if (e.target.position) {
          const lineNumber = e.target.position.lineNumber;

          // Prevent default Monaco behavior
          e.event.preventDefault();
          e.event.stopPropagation();

          // Check if there's an existing selection in this editor
          const selection = editor.getSelection();
          if (selection && !selection.isEmpty()) {
            // Use the existing selection
            const startLine = selection.startLineNumber;
            const endLine = selection.endLineNumber;
            this.showCommentForSelection(
              startLine,
              endLine,
              editorType,
              selection,
            );
          } else {
            // Start drag selection or show comment for clicked line
            this.isDragging = true;
            this.dragStartLine = lineNumber;
            this.dragStartEditor = editorType;

            // If it's just a click (not drag), show comment box immediately
            this.showCommentForLines(lineNumber, lineNumber, editorType);
          }
        }
      }
    });

    // Listen for mouse up events to end drag selection
    editor.onMouseUp((e) => {
      if (this.isDragging) {
        if (
          e.target.position &&
          this.dragStartLine !== null &&
          this.dragStartEditor === editorType
        ) {
          const endLine = e.target.position.lineNumber;
          const startLine = Math.min(this.dragStartLine, endLine);
          const finalEndLine = Math.max(this.dragStartLine, endLine);

          // Update the final selection (if comment box is not already shown)
          if (!this.showCommentBox) {
            this.showCommentForLines(startLine, finalEndLine, editorType);
          } else {
            // Just update the final selection since preview was already being updated
            this.updateSelectedLinesPreview(
              startLine,
              finalEndLine,
              editorType,
            );
          }
        }

        // Reset drag state
        this.isDragging = false;
        this.dragStartLine = null;
        this.dragStartEditor = null;
      }
    });

    // // Listen for mouse leave events
    // editor.onMouseLeave(() => {
    //   if (currentHoveredLine !== null) {
    //     this.toggleGlyphVisibility(currentHoveredLine, false);
    //     currentHoveredLine = null;
    //   }
    // });
  }

  /**
   * Update the selected lines preview during drag operations
   */
  private updateSelectedLinesPreview(
    startLine: number,
    endLine: number,
    editorType: "original" | "modified",
  ) {
    try {
      if (!this.editor) {
        return;
      }

      const targetModel =
        editorType === "original" ? this.originalModel : this.modifiedModel;

      if (!targetModel) {
        return;
      }

      // Get the text for the selected lines
      const lines: string[] = [];
      for (let i = startLine; i <= endLine; i++) {
        if (i <= targetModel.getLineCount()) {
          lines.push(targetModel.getLineContent(i));
        }
      }

      const selectedText = lines.join("\n");

      // Update the selected lines state
      this.selectedLines = {
        startLine,
        endLine,
        editorType,
        text: selectedText,
      };

      // Request update to refresh the preview
      this.requestUpdate();
    } catch (error) {
      console.error("Error updating selected lines preview:", error);
    }
  }

  /**
   * Show comment box for a Monaco editor selection
   */
  private showCommentForSelection(
    startLine: number,
    endLine: number,
    editorType: "original" | "modified",
    selection: monaco.Selection,
  ) {
    try {
      if (!this.editor) {
        return;
      }

      const targetModel =
        editorType === "original" ? this.originalModel : this.modifiedModel;

      if (!targetModel) {
        return;
      }

      // Get the exact selected text from the Monaco selection
      const selectedText = targetModel.getValueInRange(selection);

      // Set the selected lines state
      this.selectedLines = {
        startLine,
        endLine,
        editorType,
        text: selectedText,
      };

      // Calculate and set comment box position
      this.commentBoxPosition = this.calculateCommentBoxPosition(
        startLine,
        editorType,
      );

      // Reset comment text and show the box
      this.commentText = "";
      this.showCommentBox = true;

      // Clear any visible glyphs since we're showing the comment box
      this.clearAllVisibleGlyphs();

      // Request update to render the comment box
      this.requestUpdate();
    } catch (error) {
      console.error("Error showing comment for selection:", error);
    }
  }

  /**
   * Show comment box for a range of lines
   */
  private showCommentForLines(
    startLine: number,
    endLine: number,
    editorType: "original" | "modified",
  ) {
    try {
      if (!this.editor) {
        return;
      }

      const targetEditor =
        editorType === "original"
          ? this.editor.getOriginalEditor()
          : this.editor.getModifiedEditor();
      const targetModel =
        editorType === "original" ? this.originalModel : this.modifiedModel;

      if (!targetEditor || !targetModel) {
        return;
      }

      // Get the text for the selected lines
      const lines: string[] = [];
      for (let i = startLine; i <= endLine; i++) {
        if (i <= targetModel.getLineCount()) {
          lines.push(targetModel.getLineContent(i));
        }
      }

      const selectedText = lines.join("\n");

      // Set the selected lines state
      this.selectedLines = {
        startLine,
        endLine,
        editorType,
        text: selectedText,
      };

      // Calculate and set comment box position
      this.commentBoxPosition = this.calculateCommentBoxPosition(
        startLine,
        editorType,
      );

      // Reset comment text and show the box
      this.commentText = "";
      this.showCommentBox = true;

      // Clear any visible glyphs since we're showing the comment box
      this.clearAllVisibleGlyphs();

      // Request update to render the comment box
      this.requestUpdate();
    } catch (error) {
      console.error("Error showing comment for lines:", error);
    }
  }

  /**
   * Clear all currently visible glyphs
   */
  private clearAllVisibleGlyphs() {
    try {
      this.visibleGlyphs.forEach((glyphId) => {
        const element = this.container.value?.querySelector(`.${glyphId}`);
        if (element) {
          element.classList.remove("hover-visible");
        }
      });
      this.visibleGlyphs.clear();
    } catch (error) {
      console.error("Error clearing visible glyphs:", error);
    }
  }

  /**
   * Toggle the visibility of a glyph decoration for a specific line
   */
  private toggleGlyphVisibility(lineNumber: number, visible: boolean) {
    try {
      // If making visible, clear all existing visible glyphs first
      if (visible) {
        this.clearAllVisibleGlyphs();
      }

      // Find all glyph decorations for this line in both editors
      const selectors = [
        `comment-glyph-original-${lineNumber}`,
        `comment-glyph-modified-${lineNumber}`,
      ];

      selectors.forEach((glyphId) => {
        const element = this.container.value?.querySelector(`.${glyphId}`);
        if (element) {
          if (visible) {
            element.classList.add("hover-visible");
            this.visibleGlyphs.add(glyphId);
          } else {
            element.classList.remove("hover-visible");
            this.visibleGlyphs.delete(glyphId);
          }
        }
      });
    } catch (error) {
      console.error("Error toggling glyph visibility:", error);
    }
  }

  /**
   * Update editor options
   */
  setOptions(value: monaco.editor.IDiffEditorConstructionOptions) {
    if (this.editor) {
      this.editor.updateOptions(value);
      // Re-fit content after options change with scroll preservation
      if (this.fitEditorToContent) {
        setTimeout(() => {
          // Preserve scroll positions during options change
          const originalScrollTop =
            this.editor!.getOriginalEditor().getScrollTop();
          const modifiedScrollTop =
            this.editor!.getModifiedEditor().getScrollTop();

          this.fitEditorToContent!();

          // Restore scroll positions
          requestAnimationFrame(() => {
            this.editor!.getOriginalEditor().setScrollTop(originalScrollTop);
            this.editor!.getModifiedEditor().setScrollTop(modifiedScrollTop);
          });
        }, 50);
      }
    }
  }

  /**
   * Toggle hideUnchangedRegions feature
   */
  toggleHideUnchangedRegions(enabled: boolean) {
    if (this.editor) {
      this.editor.updateOptions({
        hideUnchangedRegions: {
          enabled: enabled,
          contextLineCount: 3,
          minimumLineCount: 3,
          revealLineCount: 10,
        },
      });
      // Re-fit content after toggling with scroll preservation
      if (this.fitEditorToContent) {
        setTimeout(() => {
          // Preserve scroll positions during toggle
          const originalScrollTop =
            this.editor!.getOriginalEditor().getScrollTop();
          const modifiedScrollTop =
            this.editor!.getModifiedEditor().getScrollTop();

          this.fitEditorToContent!();

          // Restore scroll positions
          requestAnimationFrame(() => {
            this.editor!.getOriginalEditor().setScrollTop(originalScrollTop);
            this.editor!.getModifiedEditor().setScrollTop(modifiedScrollTop);
          });
        }, 100);
      }
    }
  }

  // Models for the editor
  private originalModel?: monaco.editor.ITextModel;
  private modifiedModel?: monaco.editor.ITextModel;

  // Decoration collections for glyph decorations
  private originalDecorations?: monaco.editor.IEditorDecorationsCollection;
  private modifiedDecorations?: monaco.editor.IEditorDecorationsCollection;

  private async initializeEditor() {
    try {
      // Load Monaco dynamically
      const monaco = await loadMonaco();

      // Disable semantic validation globally for TypeScript/JavaScript if available
      if (monaco.languages && monaco.languages.typescript) {
        monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions({
          noSemanticValidation: true,
        });
        monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions({
          noSemanticValidation: true,
        });
      }

      // First time initialization
      if (!this.editor) {
        // Ensure the container ref is available
        if (!this.container.value) {
          throw new Error(
            "Container element not available - component may not be fully rendered",
          );
        }

        // Create the diff editor with auto-sizing configuration
        this.editor = monaco.editor.createDiffEditor(this.container.value, {
          automaticLayout: false, // We'll resize manually
          readOnly: true,
          theme: "vs", // Always use light mode
          renderSideBySide: !this.inline,
          ignoreTrimWhitespace: false,
          // Enable glyph margin for both editors to show decorations
          glyphMargin: true,
          scrollbar: {
            // Ideally we'd handle the mouse wheel for the horizontal scrollbar,
            // but there doesn't seem to be that option. Setting
            // alwaysConsumeMousewheel false and handleMouseWheel true didn't
            // work for me.
            handleMouseWheel: false,
          },
          renderOverviewRuler: false, // Disable overview ruler
          scrollBeyondLastLine: false,
          // Focus on the differences by hiding unchanged regions
          hideUnchangedRegions: {
            enabled: true, // Enable the feature
            contextLineCount: 5, // Show 3 lines of context around each difference
            minimumLineCount: 3, // Hide regions only when they're at least 3 lines
            revealLineCount: 10, // Show 10 lines when expanding a hidden region
          },
        });

        this.setupKeyboardShortcuts();

        // If this is an editable view, set the correct read-only state for each editor
        if (this.editableRight) {
          // Make sure the original editor is always read-only
          this.editor
            .getOriginalEditor()
            .updateOptions({ readOnly: true, glyphMargin: true });
          // Make sure the modified editor is editable
          this.editor
            .getModifiedEditor()
            .updateOptions({ readOnly: false, glyphMargin: true });
        } else {
          // Ensure glyph margin is enabled on both editors even in read-only mode
          this.editor.getOriginalEditor().updateOptions({ glyphMargin: true });
          this.editor.getModifiedEditor().updateOptions({ glyphMargin: true });
        }

        // Set up auto-sizing
        this.setupAutoSizing();

        // Add Monaco editor to debug global
        this.addToDebugGlobal();
      }

      // Create or update models
      this.updateModels();
      // Add glyph decorations after models are set
      this.setupGlyphDecorations();
      // Set up content change listener
      this.setupContentChangeListener();

      // Fix cursor positioning issues by ensuring fonts are loaded
      document.fonts.ready.then(() => {
        if (this.editor) {
          // Preserve scroll positions during font remeasuring
          const originalScrollTop = this.editor
            .getOriginalEditor()
            .getScrollTop();
          const modifiedScrollTop = this.editor
            .getModifiedEditor()
            .getScrollTop();

          monaco.editor.remeasureFonts();

          if (this.fitEditorToContent) {
            this.fitEditorToContent();
          }

          // Restore scroll positions after font remeasuring
          requestAnimationFrame(() => {
            this.editor!.getOriginalEditor().setScrollTop(originalScrollTop);
            this.editor!.getModifiedEditor().setScrollTop(modifiedScrollTop);
          });
        }
      });

      // Force layout recalculation after a short delay with scroll preservation
      setTimeout(() => {
        if (this.editor && this.fitEditorToContent) {
          // Preserve scroll positions
          const originalScrollTop = this.editor
            .getOriginalEditor()
            .getScrollTop();
          const modifiedScrollTop = this.editor
            .getModifiedEditor()
            .getScrollTop();

          this.fitEditorToContent();

          // Restore scroll positions
          requestAnimationFrame(() => {
            this.editor!.getOriginalEditor().setScrollTop(originalScrollTop);
            this.editor!.getModifiedEditor().setScrollTop(modifiedScrollTop);
          });
        }
      }, 100);
    } catch (error) {
      console.error("Error initializing Monaco editor:", error);
    }
  }

  private updateModels() {
    try {
      // Get language based on filename
      const originalLang = this.getLanguageForFile(this.originalFilename || "");
      const modifiedLang = this.getLanguageForFile(this.modifiedFilename || "");

      // Always create new models with unique URIs based on timestamp to avoid conflicts
      const timestamp = new Date().getTime();
      // TODO: Could put filename in these URIs; unclear how they're used right now.
      const originalUri = window.monaco!.Uri.parse(
        `file:///original-${timestamp}.${originalLang}`,
      );
      const modifiedUri = window.monaco!.Uri.parse(
        `file:///modified-${timestamp}.${modifiedLang}`,
      );

      // Store references to old models
      const oldOriginalModel = this.originalModel;
      const oldModifiedModel = this.modifiedModel;

      // Nullify instance variables to prevent accidental use
      this.originalModel = undefined;
      this.modifiedModel = undefined;

      // Clear the editor model first to release Monaco's internal references
      if (this.editor) {
        this.editor.setModel(null);
      }

      // Now it's safe to dispose the old models
      if (oldOriginalModel) {
        oldOriginalModel.dispose();
      }

      if (oldModifiedModel) {
        oldModifiedModel.dispose();
      }

      // Create new models
      this.originalModel = window.monaco!.editor.createModel(
        this.originalCode || "",
        originalLang,
        originalUri,
      );

      this.modifiedModel = window.monaco!.editor.createModel(
        this.modifiedCode || "",
        modifiedLang,
        modifiedUri,
      );

      // Set the new models on the editor
      if (this.editor) {
        this.editor.setModel({
          original: this.originalModel,
          modified: this.modifiedModel,
        });

        // Set initial hideUnchangedRegions state (default to enabled/collapsed)
        this.editor.updateOptions({
          hideUnchangedRegions: {
            enabled: true, // Default to collapsed state
            contextLineCount: 3,
            minimumLineCount: 3,
            revealLineCount: 10,
          },
        });

        // Fit content after setting new models with scroll preservation
        if (this.fitEditorToContent) {
          setTimeout(() => {
            // Preserve scroll positions when fitting content after model changes
            const originalScrollTop =
              this.editor!.getOriginalEditor().getScrollTop();
            const modifiedScrollTop =
              this.editor!.getModifiedEditor().getScrollTop();

            this.fitEditorToContent!();

            // Restore scroll positions
            requestAnimationFrame(() => {
              this.editor!.getOriginalEditor().setScrollTop(originalScrollTop);
              this.editor!.getModifiedEditor().setScrollTop(modifiedScrollTop);
            });
          }, 50);
        }

        // Add glyph decorations after setting new models
        setTimeout(() => this.setupGlyphDecorations(), 100);
      }
      this.setupContentChangeListener();
    } catch (error) {
      console.error("Error updating Monaco models:", error);
    }
  }

  async updated(changedProperties: Map<string, any>) {
    // If any relevant properties changed, just update the models
    if (
      changedProperties.has("originalCode") ||
      changedProperties.has("modifiedCode") ||
      changedProperties.has("originalFilename") ||
      changedProperties.has("modifiedFilename") ||
      changedProperties.has("editableRight")
    ) {
      if (this.editor) {
        this.updateModels();

        // Force auto-sizing after model updates
        // Use a slightly longer delay to ensure layout is stable with scroll preservation
        setTimeout(() => {
          if (this.fitEditorToContent && this.editor) {
            // Preserve scroll positions during model update layout
            const originalScrollTop = this.editor
              .getOriginalEditor()
              .getScrollTop();
            const modifiedScrollTop = this.editor
              .getModifiedEditor()
              .getScrollTop();

            this.fitEditorToContent();

            // Restore scroll positions
            requestAnimationFrame(() => {
              this.editor!.getOriginalEditor().setScrollTop(originalScrollTop);
              this.editor!.getModifiedEditor().setScrollTop(modifiedScrollTop);
            });
          }
        }, 100);
      } else {
        // If the editor isn't initialized yet but we received content,
        // ensure we're connected before initializing
        await this.ensureConnectedToDocument();
        await this.initializeEditor();
      }
    }
  }

  // Set up auto-sizing for multi-file diff view
  private setupAutoSizing() {
    if (!this.editor) return;

    const fitContent = () => {
      try {
        const originalEditor = this.editor!.getOriginalEditor();
        const modifiedEditor = this.editor!.getModifiedEditor();

        const originalHeight = originalEditor.getContentHeight();
        const modifiedHeight = modifiedEditor.getContentHeight();

        // Use the maximum height of both editors, plus some padding
        const maxHeight = Math.max(originalHeight, modifiedHeight) + 18; // 1 blank line bottom padding

        // Set both container and host height to enable proper scrolling
        if (this.container.value) {
          // Set explicit heights on both container and host
          this.container.value.style.height = `${maxHeight}px`;
          this.style.height = `${maxHeight}px`; // Update host element height

          // Emit the height change event BEFORE calling layout
          // This ensures parent containers resize first
          this.dispatchEvent(
            new CustomEvent("monaco-height-changed", {
              detail: { height: maxHeight },
              bubbles: true,
              composed: true,
            }),
          );

          // Layout after both this component and parents have updated
          setTimeout(() => {
            if (this.editor && this.container.value) {
              // Use explicit dimensions to ensure Monaco uses full available space
              // Use clientWidth instead of offsetWidth to avoid border overflow
              const width = this.container.value.clientWidth;
              this.editor.layout({
                width: width,
                height: maxHeight,
              });
            }
          }, 10);
        }
      } catch (error) {
        console.error("Error in fitContent:", error);
      }
    };

    // Store the fit function for external access
    this.fitEditorToContent = fitContent;

    // Set up listeners for content size changes
    this.editor.getOriginalEditor().onDidContentSizeChange(fitContent);
    this.editor.getModifiedEditor().onDidContentSizeChange(fitContent);

    // Initial fit
    fitContent();
  }

  private fitEditorToContent: (() => void) | null = null;

  /**
   * Set up window resize handler to ensure Monaco editor adapts to browser window changes
   */
  private setupWindowResizeHandler() {
    // Create a debounced resize handler to avoid too many layout calls
    let resizeTimeout: number | null = null;

    this._windowResizeHandler = () => {
      // Clear any existing timeout
      if (resizeTimeout) {
        window.clearTimeout(resizeTimeout);
      }

      // Debounce the resize to avoid excessive layout calls
      resizeTimeout = window.setTimeout(() => {
        if (this.editor && this.container.value) {
          // Trigger layout recalculation with scroll preservation
          if (this.fitEditorToContent) {
            // Preserve scroll positions during window resize
            const originalScrollTop = this.editor
              .getOriginalEditor()
              .getScrollTop();
            const modifiedScrollTop = this.editor
              .getModifiedEditor()
              .getScrollTop();

            this.fitEditorToContent();

            // Restore scroll positions
            requestAnimationFrame(() => {
              this.editor!.getOriginalEditor().setScrollTop(originalScrollTop);
              this.editor!.getModifiedEditor().setScrollTop(modifiedScrollTop);
            });
          } else {
            // Fallback: just trigger a layout with current container dimensions
            // Use clientWidth/Height instead of offsetWidth/Height to avoid border overflow
            const width = this.container.value.clientWidth;
            const height = this.container.value.clientHeight;
            this.editor.layout({ width, height });
          }
        }
      }, 100); // 100ms debounce
    };

    // Add the event listener
    window.addEventListener("resize", this._windowResizeHandler);
  }

  // Add resize observer to ensure editor resizes when container changes
  async firstUpdated() {
    // Ensure we're connected to the document before Monaco initialization
    await this.ensureConnectedToDocument();

    // Initialize the editor
    await this.initializeEditor();

    // Set up window resize handler to ensure Monaco editor adapts to browser window changes
    this.setupWindowResizeHandler();

    // For multi-file diff, we don't use ResizeObserver since we control the size
    // Instead, we rely on auto-sizing based on content

    // If editable, set up edit mode and content change listener
    if (this.editableRight && this.editor) {
      // Ensure the original editor is read-only
      this.editor.getOriginalEditor().updateOptions({ readOnly: true });
      // Ensure the modified editor is editable
      this.editor.getModifiedEditor().updateOptions({ readOnly: false });
    }
  }

  /**
   * Ensure this component and its container are properly connected to the document.
   * Monaco editor requires the container to be in the document for proper initialization.
   */
  private async ensureConnectedToDocument(): Promise<void> {
    // Wait for our own render to complete
    await this.updateComplete;

    // Verify the container ref is available
    if (!this.container.value) {
      throw new Error("Container element not available after updateComplete");
    }

    // Check if we're connected to the document
    if (!this.isConnected) {
      throw new Error("Component is not connected to the document");
    }

    // Verify the container is also in the document
    if (!this.container.value.isConnected) {
      throw new Error("Container element is not connected to the document");
    }
  }

  private _resizeObserver: ResizeObserver | null = null;
  private _windowResizeHandler: (() => void) | null = null;

  /**
   * Add this Monaco editor instance to the global debug object
   * This allows inspection and debugging via browser console
   */
  private addToDebugGlobal() {
    try {
      // Initialize the debug global if it doesn't exist
      if (!(window as any).sketchDebug) {
        (window as any).sketchDebug = {
          monaco: window.monaco!,
          editors: [],
          remeasureFonts: () => {
            window.monaco!.editor.remeasureFonts();
            (window as any).sketchDebug.editors.forEach(
              (editor: any, _index: number) => {
                if (editor && editor.layout) {
                  editor.layout();
                }
              },
            );
          },
          layoutAll: () => {
            (window as any).sketchDebug.editors.forEach(
              (editor: any, _index: number) => {
                if (editor && editor.layout) {
                  editor.layout();
                }
              },
            );
          },
          getActiveEditors: () => {
            return (window as any).sketchDebug.editors.filter(
              (editor: any) => editor !== null,
            );
          },
        };
      }

      // Add this editor to the debug collection
      if (this.editor) {
        (window as any).sketchDebug.editors.push(this.editor);
      }
    } catch (error) {
      console.error("Error adding Monaco editor to debug global:", error);
    }
  }

  disconnectedCallback() {
    super.disconnectedCallback();

    try {
      // Remove editor from debug global before disposal
      if (this.editor && (window as any).sketchDebug?.editors) {
        const index = (window as any).sketchDebug.editors.indexOf(this.editor);
        if (index > -1) {
          (window as any).sketchDebug.editors[index] = null;
        }
      }

      // Clean up decorations
      if (this.originalDecorations) {
        this.originalDecorations.clear();
        this.originalDecorations = undefined;
      }

      if (this.modifiedDecorations) {
        this.modifiedDecorations.clear();
        this.modifiedDecorations = undefined;
      }

      // Clean up resources when element is removed
      if (this.editor) {
        this.editor.dispose();
        this.editor = undefined;
      }

      // Dispose models to prevent memory leaks
      if (this.originalModel) {
        this.originalModel.dispose();
        this.originalModel = undefined;
      }

      if (this.modifiedModel) {
        this.modifiedModel.dispose();
        this.modifiedModel = undefined;
      }

      // Clean up resize observer (if any)
      if (this._resizeObserver) {
        this._resizeObserver.disconnect();
        this._resizeObserver = null;
      }

      // Clear the fit function reference
      this.fitEditorToContent = null;

      // Remove window resize handler if set
      if (this._windowResizeHandler) {
        window.removeEventListener("resize", this._windowResizeHandler);
        this._windowResizeHandler = null;
      }

      // Clear visible glyphs tracking
      this.visibleGlyphs.clear();
    } catch (error) {
      console.error("Error in disconnectedCallback:", error);
    }
  }

  // disconnectedCallback implementation is defined below
}

declare global {
  interface HTMLElementTagNameMap {
    "sketch-monaco-view": CodeDiffEditor;
  }
}
