import {
  DeesElement,
  property,
  html,
  customElement,
  type TemplateResult,
  css,
  cssManager,
  state,
} from '@design.estate/dees-element';
import * as domtools from '@design.estate/dees-domtools';
import { themeDefaultStyles } from '../../00theme.js';
import type { IExecutionEnvironment, IFileWatcher } from '../../00group-runtime/index.js';
import { WebContainerEnvironment } from '../../00group-runtime/index.js';
import type { FileSystemTree } from '@tempfix/webcontainer__api';
import '../dees-workspace-monaco/dees-workspace-monaco.js';
import '../dees-workspace-filetree/dees-workspace-filetree.js';
import { DeesWorkspaceFiletree } from '../dees-workspace-filetree/dees-workspace-filetree.js';
import '../dees-workspace-terminal/dees-workspace-terminal.js';
import { DeesWorkspaceTerminal } from '../dees-workspace-terminal/dees-workspace-terminal.js';
import type { IRunProcessEventDetail } from '../dees-workspace-terminal/interfaces.js';
import '../dees-workspace-terminal-preview/dees-workspace-terminal-preview.js';
import '../dees-workspace-bottombar/dees-workspace-bottombar.js';
import '../../dees-icon/dees-icon.js';
import { DeesWorkspaceMonaco } from '../dees-workspace-monaco/dees-workspace-monaco.js';
import { TypeScriptIntelliSenseManager } from './typescript-intellisense.js';
import { DeesContextmenu } from '../../dees-contextmenu/dees-contextmenu.js';
import '@design.estate/dees-wcctools/demotools';
import '../../dees-actionbar/dees-actionbar.js';
import type { DeesActionbar } from '../../dees-actionbar/dees-actionbar.js';
import '../dees-workspace-diff-editor/dees-workspace-diff-editor.js';

declare global {
  interface HTMLElementTagNameMap {
    'dees-workspace': DeesWorkspace;
  }
}

interface IOpenFile {
  path: string;
  name: string;
  content: string;
  modified: boolean;
}

@customElement('dees-workspace')
export class DeesWorkspace extends DeesElement {
  public static demo = () => {
    const env = new WebContainerEnvironment();

    // Mount initial TypeScript project files
    const mountPromise = (async () => {
      await env.init();

      const fileTree: FileSystemTree = {
        'package.json': {
          file: {
            contents: JSON.stringify(
              {
                name: 'demo-project',
                version: '1.0.0',
                type: 'module',
                scripts: {
                  build: 'tsc',
                  dev: 'tsc --watch',
                },
                dependencies: {
                  '@push.rocks/smartpromise': '^4.2.3',
                },
                devDependencies: {
                  '@types/node': '^22.0.0',
                  typescript: '^5.0.0',
                },
              },
              null,
              2
            ),
          },
        },
        'npmextra.json': {
          file: {
            contents: JSON.stringify(
              {
                deesEditorWorkspace: {
                  onInit: 'pnpm install',
                },
              },
              null,
              2
            ),
          },
        },
        'tsconfig.json': {
          file: {
            contents: JSON.stringify(
              {
                compilerOptions: {
                  target: 'ES2022',
                  module: 'NodeNext',
                  moduleResolution: 'NodeNext',
                  strict: true,
                  outDir: './dist',
                  rootDir: './src',
                  declaration: true,
                },
                include: ['src/**/*'],
              },
              null,
              2
            ),
          },
        },
        src: {
          directory: {
            'index.ts': {
              file: {
                contents: `// Main entry point
import { greet, formatName } from './utils.js';

const name = formatName('World');
console.log(greet(name));

// Example async function
async function main() {
  const result = await Promise.resolve('Hello from async!');
  console.log(result);
}

main();
`,
              },
            },
            'utils.ts': {
              file: {
                contents: `// Utility functions

export interface IUser {
  firstName: string;
  lastName: string;
}

export function greet(name: string): string {
  return \`Hello, \${name}!\`;
}

export function formatName(name: string): string {
  return name.trim().toUpperCase();
}

export function createUser(firstName: string, lastName: string): IUser {
  return { firstName, lastName };
}
`,
              },
            },
            'importtest.ts': {
              file: {
                contents: `// Test npm package imports
import * as smartpromise from '@push.rocks/smartpromise';

// This should have IntelliSense showing defer() method
const deferred = smartpromise.defer<string>();

// Test using the deferred promise
async function testSmartPromise() {
  setTimeout(() => {
    deferred.resolve('Hello from smartpromise!');
  }, 100);

  const result = await deferred.promise;
  console.log(result);
}

testSmartPromise();
`,
              },
            },
          },
        },
      };

      await env.mount(fileTree);
    })();

    // Create container element for proper 100% height like dees-appui
    const containerElement = document.createElement('div');
    containerElement.style.cssText = 'position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden;';

    const workspaceElement = document.createElement('dees-workspace') as DeesWorkspace;
    workspaceElement.executionEnvironment = env;
    workspaceElement.initializationPromise = mountPromise;
    containerElement.appendChild(workspaceElement);

    return html`
      <dees-demowrapper>
        ${containerElement}
      </dees-demowrapper>
    `;
  };
  public static demoGroup = 'Workspace';

  // INSTANCE
  @property({ type: Object })
  accessor executionEnvironment: IExecutionEnvironment | null = null;

  @property({ attribute: false })
  accessor initializationPromise: Promise<void> | null = null;

  @property({ type: Boolean })
  accessor showFileTree: boolean = true;

  @property({ type: Boolean })
  accessor showTerminal: boolean = true;

  @property({ type: Number })
  accessor fileTreeWidth: number = 250;

  @property({ type: Number })
  accessor terminalHeight: number = 200;

  @state()
  accessor openFiles: IOpenFile[] = [];

  @state()
  accessor activeFilePath: string = '';

  @state()
  accessor isTerminalCollapsed: boolean = false;

  @state()
  accessor isFileTreeCollapsed: boolean = false;

  @state()
  accessor isInitializing: boolean = true;

  @state()
  accessor activeBottomPanel: 'terminal' | 'problems' = 'terminal';

  @state()
  accessor diagnosticMarkers: Array<{
    message: string;
    severity: number;
    startLineNumber: number;
    startColumn: number;
    endLineNumber: number;
    endColumn: number;
    source?: string;
    resource: { path: string };
  }> = [];

  private editorElement: DeesWorkspaceMonaco | null = null;
  private initializationStarted: boolean = false;
  private intelliSenseManager: TypeScriptIntelliSenseManager | null = null;
  private intelliSenseInitialized: boolean = false;

  // node_modules watcher for auto-loading types
  private nodeModulesWatcher: IFileWatcher | null = null;
  private nodeModulesDebounceTimeout: ReturnType<typeof setTimeout> | null = null;
  private intelliSenseDebounceTimeout: ReturnType<typeof setTimeout> | null = null;

  // Open file watchers for external change detection
  private openFileWatchers: Map<string, IFileWatcher> = new Map();
  private fileChangeDebounce: Map<string, ReturnType<typeof setTimeout>> = new Map();
  private actionbarElement: DeesActionbar | null = null;

  // Auto-save functionality
  @state()
  accessor autoSave: boolean = false;
  private autoSaveInterval: ReturnType<typeof setInterval> | null = null;

  // Init terminal preview state
  @state()
  accessor initCommand: string = '';

  @state()
  accessor initOutput: string[] = [];

  // Resize state
  @state()
  accessor currentFileTreeWidth: number = 250;

  @state()
  accessor currentTerminalHeight: number = 200;

  @state()
  accessor isDraggingFileTree: boolean = false;

  @state()
  accessor isDraggingTerminal: boolean = false;

  // Diff view state
  @state()
  accessor showDiffView: boolean = false;

  @state()
  accessor diffViewConfig: {
    filePath: string;
    originalContent: string;
    modifiedContent: string;
    language: string;
  } | null = null;

  // Keyboard shortcut handler (bound for proper cleanup)
  private keydownHandler = (e: KeyboardEvent) => {
    // Cmd+S (Mac) or Ctrl+S (Windows/Linux) - Save
    if ((e.metaKey || e.ctrlKey) && e.key === 's' && !e.shiftKey) {
      e.preventDefault();
      this.saveActiveFile();
    }

    // Cmd+Shift+S - Save All
    if ((e.metaKey || e.ctrlKey) && e.shiftKey && e.key.toLowerCase() === 's') {
      e.preventDefault();
      this.saveAllFiles();
    }
  };

  // ========== Filetree Resize Handlers ==========
  private handleFileTreeMouseDown = (e: MouseEvent) => {
    e.preventDefault();
    this.isDraggingFileTree = true;
    document.addEventListener('mousemove', this.handleFileTreeMouseMove);
    document.addEventListener('mouseup', this.handleFileTreeMouseUp);
  };

  private handleFileTreeMouseMove = (e: MouseEvent) => {
    if (!this.isDraggingFileTree) return;

    const containerRect = this.getBoundingClientRect();
    const mouseX = e.clientX - containerRect.left;

    // Clamp to min/max (150px min, 50% of container max)
    const minWidth = 150;
    const maxWidth = containerRect.width * 0.5;
    const newWidth = Math.max(minWidth, Math.min(maxWidth, mouseX));

    this.currentFileTreeWidth = newWidth;
  };

  private handleFileTreeMouseUp = () => {
    this.isDraggingFileTree = false;
    document.removeEventListener('mousemove', this.handleFileTreeMouseMove);
    document.removeEventListener('mouseup', this.handleFileTreeMouseUp);

    // Notify Monaco editor of size change
    window.dispatchEvent(new Event('resize'));
  };

  // ========== Terminal Resize Handlers ==========
  private handleTerminalMouseDown = (e: MouseEvent) => {
    e.preventDefault();
    this.isDraggingTerminal = true;
    document.addEventListener('mousemove', this.handleTerminalMouseMove);
    document.addEventListener('mouseup', this.handleTerminalMouseUp);
  };

  private handleTerminalMouseMove = (e: MouseEvent) => {
    if (!this.isDraggingTerminal) return;

    const containerRect = this.getBoundingClientRect();
    const mouseY = e.clientY - containerRect.top;

    // Calculate terminal height from bottom
    const terminalHeight = containerRect.height - mouseY;

    // Clamp to min/max (100px min, 70% of container max)
    const minHeight = 100;
    const maxHeight = containerRect.height * 0.7;
    const newHeight = Math.max(minHeight, Math.min(maxHeight, terminalHeight));

    this.currentTerminalHeight = newHeight;
  };

  private handleTerminalMouseUp = () => {
    this.isDraggingTerminal = false;
    document.removeEventListener('mousemove', this.handleTerminalMouseMove);
    document.removeEventListener('mouseup', this.handleTerminalMouseUp);

    // Notify Monaco editor of size change
    window.dispatchEvent(new Event('resize'));
  };

  public static styles = [
    themeDefaultStyles,
    cssManager.defaultStyles,
    css`
      :host {
        display: block;
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background: ${cssManager.bdTheme('hsl(0 0% 96%)', 'hsl(0 0% 7%)')};
        font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
      }

      .workspace-outer {
        display: flex;
        flex-direction: column;
        height: 100%;
        width: 100%;
      }

      .workspace-container {
        display: flex;
        flex-direction: row;
        flex: 1;
        min-height: 0;
        width: 100%;
      }

      .editor-area {
        display: flex;
        flex-direction: column;
        flex: 1;
        min-width: 0;
        overflow: hidden;
      }

      .filetree-panel {
        position: relative;
        overflow: hidden;
        flex-shrink: 0;
      }

      .filetree-panel.collapsed {
        width: 0 !important;
      }

      .editor-panel {
        position: relative;
        display: flex;
        flex-direction: column;
        overflow: hidden;
        background: ${cssManager.bdTheme('hsl(0 0% 100%)', 'hsl(0 0% 9%)')};
        flex: 1;
        min-width: 200px;
      }

      .terminal-panel {
        position: relative;
        border-top: 1px solid ${cssManager.bdTheme('hsl(0 0% 85%)', 'hsl(0 0% 15%)')};
        overflow: hidden;
        flex-shrink: 0;
      }

      .terminal-panel.collapsed {
        height: 32px !important;
      }

      .panel-header {
        height: 32px;
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 0 8px;
        background: ${cssManager.bdTheme('hsl(0 0% 95%)', 'hsl(0 0% 8%)')};
        border-bottom: 1px solid ${cssManager.bdTheme('hsl(0 0% 85%)', 'hsl(0 0% 15%)')};
        font-size: 12px;
        font-weight: 500;
        color: ${cssManager.bdTheme('hsl(0 0% 40%)', 'hsl(0 0% 60%)')};
      }

      .panel-header-title {
        display: flex;
        align-items: center;
        gap: 6px;
      }

      .panel-header-actions {
        display: flex;
        align-items: center;
        gap: 4px;
      }

      .panel-action {
        width: 24px;
        height: 24px;
        display: flex;
        align-items: center;
        justify-content: center;
        border-radius: 4px;
        cursor: pointer;
        color: ${cssManager.bdTheme('hsl(0 0% 50%)', 'hsl(0 0% 60%)')};
        transition: all 0.15s ease;
      }

      .panel-action:hover {
        background: ${cssManager.bdTheme('hsl(0 0% 88%)', 'hsl(0 0% 18%)')};
        color: ${cssManager.bdTheme('hsl(0 0% 30%)', 'hsl(0 0% 80%)')};
      }

      .tabs-bar {
        display: flex;
        align-items: stretch;
        height: 36px;
        background: ${cssManager.bdTheme('hsl(0 0% 96%)', 'hsl(0 0% 8%)')};
        border-bottom: 1px solid ${cssManager.bdTheme('hsl(0 0% 85%)', 'hsl(0 0% 15%)')};
        overflow-x: auto;
      }

      .tab {
        display: flex;
        align-items: center;
        gap: 6px;
        padding: 0 12px;
        min-width: 120px;
        max-width: 200px;
        border-right: 1px solid ${cssManager.bdTheme('hsl(0 0% 88%)', 'hsl(0 0% 12%)')};
        cursor: pointer;
        font-size: 12px;
        color: ${cssManager.bdTheme('hsl(0 0% 50%)', 'hsl(0 0% 60%)')};
        background: ${cssManager.bdTheme('hsl(0 0% 94%)', 'hsl(0 0% 10%)')};
        transition: all 0.15s ease;
      }

      .tab:hover {
        background: ${cssManager.bdTheme('hsl(0 0% 92%)', 'hsl(0 0% 12%)')};
      }

      .tab.active {
        background: ${cssManager.bdTheme('hsl(0 0% 100%)', 'hsl(0 0% 9%)')};
        color: ${cssManager.bdTheme('hsl(0 0% 20%)', 'hsl(0 0% 90%)')};
        border-bottom: 2px solid ${cssManager.bdTheme('hsl(210 100% 50%)', 'hsl(210 100% 60%)')};
      }

      .tab-name {
        flex: 1;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
      }

      .tab-close {
        width: 16px;
        height: 16px;
        display: flex;
        align-items: center;
        justify-content: center;
        border-radius: 4px;
        opacity: 0;
        transition: all 0.15s ease;
      }

      .tab:hover .tab-close {
        opacity: 1;
      }

      .tab-close:hover {
        background: ${cssManager.bdTheme('hsl(0 0% 85%)', 'hsl(0 0% 25%)')};
      }

      .tab-modified {
        width: 8px;
        height: 8px;
        border-radius: 50%;
        background: ${cssManager.bdTheme('hsl(0 0% 50%)', 'hsl(0 0% 60%)')};
      }

      .tabs-container {
        display: flex;
        flex: 1;
        overflow-x: auto;
      }

      .editor-menu-button {
        padding: 6px 8px;
        margin-right: 4px;
        margin-left: auto;
        border-radius: 4px;
        cursor: pointer;
        opacity: 0.6;
        transition: opacity 0.15s, background 0.15s;
        flex-shrink: 0;
        display: flex;
        align-items: center;
        justify-content: center;
      }

      .editor-menu-button:hover {
        opacity: 1;
        background: ${cssManager.bdTheme('hsl(0 0% 0% / 0.08)', 'hsl(0 0% 100% / 0.1)')};
      }

      .editor-content {
        flex: 1;
        position: relative;
      }

      .terminal-content {
        position: absolute;
        top: 32px;
        left: 0;
        right: 0;
        bottom: 0;
      }

      .problems-content {
        position: absolute;
        top: 32px;
        left: 0;
        right: 0;
        bottom: 0;
        overflow-y: auto;
        background: ${cssManager.bdTheme('hsl(0 0% 100%)', 'hsl(0 0% 9%)')};
      }

      .panel-tabs {
        display: flex;
        align-items: center;
        gap: 0;
      }

      .panel-tab {
        display: flex;
        align-items: center;
        gap: 6px;
        padding: 0 12px;
        height: 32px;
        cursor: pointer;
        font-size: 12px;
        font-weight: 500;
        color: ${cssManager.bdTheme('hsl(0 0% 50%)', 'hsl(0 0% 55%)')};
        border-bottom: 2px solid transparent;
        transition: all 0.15s ease;
      }

      .panel-tab:hover {
        color: ${cssManager.bdTheme('hsl(0 0% 30%)', 'hsl(0 0% 75%)')};
        background: ${cssManager.bdTheme('hsl(0 0% 90%)', 'hsl(0 0% 12%)')};
      }

      .panel-tab.active {
        color: ${cssManager.bdTheme('hsl(0 0% 20%)', 'hsl(0 0% 90%)')};
        border-bottom-color: ${cssManager.bdTheme('hsl(210 100% 50%)', 'hsl(210 100% 60%)')};
      }

      .panel-tab-badge {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        min-width: 18px;
        height: 18px;
        padding: 0 5px;
        border-radius: 9px;
        font-size: 11px;
        font-weight: 600;
        background: ${cssManager.bdTheme('hsl(0 70% 50%)', 'hsl(0 70% 45%)')};
        color: white;
      }

      .panel-tab-badge.warning {
        background: ${cssManager.bdTheme('hsl(40 70% 50%)', 'hsl(40 70% 45%)')};
      }

      .panel-tab-badge.none {
        display: none;
      }

      .problems-list {
        padding: 4px 0;
      }

      .problem-item {
        display: flex;
        align-items: flex-start;
        gap: 8px;
        padding: 6px 12px;
        cursor: pointer;
        font-size: 12px;
        line-height: 1.4;
        color: ${cssManager.bdTheme('hsl(0 0% 30%)', 'hsl(0 0% 80%)')};
        transition: background 0.1s ease;
      }

      .problem-item:hover {
        background: ${cssManager.bdTheme('hsl(0 0% 95%)', 'hsl(0 0% 15%)')};
      }

      .problem-icon {
        flex-shrink: 0;
        margin-top: 2px;
      }

      .problem-icon.error {
        color: ${cssManager.bdTheme('hsl(0 70% 50%)', 'hsl(0 70% 60%)')};
      }

      .problem-icon.warning {
        color: ${cssManager.bdTheme('hsl(40 70% 50%)', 'hsl(40 70% 60%)')};
      }

      .problem-details {
        flex: 1;
        min-width: 0;
      }

      .problem-message {
        word-break: break-word;
      }

      .problem-location {
        margin-top: 2px;
        font-size: 11px;
        color: ${cssManager.bdTheme('hsl(0 0% 50%)', 'hsl(0 0% 55%)')};
      }

      .problems-empty {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        height: 100%;
        color: ${cssManager.bdTheme('hsl(0 0% 55%)', 'hsl(0 0% 50%)')};
        font-size: 13px;
        gap: 8px;
      }

      .empty-state {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        height: 100%;
        color: ${cssManager.bdTheme('hsl(0 0% 50%)', 'hsl(0 0% 50%)')};
        font-size: 14px;
        gap: 8px;
      }

      .empty-state dees-icon {
        width: 48px;
        height: 48px;
        opacity: 0.5;
      }

      @keyframes spin {
        from { transform: rotate(0deg); }
        to { transform: rotate(360deg); }
      }

      .initializing {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        height: 100%;
        color: ${cssManager.bdTheme('hsl(0 0% 50%)', 'hsl(0 0% 60%)')};
        font-size: 14px;
        gap: 12px;
      }

      .initializing dees-icon {
        animation: spin 1s linear infinite;
      }

      .initializing dees-workspace-terminal-preview {
        margin-top: 24px;
        width: 80%;
        max-width: 600px;
        height: 200px;
      }

      dees-workspace-filetree {
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
      }

      dees-workspace-monaco {
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
      }

      dees-workspace-terminal {
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
      }

      /* Resize handles */
      .resize-handle-vertical {
        width: 6px;
        cursor: col-resize;
        background: transparent;
        transition: background 0.15s ease;
        position: relative;
        flex-shrink: 0;
        z-index: 10;
      }

      .resize-handle-vertical:hover,
      .resize-handle-vertical.dragging {
        background: ${cssManager.bdTheme('#3b82f6', '#58a6ff')};
      }

      .resize-handle-vertical::after {
        content: '';
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        width: 2px;
        height: 32px;
        background: ${cssManager.bdTheme('#9ca3af', '#6e7681')};
        border-radius: 1px;
        opacity: 0;
        transition: opacity 0.15s ease;
      }

      .resize-handle-vertical:hover::after,
      .resize-handle-vertical.dragging::after {
        opacity: 1;
        background: ${cssManager.bdTheme('#ffffff', '#ffffff')};
      }

      .resize-handle-horizontal {
        height: 6px;
        cursor: row-resize;
        background: transparent;
        transition: background 0.15s ease;
        position: relative;
        flex-shrink: 0;
        z-index: 10;
      }

      .resize-handle-horizontal:hover,
      .resize-handle-horizontal.dragging {
        background: ${cssManager.bdTheme('#3b82f6', '#58a6ff')};
      }

      .resize-handle-horizontal::after {
        content: '';
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        width: 32px;
        height: 2px;
        background: ${cssManager.bdTheme('#9ca3af', '#6e7681')};
        border-radius: 1px;
        opacity: 0;
        transition: opacity 0.15s ease;
      }

      .resize-handle-horizontal:hover::after,
      .resize-handle-horizontal.dragging::after {
        opacity: 1;
        background: ${cssManager.bdTheme('#ffffff', '#ffffff')};
      }

      /* Prevent text selection while dragging */
      .workspace-container.dragging {
        user-select: none;
      }

      .workspace-container.dragging .filetree-panel,
      .workspace-container.dragging .editor-panel,
      .workspace-container.dragging .terminal-panel {
        pointer-events: none;
      }

    `,
  ];

  public render(): TemplateResult {
    const containerClasses = [
      'workspace-container',
      (this.isDraggingFileTree || this.isDraggingTerminal) ? 'dragging' : '',
    ].filter(Boolean).join(' ');

    if (this.isInitializing) {
      return html`
        <div class="initializing">
          <dees-icon .icon=${'lucide:loader2'} iconSize="32"></dees-icon>
          <span>Initializing workspace...</span>
          <dees-workspace-terminal-preview
            .command=${this.initCommand || ''}
            .lines=${this.initOutput}
          ></dees-workspace-terminal-preview>
        </div>
      `;
    }

    return html`
      <div class="workspace-outer">
        <div class="${containerClasses}">
          <!-- Filetree panel (full height) -->
          ${this.showFileTree ? html`
            <div
              class="filetree-panel ${this.isFileTreeCollapsed ? 'collapsed' : ''}"
              style="width: ${this.isFileTreeCollapsed ? 0 : this.currentFileTreeWidth}px"
            >
              <dees-workspace-filetree
                .executionEnvironment=${this.executionEnvironment}
                .selectedPath=${this.activeFilePath}
                @file-select=${this.handleFileSelect}
              ></dees-workspace-filetree>
            </div>
            ${!this.isFileTreeCollapsed ? html`
              <div
                class="resize-handle-vertical ${this.isDraggingFileTree ? 'dragging' : ''}"
                @mousedown=${this.handleFileTreeMouseDown}
              ></div>
            ` : ''}
          ` : ''}

          <!-- Editor + Terminal area -->
          <div class="editor-area">
            <div class="editor-panel">
              <div class="tabs-bar">
                <div class="tabs-container">
                  ${this.openFiles.map(file => html`
                    <div
                      class="tab ${file.path === this.activeFilePath ? 'active' : ''}"
                      @click=${() => this.activateFile(file.path)}
                    >
                      ${file.modified ? html`<span class="tab-modified"></span>` : ''}
                      <span class="tab-name">${file.name}</span>
                      <span class="tab-close" @click=${(e: Event) => this.closeFile(e, file.path)}>
                        <dees-icon .icon=${'lucide:x'} iconSize="12"></dees-icon>
                      </span>
                    </div>
                  `)}
                </div>
                <div class="editor-menu-button" @click=${this.showEditorMenu} title="Editor options">
                  <dees-icon .icon=${'lucide:moreVertical'} iconSize="16"></dees-icon>
                </div>
              </div>
              <div class="editor-content">
                ${this.showDiffView && this.diffViewConfig ? html`
                  <dees-workspace-diff-editor
                    .filePath=${this.diffViewConfig.filePath}
                    .originalContent=${this.diffViewConfig.originalContent}
                    .modifiedContent=${this.diffViewConfig.modifiedContent}
                    .language=${this.diffViewConfig.language}
                    @diff-resolved=${this.handleDiffResolved}
                    @diff-closed=${() => { this.showDiffView = false; this.diffViewConfig = null; }}
                  ></dees-workspace-diff-editor>
                ` : this.openFiles.length === 0 ? html`
                  <div class="empty-state">
                    <dees-icon .icon=${'lucide:fileCode'} iconSize="48"></dees-icon>
                    <span>Select a file to edit</span>
                  </div>
                ` : html`
                  <dees-workspace-monaco
                    .filePath=${this.activeFilePath}
                    .content=${this.getActiveFileContent()}
                    .language=${this.getLanguageFromPath(this.activeFilePath)}
                    @content-change=${this.handleContentChange}
                  ></dees-workspace-monaco>
                `}
              </div>
              <dees-actionbar></dees-actionbar>
            </div>

            <!-- Horizontal resize handle for terminal -->
            ${this.showTerminal && !this.isTerminalCollapsed ? html`
              <div
                class="resize-handle-horizontal ${this.isDraggingTerminal ? 'dragging' : ''}"
                @mousedown=${this.handleTerminalMouseDown}
              ></div>
            ` : ''}

            <!-- Terminal panel -->
            ${this.showTerminal ? html`
              <div
                class="terminal-panel ${this.isTerminalCollapsed ? 'collapsed' : ''}"
                style="height: ${this.isTerminalCollapsed ? 32 : this.currentTerminalHeight}px"
              >
                <div class="panel-header">
                  <div class="panel-tabs">
                    <div
                      class="panel-tab ${this.activeBottomPanel === 'terminal' ? 'active' : ''}"
                      @click=${() => this.activeBottomPanel = 'terminal'}
                    >
                      <dees-icon .icon=${'lucide:terminal'} iconSize="14"></dees-icon>
                      Terminal
                    </div>
                    <div
                      class="panel-tab ${this.activeBottomPanel === 'problems' ? 'active' : ''}"
                      @click=${() => this.activeBottomPanel = 'problems'}
                    >
                      <dees-icon .icon=${'lucide:circleAlert'} iconSize="14"></dees-icon>
                      Problems
                      ${this.diagnosticMarkers.length > 0 ? html`
                        <span class="panel-tab-badge ${this.getErrorCount() === 0 ? 'warning' : ''}">${this.diagnosticMarkers.length}</span>
                      ` : ''}
                    </div>
                  </div>
                  <div class="panel-header-actions">
                    <div class="panel-action" @click=${this.toggleTerminal}>
                      <dees-icon
                        .icon=${this.isTerminalCollapsed ? 'lucide:chevronUp' : 'lucide:chevronDown'}
                        iconSize="14"
                      ></dees-icon>
                    </div>
                  </div>
                </div>
                <div class="terminal-content" style="display: ${this.activeBottomPanel === 'terminal' ? 'block' : 'none'}">
                  <dees-workspace-terminal
                    .executionEnvironment=${this.executionEnvironment}
                    .setupCommand=${''}
                  ></dees-workspace-terminal>
                </div>
                <div class="problems-content" style="display: ${this.activeBottomPanel === 'problems' ? 'block' : 'none'}">
                  ${this.renderProblemsPanel()}
                </div>
              </div>
            ` : ''}
          </div>
        </div>

        <!-- Bottom Bar (full width) -->
        <dees-workspace-bottombar
          .executionEnvironment=${this.executionEnvironment}
          @run-process=${this.handleRunProcess}
        ></dees-workspace-bottombar>
      </div>
    `;
  }

  async connectedCallback() {
    await super.connectedCallback();
    document.addEventListener('keydown', this.keydownHandler);
  }

  async disconnectedCallback() {
    await super.disconnectedCallback();
    document.removeEventListener('keydown', this.keydownHandler);

    // Clean up resize event listeners
    document.removeEventListener('mousemove', this.handleFileTreeMouseMove);
    document.removeEventListener('mouseup', this.handleFileTreeMouseUp);
    document.removeEventListener('mousemove', this.handleTerminalMouseMove);
    document.removeEventListener('mouseup', this.handleTerminalMouseUp);

    if (this.autoSaveInterval) {
      clearInterval(this.autoSaveInterval);
      this.autoSaveInterval = null;
    }
    this.stopNodeModulesWatcher();
    this.stopAllFileWatchers();
  }

  public async firstUpdated() {
    // Initialize current sizes from properties
    this.currentFileTreeWidth = this.fileTreeWidth;
    this.currentTerminalHeight = this.terminalHeight;

    if (this.executionEnvironment) {
      await this.initializeWorkspace();
    }
  }

  public async updated(changedProperties: Map<string, any>) {
    if (changedProperties.has('executionEnvironment') && this.executionEnvironment) {
      await this.initializeWorkspace();
    }

    // Capture actionbar reference when it becomes available (after initialization completes)
    if (!this.actionbarElement) {
      this.actionbarElement = this.shadowRoot?.querySelector('.editor-panel dees-actionbar') as DeesActionbar;
    }
  }

  private async initializeWorkspace() {
    if (!this.executionEnvironment) return;

    // Prevent double initialization
    if (this.initializationStarted) return;
    this.initializationStarted = true;

    this.isInitializing = true;

    try {
      // Wait for any external initialization (e.g., file mounting)
      if (this.initializationPromise) {
        await this.initializationPromise;
      } else if (!this.executionEnvironment.ready) {
        await this.executionEnvironment.init();
      }

      // Execute onInit command from npmextra.json if present
      await this.executeOnInitCommand();

      // IntelliSense is initialized lazily when first file is opened (Monaco loads on demand)
    } catch (error) {
      console.error('Failed to initialize workspace:', error);
      // Reset flag to allow retry
      this.initializationStarted = false;
    } finally {
      this.isInitializing = false;
    }
  }

  /**
   * Execute onInit command from npmextra.json if present
   * This allows automatic setup like `pnpm install` on workspace initialization
   */
  private async executeOnInitCommand(): Promise<void> {
    if (!this.executionEnvironment) return;

    try {
      if (await this.executionEnvironment.exists('/npmextra.json')) {
        const content = await this.executionEnvironment.readFile('/npmextra.json');
        const config = JSON.parse(content);
        const onInit = config?.deesEditorWorkspace?.onInit;

        if (onInit && typeof onInit === 'string') {
          console.log('Executing onInit command:', onInit);

          // Set command for terminal preview display
          this.initCommand = onInit;
          this.initOutput = [];

          // Parse command and args
          const [cmd, ...args] = onInit.split(' ');
          const process = await this.executionEnvironment.spawn(cmd, args);

          // Capture stdout/stderr for terminal preview
          process.output.pipeTo(
            new WritableStream({
              write: (data) => {
                // Split data into lines and append
                const lines = data.split('\n');
                for (const line of lines) {
                  if (line) {
                    this.initOutput = [...this.initOutput, line];
                  }
                }
              },
            })
          );

          // Wait for completion
          const exitCode = await process.exit;
          console.log('onInit command completed with exit code:', exitCode);

          // Add completion message
          this.initOutput = [...this.initOutput, '', `Command completed with exit code: ${exitCode}`];
        }
      }
    } catch (error) {
      console.warn('Failed to execute onInit command:', error);
    }
  }

  private async initializeIntelliSense(): Promise<void> {
    if (!this.executionEnvironment) return;
    if (this.intelliSenseInitialized) return;

    // Wait for Monaco to be available globally (with retry for timing)
    let monacoInstance = (window as any).monaco;
    if (!monacoInstance) {
      // Monaco loads asynchronously when the editor mounts, wait a bit
      await new Promise(resolve => setTimeout(resolve, 100));
      monacoInstance = (window as any).monaco;
    }

    if (!monacoInstance) {
      console.warn('Monaco not yet loaded, IntelliSense will be initialized later');
      return;
    }

    this.intelliSenseInitialized = true;
    this.intelliSenseManager = new TypeScriptIntelliSenseManager();
    await this.intelliSenseManager.init(monacoInstance, this.executionEnvironment);

    // Set up marker listener for Problems panel
    this.setupMarkerListener();

    // Start watching node_modules for package installations
    this.startNodeModulesWatcher();

    // Initial scan for any existing packages
    await this.intelliSenseManager.scanAndLoadNewPackageTypes();
  }

  /**
   * Watch node_modules for changes (e.g., after pnpm install)
   * and automatically load types for new packages
   */
  private startNodeModulesWatcher(): void {
    if (!this.executionEnvironment || this.nodeModulesWatcher) return;

    try {
      this.nodeModulesWatcher = this.executionEnvironment.watch(
        '/node_modules',
        (_event, _filename) => {
          // Debounce - pnpm install creates many file changes
          if (this.nodeModulesDebounceTimeout) {
            clearTimeout(this.nodeModulesDebounceTimeout);
          }
          this.nodeModulesDebounceTimeout = setTimeout(async () => {
            if (this.intelliSenseManager) {
              await this.intelliSenseManager.scanAndLoadNewPackageTypes();
            }
          }, 2000); // 2 second debounce for package installation
        },
        { recursive: true }
      );
    } catch (error) {
      console.warn('Could not watch node_modules:', error);
    }
  }

  private stopNodeModulesWatcher(): void {
    if (this.nodeModulesWatcher) {
      this.nodeModulesWatcher.stop();
      this.nodeModulesWatcher = null;
    }
    if (this.nodeModulesDebounceTimeout) {
      clearTimeout(this.nodeModulesDebounceTimeout);
      this.nodeModulesDebounceTimeout = null;
    }
  }

  // ========== Open File Watching for External Changes ==========

  /**
   * Start watching an open file for external changes
   */
  private startWatchingFile(path: string): void {
    if (!this.executionEnvironment || this.openFileWatchers.has(path)) return;

    try {
      const watcher = this.executionEnvironment.watch(
        path,
        (_event, _filename) => {
          // Debounce to avoid multiple rapid triggers
          const existingTimeout = this.fileChangeDebounce.get(path);
          if (existingTimeout) {
            clearTimeout(existingTimeout);
          }
          const timeout = setTimeout(() => {
            this.handleExternalFileChange(path);
            this.fileChangeDebounce.delete(path);
          }, 300);
          this.fileChangeDebounce.set(path, timeout);
        }
      );
      this.openFileWatchers.set(path, watcher);
    } catch (error) {
      console.warn(`Could not watch file ${path}:`, error);
    }
  }

  /**
   * Stop watching a file when it's closed
   */
  private stopWatchingFile(path: string): void {
    const watcher = this.openFileWatchers.get(path);
    if (watcher) {
      watcher.stop();
      this.openFileWatchers.delete(path);
    }
    const timeout = this.fileChangeDebounce.get(path);
    if (timeout) {
      clearTimeout(timeout);
      this.fileChangeDebounce.delete(path);
    }
  }

  /**
   * Stop all file watchers
   */
  private stopAllFileWatchers(): void {
    for (const watcher of this.openFileWatchers.values()) {
      watcher.stop();
    }
    this.openFileWatchers.clear();

    for (const timeout of this.fileChangeDebounce.values()) {
      clearTimeout(timeout);
    }
    this.fileChangeDebounce.clear();
  }

  /**
   * Handle external file change - show actionbar if file has local changes,
   * otherwise silently update with cursor preservation
   */
  private async handleExternalFileChange(path: string): Promise<void> {
    const file = this.openFiles.find(f => f.path === path);
    if (!file || !this.executionEnvironment) return;

    try {
      // Read the new content from disk
      const newContent = await this.executionEnvironment.readFile(path);

      // If content is same as what we have, no action needed
      if (newContent === file.content) return;

      if (file.modified) {
        // File has unsaved local changes AND disk changed - conflict!
        const result = await this.actionbarElement?.show({
          message: `"${file.name}" changed on disk. What do you want to do?`,
          type: 'question',
          icon: 'lucide:gitMerge',
          actions: [
            { id: 'load-disk', label: 'Load from Disk', primary: true },
            { id: 'save-local', label: 'Save Local to Disk' },
            { id: 'compare', label: 'Compare' },
          ],
          timeout: { duration: 15000, defaultActionId: 'load-disk' },
          dismissible: true,
        });

        if (result?.actionId === 'load-disk') {
          // Discard local changes, load disk version
          await this.updateFileContent(path, newContent, false);
        } else if (result?.actionId === 'save-local') {
          // Keep local changes and save to disk (overwrite external)
          await this.executionEnvironment.writeFile(path, file.content);
          // Mark as saved
          this.openFiles = this.openFiles.map(f =>
            f.path === path ? { ...f, modified: false } : f
          );
        } else if (result?.actionId === 'compare') {
          // Open diff view
          this.openDiffView(path, file.content, newContent);
        }
        // If dismissed, do nothing - user can manually resolve later
      } else {
        // No local changes - silently update with cursor preservation
        await this.updateFileContent(path, newContent, true);
      }
    } catch (error) {
      console.warn(`Failed to handle external change for ${path}:`, error);
    }
  }

  /**
   * Update file content in state and optionally in the editor
   */
  private async updateFileContent(
    path: string,
    newContent: string,
    preserveCursor: boolean
  ): Promise<void> {
    // Update internal state
    this.openFiles = this.openFiles.map(f =>
      f.path === path ? { ...f, content: newContent, modified: false } : f
    );

    // If this is the active file, update Monaco editor
    if (path === this.activeFilePath) {
      const editor = this.shadowRoot?.querySelector('dees-workspace-monaco') as DeesWorkspaceMonaco;
      if (editor) {
        await editor.setContentExternal(newContent, preserveCursor);
      }
    }
  }

  /**
   * Open the diff view to compare local and disk versions
   */
  private openDiffView(path: string, localContent: string, diskContent: string): void {
    this.diffViewConfig = {
      filePath: path,
      originalContent: diskContent,
      modifiedContent: localContent,
      language: this.getLanguageFromPath(path),
    };
    this.showDiffView = true;
  }

  /**
   * Handle diff view resolution
   */
  private async handleDiffResolved(e: CustomEvent): Promise<void> {
    const { action, content } = e.detail;
    const path = this.diffViewConfig?.filePath;

    if (!path || !this.executionEnvironment) {
      this.showDiffView = false;
      this.diffViewConfig = null;
      return;
    }

    if (action === 'use-local') {
      // Save local content to disk
      await this.executionEnvironment.writeFile(path, content);
      this.openFiles = this.openFiles.map(f =>
        f.path === path ? { ...f, content, modified: false } : f
      );
      // Update editor if active
      if (path === this.activeFilePath) {
        const editor = this.shadowRoot?.querySelector('dees-workspace-monaco') as DeesWorkspaceMonaco;
        if (editor) {
          await editor.setContentExternal(content, false);
        }
      }
    } else if (action === 'use-disk') {
      // Update editor with disk content
      await this.updateFileContent(path, content, false);
    }

    this.showDiffView = false;
    this.diffViewConfig = null;
  }

  private async handleFileSelect(e: CustomEvent<{ path: string; name: string }>) {
    const { path, name } = e.detail;
    await this.openFile(path, name);
  }

  private async openFile(path: string, name: string) {
    // Check if already open
    const existingFile = this.openFiles.find(f => f.path === path);
    if (existingFile) {
      this.activeFilePath = path;
      return;
    }

    // Load file content
    if (!this.executionEnvironment) return;

    try {
      const content = await this.executionEnvironment.readFile(path);
      this.openFiles = [
        ...this.openFiles,
        { path, name, content, modified: false },
      ];
      this.activeFilePath = path;

      // Start watching for external changes
      this.startWatchingFile(path);

      // Initialize IntelliSense lazily after first file opens (Monaco loads on demand)
      if (!this.intelliSenseInitialized) {
        // Wait for Monaco editor to mount and load Monaco from CDN
        await this.updateComplete;
        // Give Monaco time to load via require.js
        await new Promise(resolve => setTimeout(resolve, 500));
        await this.initializeIntelliSense();

        // Process the initial file content for IntelliSense
        const language = this.getLanguageFromPath(path);
        if (this.intelliSenseManager && (language === 'typescript' || language === 'javascript')) {
          await this.intelliSenseManager.processContentChange(content);
        }
      }
    } catch (error) {
      console.error(`Failed to open file ${path}:`, error);
    }
  }

  private activateFile(path: string) {
    this.activeFilePath = path;
  }

  private closeFile(e: Event, path: string) {
    e.stopPropagation();

    const fileIndex = this.openFiles.findIndex(f => f.path === path);
    if (fileIndex === -1) return;

    // Check for unsaved changes
    const file = this.openFiles[fileIndex];
    if (file.modified) {
      const confirmed = confirm(`${file.name} has unsaved changes. Close anyway?`);
      if (!confirmed) return;
    }

    // Stop watching this file
    this.stopWatchingFile(path);

    this.openFiles = this.openFiles.filter(f => f.path !== path);

    // If closing the active file, activate another one
    if (this.activeFilePath === path) {
      if (this.openFiles.length > 0) {
        const newIndex = Math.min(fileIndex, this.openFiles.length - 1);
        this.activeFilePath = this.openFiles[newIndex].path;
      } else {
        this.activeFilePath = '';
      }
    }
  }

  private getActiveFileContent(): string {
    const file = this.openFiles.find(f => f.path === this.activeFilePath);
    return file?.content || '';
  }

  private handleContentChange(e: CustomEvent) {
    const newContent = e.detail;
    const fileIndex = this.openFiles.findIndex(f => f.path === this.activeFilePath);
    if (fileIndex === -1) return;

    const file = this.openFiles[fileIndex];
    if (file.content !== newContent) {
      this.openFiles = [
        ...this.openFiles.slice(0, fileIndex),
        { ...file, content: newContent, modified: true },
        ...this.openFiles.slice(fileIndex + 1),
      ];

      // Process content for IntelliSense (debounced to avoid parsing on every keystroke)
      const language = this.getLanguageFromPath(this.activeFilePath);
      if (this.intelliSenseManager && (language === 'typescript' || language === 'javascript')) {
        if (this.intelliSenseDebounceTimeout) {
          clearTimeout(this.intelliSenseDebounceTimeout);
        }
        this.intelliSenseDebounceTimeout = setTimeout(() => {
          this.intelliSenseManager?.processContentChange(newContent);
        }, 500); // 500ms debounce
      }
    }
  }

  private getLanguageFromPath(path: string): string {
    const ext = path.split('.').pop()?.toLowerCase();
    const languageMap: Record<string, string> = {
      ts: 'typescript',
      tsx: 'typescript',
      js: 'javascript',
      jsx: 'javascript',
      json: 'json',
      html: 'html',
      css: 'css',
      scss: 'scss',
      less: 'less',
      md: 'markdown',
      yaml: 'yaml',
      yml: 'yaml',
      xml: 'xml',
      sql: 'sql',
      py: 'python',
      sh: 'shell',
      bash: 'shell',
    };
    return languageMap[ext || ''] || 'plaintext';
  }

  private toggleTerminal() {
    this.isTerminalCollapsed = !this.isTerminalCollapsed;
  }

  // ========== Save Operations ==========

  public async saveActiveFile(): Promise<void> {
    const file = this.openFiles.find(f => f.path === this.activeFilePath);
    if (!file || !this.executionEnvironment) return;

    try {
      await this.executionEnvironment.writeFile(file.path, file.content);

      // Update file state to mark as saved
      this.openFiles = this.openFiles.map(f =>
        f.path === file.path ? { ...f, modified: false } : f
      );

      // Update IntelliSense manager with latest content
      if (this.intelliSenseManager) {
        this.intelliSenseManager.addFileModel(file.path, file.content);
      }
    } catch (error) {
      console.error('Failed to save file:', error);
    }
  }

  public async saveAllFiles(): Promise<void> {
    if (!this.executionEnvironment) return;

    for (const file of this.openFiles.filter(f => f.modified)) {
      try {
        await this.executionEnvironment.writeFile(file.path, file.content);

        // Update IntelliSense manager
        if (this.intelliSenseManager) {
          this.intelliSenseManager.addFileModel(file.path, file.content);
        }
      } catch (error) {
        console.error(`Failed to save ${file.path}:`, error);
      }
    }

    // Mark all files as saved
    this.openFiles = this.openFiles.map(f => ({ ...f, modified: false }));
  }

  // ========== Editor Menu ==========

  private async showEditorMenu(e: MouseEvent) {
    e.stopPropagation();

    const menuItems: Parameters<typeof DeesContextmenu.openContextMenuWithOptions>[1] = [
      {
        name: this.autoSave ? '✓ Auto Save' : 'Auto Save',
        iconName: 'lucide:save',
        action: async () => this.toggleAutoSave(),
      },
      { divider: true },
      {
        name: 'Save',
        iconName: 'lucide:save',
        action: async () => this.saveActiveFile(),
      },
      {
        name: 'Save All',
        iconName: 'lucide:save',
        action: async () => this.saveAllFiles(),
      },
    ];

    await DeesContextmenu.openContextMenuWithOptions(e, menuItems);
  }

  private toggleAutoSave() {
    this.autoSave = !this.autoSave;

    if (this.autoSave) {
      // Save every 2 seconds if there are changes
      this.autoSaveInterval = setInterval(() => {
        const hasUnsaved = this.openFiles.some(f => f.modified);
        if (hasUnsaved) {
          this.saveAllFiles();
        }
      }, 2000);
    } else {
      if (this.autoSaveInterval) {
        clearInterval(this.autoSaveInterval);
        this.autoSaveInterval = null;
      }
    }
  }

  private getErrorCount(): number {
    // Monaco MarkerSeverity: Error = 8, Warning = 4, Info = 2, Hint = 1
    return this.diagnosticMarkers.filter(m => m.severity === 8).length;
  }

  private renderProblemsPanel(): TemplateResult {
    if (this.diagnosticMarkers.length === 0) {
      return html`
        <div class="problems-empty">
          <dees-icon .icon=${'lucide:checkCircle'} iconSize="24"></dees-icon>
          <span>No problems detected</span>
        </div>
      `;
    }

    return html`
      <div class="problems-list">
        ${this.diagnosticMarkers.map(marker => html`
          <div class="problem-item" @click=${() => this.navigateToProblem(marker)}>
            <dees-icon
              class="problem-icon ${marker.severity === 8 ? 'error' : 'warning'}"
              .icon=${marker.severity === 8 ? 'lucide:circleX' : 'lucide:triangleAlert'}
              iconSize="14"
            ></dees-icon>
            <div class="problem-details">
              <div class="problem-message">${marker.message}</div>
              <div class="problem-location">
                ${marker.resource.path.split('/').pop()} (${marker.startLineNumber}, ${marker.startColumn})
                ${marker.source ? `[${marker.source}]` : ''}
              </div>
            </div>
          </div>
        `)}
      </div>
    `;
  }

  private async navigateToProblem(marker: typeof this.diagnosticMarkers[0]) {
    // Extract file path from resource
    const filePath = marker.resource.path;
    const fileName = filePath.split('/').pop() || '';

    // Open the file if not already open
    const existingFile = this.openFiles.find(f => f.path === filePath);
    if (!existingFile) {
      await this.openFile(filePath, fileName);
    } else {
      this.activeFilePath = filePath;
    }

    // Wait for editor to be ready, then navigate to the line
    await this.updateComplete;
    const editorElement = this.shadowRoot?.querySelector('dees-workspace-monaco') as DeesWorkspaceMonaco;
    if (editorElement) {
      const editor = await editorElement.editorDeferred.promise;
      editor.revealLineInCenter(marker.startLineNumber);
      editor.setPosition({
        lineNumber: marker.startLineNumber,
        column: marker.startColumn,
      });
      editor.focus();
    }
  }

  private setupMarkerListener() {
    const monacoInstance = (window as any).monaco;
    if (!monacoInstance) return;

    // Listen for marker changes
    monacoInstance.editor.onDidChangeMarkers((uris: any[]) => {
      this.updateDiagnosticMarkers();
    });

    // Initial load
    this.updateDiagnosticMarkers();
  }

  private updateDiagnosticMarkers() {
    const monacoInstance = (window as any).monaco;
    if (!monacoInstance) return;

    // Get all markers from Monaco
    const allMarkers = monacoInstance.editor.getModelMarkers({});

    // Transform to our format
    this.diagnosticMarkers = allMarkers.map((m: any) => ({
      message: m.message,
      severity: m.severity,
      startLineNumber: m.startLineNumber,
      startColumn: m.startColumn,
      endLineNumber: m.endLineNumber,
      endColumn: m.endColumn,
      source: m.source,
      resource: { path: m.resource.path },
    }));
  }

  // ========== Bottom Bar Event Handlers ==========

  /**
   * Handle run-process events from bottom bar widgets
   * Creates a new terminal tab for the process
   */
  private async handleRunProcess(e: CustomEvent<IRunProcessEventDetail>): Promise<void> {
    const detail = e.detail;

    // Find the terminal component
    const terminal = this.shadowRoot?.querySelector('dees-workspace-terminal') as DeesWorkspaceTerminal;
    if (!terminal) {
      console.warn('Terminal component not found');
      return;
    }

    // Expand terminal if collapsed
    if (this.isTerminalCollapsed) {
      this.isTerminalCollapsed = false;
    }

    // Switch to terminal panel
    this.activeBottomPanel = 'terminal';

    // Wait for UI update
    await this.updateComplete;

    // Create a new terminal tab for the process
    await terminal.createProcessTab({
      type: detail.type,
      label: detail.label,
      command: detail.command,
      args: detail.args,
      metadata: detail.metadata,
      switchToTab: true,
    });
  }

  // ========== Public Layout Methods ==========

  /**
   * Programmatically set the file tree width
   */
  public setFileTreeWidth(width: number): void {
    const minWidth = 150;
    const maxWidth = this.getBoundingClientRect().width * 0.5;
    this.currentFileTreeWidth = Math.max(minWidth, Math.min(maxWidth, width));
    window.dispatchEvent(new Event('resize'));
  }

  /**
   * Programmatically set the terminal height
   */
  public setTerminalHeight(height: number): void {
    const minHeight = 100;
    const maxHeight = this.getBoundingClientRect().height * 0.7;
    this.currentTerminalHeight = Math.max(minHeight, Math.min(maxHeight, height));
    window.dispatchEvent(new Event('resize'));
  }

  /**
   * Reset layout to initial property values
   */
  public resetLayout(): void {
    this.currentFileTreeWidth = this.fileTreeWidth;
    this.currentTerminalHeight = this.terminalHeight;
    window.dispatchEvent(new Event('resize'));
  }
}
