import {
  DeesElement,
  type TemplateResult,
  property,
  customElement,
  html,
  css,
  cssManager,
} from '@design.estate/dees-element';

import {
  type ITheme,
  type IThemeColors,
  type IThemeSpacing,
  type IThemeRadius,
  type IThemeShadows,
  type IThemeTransitions,
  type IThemeControlHeights,
  themeDefaults,
  themeDefaultStyles,
} from '../00theme.js';

import { demoFunc } from './dees-theme.demo.js';

/**
 * A theme provider component that wraps children and provides CSS custom properties.
 * Can be used at the app root or around specific sections to customize theming.
 *
 * Usage:
 * ```html
 * <dees-theme>
 *   <my-app></my-app>
 * </dees-theme>
 * ```
 *
 * With custom overrides:
 * ```html
 * <dees-theme .customSpacing=${{ lg: '20px' }}>
 *   <my-section></my-section>
 * </dees-theme>
 * ```
 */
@customElement('dees-theme')
export class DeesTheme extends DeesElement {
  public static demo = demoFunc;

  // ============================================
  // Properties for theme overrides
  // ============================================

  @property({ type: Object })
  accessor customSpacing: Partial<IThemeSpacing> | null = null;

  @property({ type: Object })
  accessor customRadius: Partial<IThemeRadius> | null = null;

  @property({ type: Object })
  accessor customShadows: Partial<IThemeShadows> | null = null;

  @property({ type: Object })
  accessor customTransitions: Partial<IThemeTransitions> | null = null;

  @property({ type: Object })
  accessor customControlHeights: Partial<IThemeControlHeights> | null = null;

  // ============================================
  // Styles
  // ============================================

  public static styles = [
    themeDefaultStyles,
    cssManager.defaultStyles,
    css`
      :host {
        display: contents;
      }
    `,
  ];

  // ============================================
  // Render
  // ============================================

  public render(): TemplateResult {
    return html`
      <style>
        ${this.generateCustomStyles()}
      </style>
      <slot></slot>
    `;
  }

  // ============================================
  // Private Methods
  // ============================================

  private generateCustomStyles(): string {
    const styles: string[] = [':host {'];

    // Custom spacing
    if (this.customSpacing) {
      for (const [key, value] of Object.entries(this.customSpacing)) {
        if (value) {
          styles.push(`  --dees-spacing-${key}: ${value};`);
        }
      }
    }

    // Custom radius
    if (this.customRadius) {
      for (const [key, value] of Object.entries(this.customRadius)) {
        if (value) {
          styles.push(`  --dees-radius-${key}: ${value};`);
        }
      }
    }

    // Custom shadows
    if (this.customShadows) {
      for (const [key, value] of Object.entries(this.customShadows)) {
        if (value) {
          styles.push(`  --dees-shadow-${key}: ${value};`);
        }
      }
    }

    // Custom transitions
    if (this.customTransitions) {
      for (const [key, value] of Object.entries(this.customTransitions)) {
        if (value) {
          const cssKey = key === 'default' ? 'default' : key;
          styles.push(`  --dees-transition-${cssKey}: ${value};`);
        }
      }
    }

    // Custom control heights
    if (this.customControlHeights) {
      for (const [key, value] of Object.entries(this.customControlHeights)) {
        if (value) {
          styles.push(`  --dees-control-height-${key}: ${value};`);
        }
      }
    }

    styles.push('}');
    return styles.join('\n');
  }

  // ============================================
  // Public API Methods
  // ============================================

  /**
   * Set a spacing value dynamically
   */
  public setSpacing(key: keyof IThemeSpacing, value: string): void {
    this.customSpacing = { ...this.customSpacing, [key]: value };
  }

  /**
   * Set a radius value dynamically
   */
  public setRadius(key: keyof IThemeRadius, value: string): void {
    this.customRadius = { ...this.customRadius, [key]: value };
  }

  /**
   * Set a shadow value dynamically
   */
  public setShadow(key: keyof IThemeShadows, value: string): void {
    this.customShadows = { ...this.customShadows, [key]: value };
  }

  /**
   * Set a transition value dynamically
   */
  public setTransition(key: keyof IThemeTransitions, value: string): void {
    this.customTransitions = { ...this.customTransitions, [key]: value };
  }

  /**
   * Set a control height value dynamically
   */
  public setControlHeight(key: keyof IThemeControlHeights, value: string): void {
    this.customControlHeights = { ...this.customControlHeights, [key]: value };
  }

  /**
   * Get the current theme configuration (defaults + overrides)
   */
  public getTheme(): ITheme {
    return {
      colors: themeDefaults.colors,
      spacing: { ...themeDefaults.spacing, ...this.customSpacing },
      radius: { ...themeDefaults.radius, ...this.customRadius },
      shadows: { ...themeDefaults.shadows, ...this.customShadows },
      transitions: { ...themeDefaults.transitions, ...this.customTransitions },
      controlHeights: { ...themeDefaults.controlHeights, ...this.customControlHeights },
    };
  }

  /**
   * Reset all custom overrides to defaults
   */
  public resetToDefaults(): void {
    this.customSpacing = null;
    this.customRadius = null;
    this.customShadows = null;
    this.customTransitions = null;
    this.customControlHeights = null;
  }

  /**
   * Apply a complete theme object
   */
  public applyTheme(theme: Partial<ITheme>): void {
    if (theme.spacing) this.customSpacing = theme.spacing;
    if (theme.radius) this.customRadius = theme.radius;
    if (theme.shadows) this.customShadows = theme.shadows;
    if (theme.transitions) this.customTransitions = theme.transitions;
    if (theme.controlHeights) this.customControlHeights = theme.controlHeights;
  }
}
