import { css, html, LitElement } from "lit";
import { customElement, property, state } from "lit/decorators.js";
import { createRef, Ref, ref } from "lit/directives/ref.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 LitElement {
  // 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);
    });
  }

  static styles = css`
    /* Save indicator styles */
    .save-indicator {
      position: absolute;
      top: 4px;
      right: 4px;
      padding: 3px 8px;
      border-radius: 3px;
      font-size: 12px;
      font-family: system-ui, sans-serif;
      color: white;
      z-index: 100;
      opacity: 0.9;
      pointer-events: none;
      transition: opacity 0.3s ease;
    }

    .save-indicator.idle {
      background-color: #6c757d;
    }

    .save-indicator.modified {
      background-color: #f0ad4e;
    }

    .save-indicator.saving {
      background-color: #5bc0de;
    }

    .save-indicator.saved {
      background-color: #5cb85c;
    }

    /* Editor host styles */
    :host {
      --editor-width: 100%;
      --editor-height: 100%;
      display: flex;
      flex: none; /* Don't grow/shrink - size is determined by content */
      min-height: 0; /* Critical for flex layout */
      position: relative; /* Establish positioning context */
      width: 100%; /* Take full width */
      /* Height will be set dynamically by setupAutoSizing */
    }
    main {
      width: 100%;
      height: 100%; /* Fill the host element completely */
      border: 1px solid #e0e0e0;
      flex: none; /* Size determined by parent */
      min-height: 200px; /* Ensure a minimum height for the editor */
      /* Remove absolute positioning - use normal block layout */
      position: relative;
      display: block;
      box-sizing: border-box; /* Include border in width calculation */
    }

    /* Comment box styles */
    .comment-box {
      position: fixed;
      background-color: white;
      border: 1px solid #ddd;
      border-radius: 4px;
      box-shadow: 0 3px 10px rgba(0, 0, 0, 0.15);
      padding: 12px;
      z-index: 10001;
      width: 350px;
      animation: fadeIn 0.2s ease-in-out;
      max-height: 80vh;
      overflow-y: auto;
    }

    .comment-box-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 8px;
    }

    .comment-box-header h3 {
      margin: 0;
      font-size: 14px;
      font-weight: 500;
    }

    .close-button {
      background: none;
      border: none;
      cursor: pointer;
      font-size: 16px;
      color: #666;
      padding: 2px 6px;
    }

    .close-button:hover {
      color: #333;
    }

    .selected-text-preview {
      background-color: #f5f5f5;
      border: 1px solid #eee;
      border-radius: 3px;
      padding: 8px;
      margin-bottom: 10px;
      font-family: monospace;
      font-size: 12px;
      max-height: 100px;
      overflow-y: auto;
      white-space: pre-wrap;
      word-break: break-all;
    }

    .comment-textarea {
      width: 100%;
      min-height: 80px;
      padding: 8px;
      border: 1px solid #ddd;
      border-radius: 3px;
      resize: vertical;
      font-family: inherit;
      margin-bottom: 10px;
      box-sizing: border-box;
    }

    .comment-actions {
      display: flex;
      justify-content: flex-end;
      gap: 8px;
    }

    .comment-actions button {
      padding: 6px 12px;
      border-radius: 3px;
      cursor: pointer;
      font-size: 12px;
    }

    .cancel-button {
      background-color: transparent;
      border: 1px solid #ddd;
    }

    .cancel-button:hover {
      background-color: #f5f5f5;
    }

    .submit-button {
      background-color: #4285f4;
      color: white;
      border: none;
    }

    .submit-button:hover {
      background-color: #3367d6;
    }

    @keyframes fadeIn {
      from {
        opacity: 0;
      }
      to {
        opacity: 1;
      }
    }
  `;

  render() {
    return html`
      <style>
        ${monacoStyles}
      </style>
      <main ${ref(this.container)}></main>

      <!-- Save indicator - shown when editing -->
      ${this.editableRight
        ? html`
            <div class="save-indicator ${this.saveState}">
              ${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="comment-box"
              style="top: ${this.commentBoxPosition.top}px; left: ${this
                .commentBoxPosition.left}px;"
            >
              <div class="comment-box-header">
                <h3>Add comment</h3>
                <button class="close-button" @click="${this.closeCommentBox}">
                  ×
                </button>
              </div>
              ${this.selectedLines
                ? html`
                    <div class="selected-text-preview">
                      ${this.selectedLines.text}
                    </div>
                  `
                : ""}
              <textarea
                class="comment-textarea"
                placeholder="Type your comment here..."
                .value="${this.commentText}"
                @input="${this.handleCommentInput}"
              ></textarea>
              <div class="comment-actions">
                <button class="cancel-button" @click="${this.closeCommentBox}">
                  Cancel
                </button>
                <button class="submit-button" @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;
  }

  /**
   * 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
          const boxWidth = 350;
          const boxHeight = 300;

          // 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
      if (this.fitEditorToContent) {
        setTimeout(() => this.fitEditorToContent!(), 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
      if (this.fitEditorToContent) {
        setTimeout(() => this.fitEditorToContent!(), 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) {
          monaco.editor.remeasureFonts();
          this.fitEditorToContent();
        }
      });

      // Force layout recalculation after a short delay
      setTimeout(() => {
        if (this.editor) {
          this.fitEditorToContent();
        }
      }, 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
        if (this.fitEditorToContent) {
          setTimeout(() => this.fitEditorToContent!(), 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
        setTimeout(() => {
          if (this.fitEditorToContent) {
            this.fitEditorToContent();
          }
        }, 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
          if (this.fitEditorToContent) {
            this.fitEditorToContent();
          } 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;
  }
}
