import { LitElement, html } from 'lit';
import { customElement, property, state } from 'lit/decorators.js';

type HeadingTag = 'p' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
type GenericOption = { value: string; label?: string; icon?: string };
type HeadingOption = { value: HeadingTag; label?: string; icon?: string };
type NormalizedOption = { value: string; label: string; icon?: string };

const HEADING_ALLOWLIST: ReadonlySet<HeadingTag> = new Set([
  'p',
  'h1',
  'h2',
  'h3',
  'h4',
  'h5',
  'h6',
]);

function isHeadingTag(v: string): v is HeadingTag {
  return HEADING_ALLOWLIST.has(v as HeadingTag);
}

@customElement('nile-rte-select')
export class NileRteSelect extends LitElement {
  protected createRenderRoot() {
    return this;
  }

  @property({ type: String, attribute: true, reflect: true }) type = '';

  @property({ type: String, attribute: true, reflect: true }) options = '[]';

  @property({ attribute: false })
  optionsObj?: Array<GenericOption | HeadingOption>;

  @property({ type: String, attribute: true, reflect: true }) label = '';

  @property({ type: Boolean, attribute: true, reflect: true }) disabled = false;

  @state() private selectedValue = '';

  private mapAlignIcon(v: string) {
    const map: Record<string, string> = {
      left: 'format_align_left',
      center: 'format_align_middle',
      right: 'format_align_right',
      justify: 'format_align_justify',
    };
    return map[v] || 'format_align_left';
  }
  private get parsedOptions(): NormalizedOption[] {
    const source: unknown = this.optionsObj ?? this.options;

    let rawArray: any[] = (() => {
      if (Array.isArray(source)) return source;
      try {
        return JSON.parse(String(source));
      } catch {
        return [];
      }
    })();

    if (this.type === 'align' && rawArray.length === 0) {
      rawArray = [
        { value: 'left', label: 'Align Left' },
        { value: 'center', label: 'Align Center' },
        { value: 'right', label: 'Align Right' },
        { value: 'justify', label: 'Justify' },
      ];
    }

    let items: NormalizedOption[] = rawArray.map((o: any) => {
      const value: string = o?.value ?? o;
      const label: string = o?.label ?? o?.value ?? o;
      const icon: string | undefined =
        o?.icon ??
        (this.type === 'align' ? this.mapAlignIcon(String(value)) : undefined);
      return { value, label, icon };
    });

    if (this.type === 'heading') {
      const before = items.length;
      items = items.filter(i => isHeadingTag(i.value));
      if (items.length !== before) {
      }
      if (this.selectedValue && !isHeadingTag(this.selectedValue)) {
        this.selectedValue = '';
      }
    }

    return items;
  }

  private ensureDefault() {
    if (!this.selectedValue) {
      const first = this.parsedOptions[0];
      if (first) this.selectedValue = first.value;
    }
  }

  private onSelect(value: string) {
    if (this.type === 'heading' && !isHeadingTag(value)) {
      console.warn(
        `[nile-rte-select] Ignoring invalid heading value: ${value}`
      );
      return;
    }
    this.selectedValue = value;
    this.dispatchEvent(
      new CustomEvent('change', {
        detail: value,
        bubbles: true,
        composed: true,
      })
    );
  }

  connectedCallback(): void {
    super.connectedCallback();
    this.injectLocalStyles();
  }

  private injectLocalStyles() {
    if (this.querySelector('style[data-rte-select-style]')) return;

    const style = document.createElement('style');
    style.setAttribute('data-rte-select-style', 'true');
    style.textContent = `
      nile-menu.rte-align-menu::part(menu__items-wrapper) {
        display: flex;
      }
      nile-menu.rte-align-menu,
      nile-menu.rte-default-menu {
        margin-top: 0px;
      }
      nile-button.rte-align-trigger::part(base),
      nile-button.rte-default-trigger::part(base) {
        min-width: 32px;
        height: 32px;
        padding: 0px 6px;
        box-shadow: none;
      }
  nile-button.rte-align-trigger::part(base) {

  border: none;
}

 
    `;
    this.insertBefore(style, this.firstChild);
  }

  render() {
    const opts = this.parsedOptions;
    this.ensureDefault();
    const current = opts.find(o => o.value === this.selectedValue);

    if (this.type === 'align') {
      const trigger = current?.icon
        ? html`<nile-icon name="${current.icon}" color=${this.disabled ? 'var(--nile-colors-neutral-500, var(--ng-colors-fg-disabled-subtle))' : 'var(--nile-colors-dark-900, var(--ng-colors-text-primary-900))'} size="20"></nile-icon>`
        : this.label || 'Align';

      return html`
        <nile-dropdown ?disabled=${this.disabled} class="rte-align-dd">
          <nile-button
            slot="trigger"
            variant="tertiary"
            class="rte-align-trigger"
            ?disabled=${this.disabled}
          >
            ${trigger}
          </nile-button>
          <nile-menu class="rte-align-menu">
            ${opts.map(
              o => html`
                <nile-menu-item
                  class="rte-align-item"
                  ?active=${o.value === this.selectedValue}
                  @click=${() => this.onSelect(o.value)}
                >
                  <nile-tooltip hoist content="${o.label}">
                    <nile-icon name="${o.icon}"></nile-icon>
                  </nile-tooltip>
                </nile-menu-item>
              `
            )}
          </nile-menu>
        </nile-dropdown>
      `;
    }

    if (this.type === 'font') {
      const triggerText = current?.label || this.label || 'Font';
      return html`
        <nile-dropdown class="rte-default-dd">
          <nile-button
            slot="trigger"
            variant="tertiary"
            class="rte-default-trigger"
            style="font-family: ${current?.value || 'inherit'}"
          >
            ${triggerText} <nile-icon name="arrowdown"></nile-icon>
          </nile-button>
          <nile-menu class="rte-default-menu">
            ${opts.map(
              o => html`
                <nile-menu-item
                  style="font-family: ${o.value}"
                  ?active=${o.value === this.selectedValue}
                  @click=${() => this.onSelect(o.value)}
                >
                  ${o.label}
                </nile-menu-item>
              `
            )}
          </nile-menu>
        </nile-dropdown>
      `;
    }

    const triggerText = current?.label || this.label || 'Select';
    return html`
      <nile-dropdown class="rte-default-dd">
        <nile-button
          slot="trigger"
          variant="tertiary"
          class="rte-default-trigger"
        >
          ${triggerText} <nile-icon name="arrowdown"></nile-icon>
        </nile-button>
        <nile-menu class="rte-default-menu">
          ${opts.map(
            o => html`
              <nile-menu-item
                ?active=${o.value === this.selectedValue}
                @click=${() => this.onSelect(o.value)}
              >
                ${o.label}
              </nile-menu-item>
            `
          )}
        </nile-menu>
      </nile-dropdown>
    `;
  }
}

declare global {
  interface HTMLElementTagNameMap {
    'nile-rte-select': NileRteSelect;
  }
}
