/* eslint-disable @typescript-eslint/no-explicit-any, no-async-promise-executor, @typescript-eslint/ban-ts-comment */
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: 600px;
      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;
      overflow-y: auto;
      white-space: pre-wrap;
      word-break: break-all;
      line-height: 1.4;
    }

    .selected-text-preview.small-selection {
      /* For selections of 10 lines or fewer, ensure all content is visible */
      max-height: none;
    }

    .selected-text-preview.large-selection {
      /* For selections larger than 10 lines, limit height with scroll */
      max-height: 280px; /* Approximately 10 lines at 12px font with 1.4 line-height */
    }

    .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.getPreviewCssClass()}"
                    >
                      ${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;
  }

  /**
   * 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;
  }
}
