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

@customElement('arx-button')
export class StyledButton extends LitElement {
  @property() label = '';
  @property() type: 'button' | 'submit' | 'reset' | 'menu' = 'button';
  @property({ type: Boolean }) disabled = false;
  @property() name = '';
  @property() value = '';
  @property() variant: 'default' | 'primary' | 'secondary' | 'accent' = 'default';
  @property({ type: Boolean }) loading = false;
  @property({ type: Boolean }) fullWidth = false;
  @property({ type: Boolean, reflect: true }) pressed = false;
  @property({ type: String }) href = '';

  static override styles = css`
    :host {
      display: inline-block;
      position: relative;
    }

    :host([fullWidth]) {
      display: block;
      width: 100%;
    }

    button {
      --bg: var(--color-base-100);
      --text: var(--color-base-content);

      position: relative;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      gap: 8px;
      min-height: 46px;
      padding: 10px 24px;
      font-size: 16px;
      font-weight: 500;
      font-family: inherit;
      color: var(--text);
      background: var(--bg);
      border: var(--border) solid var(--color-base-300);
      border-radius: var(--radius-selector);
      cursor: pointer;
      transition: all 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);
      box-shadow: calc(var(--depth) * 3px) calc(var(--depth) * 3px)
          calc(var(--depth) * 6px)
          oklch(from var(--color-base-content) l c h / 0.15),
        calc(var(--depth) * -3px) calc(var(--depth) * -3px)
          calc(var(--depth) * 6px) oklch(from var(--color-base-100) l c h / 0.7);
      overflow: hidden;
      outline: none;
    }

    :host([variant="primary"]) button {
      --bg: var(--color-primary);
      --text: var(--color-primary-content);
    }

    :host([variant="secondary"]) button {
      --bg: var(--color-secondary);
      --text: var(--color-secondary-content);
    }

    :host([variant="accent"]) button {
      --bg: var(--color-accent);
      --text: var(--color-accent-content);
    }

    :host([fullWidth]) button {
      width: 100%;
    }

    button:hover,
    button:focus-visible {
      transform: translateY(-2px);
      background: oklch(from var(--bg) calc(l + 0.02) c h);
      box-shadow: calc(var(--depth) * 4px) calc(var(--depth) * 4px)
          calc(var(--depth) * 8px)
          oklch(from var(--color-base-content) l c h / 0.2),
        calc(var(--depth) * -4px) calc(var(--depth) * -4px)
          calc(var(--depth) * 8px) oklch(from var(--color-base-100) l c h / 0.8);
    }

    button:active,
    :host([pressed]) button {
      transform: translateY(1px);
      border-top: var(--border) solid
        oklch(from var(--color-base-300) l c h / 0.8);
      border-left: var(--border) solid
        oklch(from var(--color-base-300) l c h / 0.8);
      border-bottom: var(--border) solid
        oklch(from var(--color-base-200) l c h / 0.8);
      border-right: var(--border) solid
        oklch(from var(--color-base-200) l c h / 0.8);
      box-shadow: inset calc(var(--depth) * 3px) calc(var(--depth) * 3px)
          calc(var(--depth) * 5px)
          oklch(from var(--color-base-content) l c h / 0.2),
        inset calc(var(--depth) * -1px) calc(var(--depth) * -1px)
          calc(var(--depth) * 3px) oklch(from var(--color-base-100) l c h / 0.5);
      background: linear-gradient(
        145deg,
        oklch(from var(--bg) calc(l - 0.03) c h),
        oklch(from var(--bg) l c h)
      );
    }

    button:disabled {
      opacity: 0.7;
      cursor: not-allowed;
      transform: none;
      box-shadow: calc(var(--depth) * 1px) calc(var(--depth) * 1px)
          calc(var(--depth) * 3px)
          oklch(from var(--color-base-content) l c h / 0.1),
        calc(var(--depth) * -1px) calc(var(--depth) * -1px)
          calc(var(--depth) * 3px) oklch(from var(--color-base-100) l c h / 0.4);
    }

    .spinner {
      display: none;
      position: relative;
      width: 18px;
      height: 18px;
    }

    :host([loading]) .spinner {
      display: inline-block;
    }

    :host([loading]) .label {
      opacity: 0.7;
    }

    .spinner::before {
      content: "";
      box-sizing: border-box;
      position: absolute;
      top: 0;
      left: 0;
      width: 18px;
      height: 18px;
      border-radius: 50%;
      border: 2px solid transparent;
      border-top-color: currentColor;
      border-right-color: currentColor;
      animation: spinner 0.8s linear infinite;
    }

    @keyframes spinner {
      to {
        transform: rotate(360deg);
      }
    }

    ::slotted([slot="prefix"]) {
      margin-right: 4px;
    }

    ::slotted([slot="suffix"]) {
      margin-left: 4px;
    }
  `;

  override render() {
    return html`
      <button
        type=${this.type}
        ?disabled=${this.disabled || this.loading}
        name=${this.name}
        value=${this.value}
        @click=${this._handleClick}
        @keydown=${this._handleKeyDown}
        @focus=${this._handleFocus}
        @blur=${this._handleBlur}
      >
        <slot name="prefix"></slot>
        <div class="spinner"></div>
        <slot name="label">
          <span class="label">${this.label}</span>
        </slot>
        <slot name="suffix"></slot>
      </button>
    `;
  }

  private _handleClick(e: MouseEvent) {
    e.preventDefault();
    e.stopPropagation();
    if (this.disabled || this.loading) {
      return;
    }

    if (this.href) {
      let href = this.href;
      if (href.startsWith('javascript:')) return href;
      if (href.startsWith('eve://')) href = href.replace('eve://', '#');
      if (href.startsWith('/')) href = href.replace('/', '#');
      if (!href.startsWith('#')) href = `#${href}`;
      window.location.href = href;
      return;
    }

    this.dispatchEvent(
      new CustomEvent('click', {
        detail: {
          name: this.name,
          value: this.value,
        },
        bubbles: false,
        composed: false,
      }),
    );
    return;
  }

  private _handleKeyDown(e: KeyboardEvent) {
    if ((e.key === 'Enter' || e.key === ' ') && !this.disabled && !this.loading) {
      e.preventDefault();
      this.dispatchEvent(
        new CustomEvent('click', {
          detail: {
            name: this.name,
            value: this.value,
          },
          bubbles: true,
          composed: true,
        }),
      );
    }

    this.dispatchEvent(
      new CustomEvent('keydown', {
        detail: { key: e.key },
        bubbles: true,
        composed: true,
      }),
    );
  }

  private _handleFocus() {
    this.dispatchEvent(
      new CustomEvent('focus', {
        bubbles: true,
        composed: true,
      }),
    );
  }

  private _handleBlur() {
    this.dispatchEvent(
      new CustomEvent('blur', {
        bubbles: true,
        composed: true,
      }),
    );
  }
}
