import { BaseBlockHandler, type IBlockEventHandlers } from '../block.base.js';
import type { IBlock } from '../../wysiwyg.types.js';
import { cssManager } from '@design.estate/dees-element';

/**
 * HTMLBlockHandler - Handles raw HTML content with preview/edit toggle
 * 
 * Features:
 * - Live HTML preview (sandboxed)
 * - Edit/preview mode toggle
 * - Syntax highlighting in edit mode
 * - HTML validation hints
 * - Auto-save on mode switch
 */
export class HtmlBlockHandler extends BaseBlockHandler {
  type = 'html';
  
  render(block: IBlock, isSelected: boolean): string {
    const isEditMode = block.metadata?.isEditMode ?? true;
    const content = block.content || '';
    
    return `
      <div class="html-block-container${isSelected ? ' selected' : ''}" 
           data-block-id="${block.id}"
           data-edit-mode="${isEditMode}">
        <div class="html-header">
          <div class="html-icon">&lt;/&gt;</div>
          <div class="html-title">HTML</div>
          <button class="html-toggle-mode" title="${isEditMode ? 'Preview' : 'Edit'}">
            ${isEditMode ? '👁️' : '✏️'}
          </button>
        </div>
        <div class="html-content">
          ${isEditMode ? this.renderEditor(content) : this.renderPreview(content)}
        </div>
      </div>
    `;
  }
  
  private renderEditor(content: string): string {
    return `
      <textarea class="html-editor" 
                placeholder="Enter HTML content..."
                spellcheck="false">${this.escapeHtml(content)}</textarea>
    `;
  }
  
  private renderPreview(content: string): string {
    return `
      <div class="html-preview">
        ${content || '<div class="preview-empty">No content to preview</div>'}
      </div>
    `;
  }
  
  setup(element: HTMLElement, block: IBlock, handlers: IBlockEventHandlers): void {
    const container = element.querySelector('.html-block-container') as HTMLElement;
    const toggleBtn = element.querySelector('.html-toggle-mode') as HTMLButtonElement;
    
    if (!container || !toggleBtn) {
      console.error('HtmlBlockHandler: Could not find required elements');
      return;
    }
    
    // Initialize metadata
    if (!block.metadata) block.metadata = {};
    if (block.metadata.isEditMode === undefined) block.metadata.isEditMode = true;
    
    // Toggle mode button
    toggleBtn.addEventListener('click', (e) => {
      e.preventDefault();
      e.stopPropagation();
      
      // Save current content if in edit mode
      if (block.metadata.isEditMode) {
        const editor = container.querySelector('.html-editor') as HTMLTextAreaElement;
        if (editor) {
          block.content = editor.value;
        }
      }
      
      // Toggle mode
      block.metadata.isEditMode = !block.metadata.isEditMode;
      
      // Request UI update
      handlers.onRequestUpdate?.();
    });
    
    // Setup based on mode
    if (block.metadata.isEditMode) {
      this.setupEditor(element, block, handlers);
    } else {
      this.setupPreview(element, block, handlers);
    }
  }
  
  private setupEditor(element: HTMLElement, block: IBlock, handlers: IBlockEventHandlers): void {
    const editor = element.querySelector('.html-editor') as HTMLTextAreaElement;
    if (!editor) return;
    
    // Focus handling
    editor.addEventListener('focus', () => handlers.onFocus());
    editor.addEventListener('blur', () => handlers.onBlur());
    
    // Content changes
    editor.addEventListener('input', () => {
      block.content = editor.value;
      this.validateHtml(editor.value);
    });
    
    // Keyboard shortcuts
    editor.addEventListener('keydown', (e) => {
      // Tab handling for indentation
      if (e.key === 'Tab') {
        e.preventDefault();
        const start = editor.selectionStart;
        const end = editor.selectionEnd;
        const value = editor.value;
        
        if (e.shiftKey) {
          // Unindent
          const beforeCursor = value.substring(0, start);
          const lastNewline = beforeCursor.lastIndexOf('\n');
          const lineStart = lastNewline + 1;
          const lineContent = value.substring(lineStart, start);
          
          if (lineContent.startsWith('  ')) {
            editor.value = value.substring(0, lineStart) + lineContent.substring(2) + value.substring(start);
            editor.selectionStart = editor.selectionEnd = start - 2;
          }
        } else {
          // Indent
          editor.value = value.substring(0, start) + '  ' + value.substring(end);
          editor.selectionStart = editor.selectionEnd = start + 2;
        }
        
        block.content = editor.value;
        return;
      }
      
      // Auto-close tags (Ctrl/Cmd + /)
      if ((e.ctrlKey || e.metaKey) && e.key === '/') {
        e.preventDefault();
        this.autoCloseTag(editor);
        block.content = editor.value;
        return;
      }
      
      // Pass other key events to handlers
      handlers.onKeyDown(e);
    });
    
    // Auto-resize
    this.autoResize(editor);
    editor.addEventListener('input', () => this.autoResize(editor));
  }
  
  private setupPreview(element: HTMLElement, block: IBlock, handlers: IBlockEventHandlers): void {
    const container = element.querySelector('.html-block-container') as HTMLElement;
    const preview = element.querySelector('.html-preview') as HTMLElement;
    
    if (!container || !preview) return;
    
    // Make preview focusable
    preview.setAttribute('tabindex', '0');
    
    // Focus handling
    preview.addEventListener('focus', () => handlers.onFocus());
    preview.addEventListener('blur', () => handlers.onBlur());
    
    // Keyboard navigation
    preview.addEventListener('keydown', (e) => {
      // Switch to edit mode on Enter
      if (e.key === 'Enter' && !e.shiftKey) {
        e.preventDefault();
        block.metadata.isEditMode = true;
        handlers.onRequestUpdate?.();
        return;
      }
      
      handlers.onKeyDown(e);
    });
    
    // Sandbox styles and scripts in preview
    this.sandboxContent(preview);
  }
  
  private autoCloseTag(editor: HTMLTextAreaElement): void {
    const cursorPos = editor.selectionStart;
    const text = editor.value;
    
    // Find the opening tag
    let tagStart = cursorPos;
    while (tagStart > 0 && text[tagStart - 1] !== '<') {
      tagStart--;
    }
    
    if (tagStart > 0) {
      const tagContent = text.substring(tagStart, cursorPos);
      const tagMatch = tagContent.match(/^(\w+)/);
      
      if (tagMatch) {
        const tagName = tagMatch[1];
        const closingTag = `</${tagName}>`;
        
        // Insert closing tag
        editor.value = text.substring(0, cursorPos) + '>' + closingTag + text.substring(cursorPos);
        editor.selectionStart = editor.selectionEnd = cursorPos + 1;
      }
    }
  }
  
  private autoResize(editor: HTMLTextAreaElement): void {
    editor.style.height = 'auto';
    editor.style.height = editor.scrollHeight + 'px';
  }
  
  private validateHtml(html: string): boolean {
    // Basic HTML validation
    const openTags: string[] = [];
    const tagRegex = /<\/?([a-zA-Z][a-zA-Z0-9]*)\b[^>]*>/g;
    let match;
    
    while ((match = tagRegex.exec(html)) !== null) {
      const isClosing = match[0].startsWith('</');
      const tagName = match[1].toLowerCase();
      
      if (isClosing) {
        if (openTags.length === 0 || openTags[openTags.length - 1] !== tagName) {
          console.warn(`Mismatched closing tag: ${tagName}`);
          return false;
        }
        openTags.pop();
      } else if (!match[0].endsWith('/>')) {
        // Not a self-closing tag
        openTags.push(tagName);
      }
    }
    
    if (openTags.length > 0) {
      console.warn(`Unclosed tags: ${openTags.join(', ')}`);
      return false;
    }
    
    return true;
  }
  
  private sandboxContent(preview: HTMLElement): void {
    // Remove any script tags
    const scripts = preview.querySelectorAll('script');
    scripts.forEach(script => script.remove());
    
    // Remove event handlers
    const allElements = preview.querySelectorAll('*');
    allElements.forEach(el => {
      // Remove all on* attributes
      Array.from(el.attributes).forEach(attr => {
        if (attr.name.startsWith('on')) {
          el.removeAttribute(attr.name);
        }
      });
    });
    
    // Prevent forms from submitting
    const forms = preview.querySelectorAll('form');
    forms.forEach(form => {
      form.addEventListener('submit', (e) => {
        e.preventDefault();
        e.stopPropagation();
      });
    });
  }
  
  private escapeHtml(text: string): string {
    const div = document.createElement('div');
    div.textContent = text;
    return div.innerHTML;
  }
  
  getContent(element: HTMLElement): string {
    const editor = element.querySelector('.html-editor') as HTMLTextAreaElement;
    if (editor) {
      return editor.value;
    }
    
    // If in preview mode, return the stored content
    const container = element.querySelector('.html-block-container');
    const blockId = container?.getAttribute('data-block-id');
    // In real implementation, would need access to block data
    return '';
  }
  
  setContent(element: HTMLElement, content: string): void {
    const editor = element.querySelector('.html-editor') as HTMLTextAreaElement;
    if (editor) {
      editor.value = content;
      this.autoResize(editor);
    }
  }
  
  getCursorPosition(element: HTMLElement): number | null {
    const editor = element.querySelector('.html-editor') as HTMLTextAreaElement;
    return editor ? editor.selectionStart : null;
  }
  
  setCursorToStart(element: HTMLElement): void {
    const editor = element.querySelector('.html-editor') as HTMLTextAreaElement;
    if (editor) {
      editor.selectionStart = editor.selectionEnd = 0;
      editor.focus();
    } else {
      this.focus(element);
    }
  }
  
  setCursorToEnd(element: HTMLElement): void {
    const editor = element.querySelector('.html-editor') as HTMLTextAreaElement;
    if (editor) {
      const length = editor.value.length;
      editor.selectionStart = editor.selectionEnd = length;
      editor.focus();
    } else {
      this.focus(element);
    }
  }
  
  focus(element: HTMLElement): void {
    const editor = element.querySelector('.html-editor') as HTMLTextAreaElement;
    if (editor) {
      editor.focus();
    } else {
      const preview = element.querySelector('.html-preview') as HTMLElement;
      preview?.focus();
    }
  }
  
  focusWithCursor(element: HTMLElement, position: 'start' | 'end' | number = 'end'): void {
    const editor = element.querySelector('.html-editor') as HTMLTextAreaElement;
    if (editor) {
      if (position === 'start') {
        this.setCursorToStart(element);
      } else if (position === 'end') {
        this.setCursorToEnd(element);
      } else if (typeof position === 'number') {
        editor.selectionStart = editor.selectionEnd = position;
        editor.focus();
      }
    } else {
      this.focus(element);
    }
  }
  
  getSplitContent(element: HTMLElement): { before: string; after: string } | null {
    const editor = element.querySelector('.html-editor') as HTMLTextAreaElement;
    if (!editor) return null;
    
    const cursorPos = editor.selectionStart;
    return {
      before: editor.value.substring(0, cursorPos),
      after: editor.value.substring(cursorPos)
    };
  }
  
  getStyles(): string {
    return `
      /* HTML Block Container */
      .html-block-container {
        position: relative;
        margin: 12px 0;
        border: 1px solid ${cssManager.bdTheme('#e5e7eb', '#374151')};
        border-radius: 6px;
        overflow: hidden;
        transition: all 0.15s ease;
        background: ${cssManager.bdTheme('#ffffff', '#111827')};
      }
      
      .html-block-container.selected {
        border-color: ${cssManager.bdTheme('#9ca3af', '#6b7280')};
      }
      
      /* Header */
      .html-header {
        display: flex;
        align-items: center;
        gap: 8px;
        padding: 8px 12px;
        border-bottom: 1px solid ${cssManager.bdTheme('#e5e7eb', '#374151')};
        background: ${cssManager.bdTheme('#f9fafb', '#0a0a0a')};
      }
      
      .html-icon {
        font-size: 14px;
        font-weight: 600;
        opacity: 0.8;
        font-family: 'Monaco', 'Consolas', 'Courier New', monospace;
      }
      
      .html-title {
        flex: 1;
        font-size: 13px;
        font-weight: 500;
        color: ${cssManager.bdTheme('#374151', '#e5e7eb')};
      }
      
      .html-toggle-mode {
        padding: 4px 8px;
        background: transparent;
        border: 1px solid ${cssManager.bdTheme('#e5e7eb', '#374151')};
        border-radius: 4px;
        font-size: 14px;
        cursor: pointer;
        transition: all 0.15s ease;
      }
      
      .html-toggle-mode:hover {
        background: ${cssManager.bdTheme('#f3f4f6', '#1f2937')};
        border-color: ${cssManager.bdTheme('#d1d5db', '#4b5563')};
      }
      
      /* Content */
      .html-content {
        position: relative;
        min-height: 120px;
      }
      
      /* Editor */
      .html-editor {
        width: 100%;
        min-height: 120px;
        padding: 12px;
        background: transparent;
        border: none;
        outline: none;
        resize: none;
        font-family: 'Monaco', 'Consolas', 'Courier New', monospace;
        font-size: 13px;
        line-height: 1.6;
        color: ${cssManager.bdTheme('#1f2937', '#f3f4f6')};
        overflow: hidden;
      }
      
      .html-editor::placeholder {
        color: ${cssManager.bdTheme('#9ca3af', '#6b7280')};
      }
      
      /* Preview */
      .html-preview {
        padding: 12px;
        min-height: 96px;
        outline: none;
        font-size: 14px;
        line-height: 1.6;
        color: ${cssManager.bdTheme('#1f2937', '#f3f4f6')};
      }
      
      .preview-empty {
        color: ${cssManager.bdTheme('#9ca3af', '#6b7280')};
        font-style: italic;
      }
      
      /* Sandboxed HTML preview styles */
      .html-preview * {
        max-width: 100%;
      }
      
      .html-preview img {
        height: auto;
      }
      
      .html-preview a {
        color: ${cssManager.bdTheme('#3b82f6', '#60a5fa')};
        text-decoration: none;
      }
      
      .html-preview a:hover {
        text-decoration: underline;
      }
      
      .html-preview table {
        border-collapse: collapse;
        width: 100%;
        margin: 8px 0;
      }
      
      .html-preview th,
      .html-preview td {
        border: 1px solid ${cssManager.bdTheme('#e5e7eb', '#374151')};
        padding: 8px;
        text-align: left;
      }
      
      .html-preview th {
        background: ${cssManager.bdTheme('#f9fafb', '#1f2937')};
        font-weight: 600;
      }
      
      .html-preview pre {
        background: ${cssManager.bdTheme('#f3f4f6', '#1f2937')};
        padding: 12px;
        border-radius: 4px;
        overflow-x: auto;
        margin: 8px 0;
      }
      
      .html-preview code {
        background: ${cssManager.bdTheme('#f3f4f6', '#1f2937')};
        padding: 2px 4px;
        border-radius: 3px;
        font-family: 'Monaco', 'Consolas', 'Courier New', monospace;
        font-size: 0.9em;
      }
      
      .html-preview pre code {
        background: transparent;
        padding: 0;
      }
    `;
  }
}