import {
  DeesElement,
  property,
  css,
  type CSSResult,
  cssManager,
} from '@design.estate/dees-element';
import * as domtools from '@design.estate/dees-domtools';

/**
 * Base class for all dees-input components
 * Provides unified margin system and layout mode support
 */
export abstract class DeesInputBase<T = any> extends DeesElement {
  /**
   * Layout mode for the input component
   * - vertical: Traditional form layout (label on top)
   * - horizontal: Inline layout (label position configurable)
   * - auto: Detect from parent context
   */
  @property({ type: String })
  accessor layoutMode: 'vertical' | 'horizontal' | 'auto' = 'auto';

  /**
   * Position of the label relative to the input
   */
  @property({ type: String })
  accessor labelPosition: 'top' | 'left' | 'right' | 'none' = 'top';

  /**
   * Common properties for all inputs
   */
  @property({ type: String })
  accessor key: string;

  @property({ type: String })
  accessor label: string;

  @property({ type: Boolean })
  accessor required: boolean = false;

  @property({ type: Boolean })
  accessor disabled: boolean = false;

  @property({ type: String })
  accessor description: string;

  /**
   * Common styles for all input components
   */
  public static get baseStyles(): CSSResult[] {
    return [
      css`
        /* CSS Variables for consistent spacing */
        :host {
          --dees-input-spacing-unit: 8px;
          --dees-input-vertical-gap: calc(var(--dees-input-spacing-unit) * 2); /* 16px */
          --dees-input-horizontal-gap: calc(var(--dees-input-spacing-unit) * 2); /* 16px */
          --dees-input-label-gap: var(--dees-input-spacing-unit); /* 8px */
        }

        /* Default vertical stacking mode (for forms) */
        :host {
          display: block;
          margin: 0;
          margin-bottom: var(--dees-input-vertical-gap);
        }

        /* Last child in container should have no bottom margin */
        :host(:last-child) {
          margin-bottom: 0;
        }

        /* Horizontal layout mode - activated by attribute */
        :host([layout-mode="horizontal"]) {
          display: inline-block;
          margin: 0;
          margin-right: var(--dees-input-horizontal-gap);
          margin-bottom: 0;
        }

        :host([layout-mode="horizontal"]:last-child) {
          margin-right: 0;
        }

        /* Auto mode - inherit from parent dees-form if present */

        /* Label position variations */
        :host([label-position="left"]) .input-wrapper {
          display: grid;
          grid-template-columns: auto 1fr;
          gap: var(--dees-input-label-gap);
          align-items: center;
        }

        :host([label-position="right"]) .input-wrapper {
          display: grid;
          grid-template-columns: 1fr auto;
          gap: var(--dees-input-label-gap);
          align-items: center;
        }

        :host([label-position="top"]) .input-wrapper {
          display: block;
        }

        :host([label-position="none"]) dees-label {
          display: none;
        }
      `,
    ];
  }

  /**
   * Subject for value changes that all inputs should implement
   */
  public changeSubject = new domtools.plugins.smartrx.rxjs.Subject<T>();

  /**
   * Called when the element is connected to the DOM
   * Sets up layout mode detection
   */
  async connectedCallback() {
    await super.connectedCallback();
    this.detectLayoutMode();
  }

  /**
   * Detects the appropriate layout mode based on parent context
   */
  private detectLayoutMode() {
    if (this.layoutMode !== 'auto') {
      this.setAttribute('layout-mode', this.layoutMode);
      return;
    }

    // Check if parent is a form with horizontal layout
    const parentForm = this.closest('dees-form');
    if (parentForm && parentForm.hasAttribute('horizontal-layout')) {
      this.setAttribute('layout-mode', 'horizontal');
    } else {
      this.setAttribute('layout-mode', 'vertical');
    }
  }

  /**
   * Updates the layout mode attribute when property changes
   */
  updated(changedProperties: Map<string, any>) {
    super.updated(changedProperties);
    
    if (changedProperties.has('layoutMode')) {
      this.detectLayoutMode();
    }

    if (changedProperties.has('labelPosition')) {
      this.setAttribute('label-position', this.labelPosition);
    }
  }

  /**
   * Standard method for freezing input (disabling)
   */
  public async freeze() {
    this.disabled = true;
  }

  /**
   * Standard method for unfreezing input (enabling)
   */
  public async unfreeze() {
    this.disabled = false;
  }

  /**
   * Abstract method that child classes must implement to get their value
   */
  public abstract getValue(): any;

  /**
   * Abstract method that child classes must implement to set their value
   */
  public abstract setValue(value: any): void;
}