import { ndk } from '@/ndk';
import type { ArxInputChangeEvent } from '@components/General/Input';
import type { NDKEvent } from '@nostr-dev-kit/ndk';
import * as nip19 from '@nostr/tools/nip19';
import { LitElement, css, html } from 'lit';
import { customElement, property, state } from 'lit/decorators.js';
import { classMap } from 'lit/directives/class-map.js';
import { keyed } from 'lit/directives/keyed.js';
import { map } from 'lit/directives/map.js';
import { when } from 'lit/directives/when.js';

import '@components/General/Input';
import '@components/HeaderSugestion';

@customElement('arx-header')
export class Header extends LitElement {
  @property({ type: String }) override title = 'Eve';
  @property({ type: String }) url = 'eve://home';
  @property({ type: Boolean }) canGoBack = false;
  @property({ type: Boolean }) canGoForward = false;

  private searchQuery = '';
  private _debounceTimeout?: ReturnType<typeof setTimeout>;

  @state() private showSuggestions = false;
  @state() private events: NDKEvent[] = [];
  @state() private suggestions: NDKEvent[] = [];

  static override styles = css`
    :host {
      display: block;
      z-index: 999999;
    }

    header {
      background: var(--color-primary);
      backdrop-filter: blur(10px);
      height: var(--font-2xl, 3rem);
      font-size: var(--font-md, 1rem);
      transition: all 0.3s ease;
      display: flex;
      align-items: space-between;
      padding: 0 var(--space-md, 1rem);
    }

    .nav-buttons {
      display: flex;
      gap: var(--space-xs, 0.5rem);
      padding: 0 var(--space-xs, 0.5rem);
    }

    button {
      text-decoration: none;
      color: var(--color-primary-content);
      background: oklch(from var(--color-primary-content) l c h / 0.1);
      border: var(--border) solid
        oklch(from var(--color-primary-content) l c h / 0.2);
      padding: var(--space-xs, 0.5rem);
      border-radius: 50%;
      font-size: var(--font-md, 1rem);
      backdrop-filter: blur(10px);
      display: flex;
      align-items: center;
      justify-content: center;
      transition: all 0.2s ease;
      &:hover {
        background: oklch(from var(--color-primary-content) l c h / 0.2);
        transform: translateY(-2px);
        box-shadow: calc(var(--depth) * 2px) calc(var(--depth) * 2px)
          calc(var(--depth) * 4px)
          oklch(from var(--color-base-content) l c h / 0.15);
      }
      &:active {
        transform: translateY(1px);
      }

      &.disabled {
        opacity: 0.5;
        pointer-events: none;
      }
    }

    .search-container {
      flex: 1;
      position: relative;
    }

    arx-input {
      transform: translateY(3px);
    }

    .suggestions {
      position: absolute;
      top: 100%;
      left: 0;
      right: 0;
      background: oklch(from var(--color-base-100) l c h / 0.9);
      backdrop-filter: blur(10px);
      border: var(--border) solid var(--color-base-200);
      border-top: none;
      border-radius: 0 0 var(--radius-field) var(--radius-field);
      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);
      z-index: 9999;
      max-height: 200px;
      overflow-y: auto;
      overflow-x: hidden;
    }
  `;

  override firstUpdated() {
    ndk
      .fetchEvents({
        limit: 50_000,
      })
      .then((events) => {
        this.events = [...events];
      });
  }

  override render() {
    return html`
      <header>
        <div class="nav-buttons">
          <button
            class=${classMap({ disabled: !this.canGoBack })}
            @click=${this._handleGoBack}
            aria-label="Go back"
          >
            <iconify-icon icon="material-symbols:arrow-back"></iconify-icon>
          </button>
          <button
            class=${classMap({ disabled: !this.canGoForward })}
            @click=${this._handleGoForward}
            aria-label="Go forward"
          >
            <iconify-icon icon="material-symbols:arrow-forward"></iconify-icon>
          </button>
          <button @click=${this._handleGoHome} aria-label="Home">
            <iconify-icon icon="material-symbols:home"></iconify-icon>
          </button>
        </div>
        <div class="search-container">
          <arx-input
            type="text"
            .value=${this.searchQuery}
            placeholder=${this.url}
            @keyup=${this._handleSearch}
            @focus=${this._handleFocus}
            @change=${this._handleInput}
          ></arx-input>
          ${when(
            this.showSuggestions,
            () => html`
              <div class="suggestions">
                ${map(this.suggestions, (suggestion: NDKEvent) =>
                  keyed(
                    suggestion.id,
                    html`
                      <arx-header-suggestion
                        .event=${suggestion}
                        .allEvents=${this.events}
                        @click=${() => this._handleSuggestionClick(suggestion)}
                      ></arx-header-suggestion>
                    `,
                  ),
                )}
              </div>
            `,
          )}
        </div>
        <div class="nav-buttons">
          <button @click=${this._goToWallet}>
            <iconify-icon icon="arx:wallet"></iconify-icon>
          </button>
        </div>
      </header>
    `;
  }

  private _goToWallet() {
    window.location.hash = 'wallet';
  }

  private _handleFocus() {
    this.showSuggestions = true;
  }

  private _handleInput(e: ArxInputChangeEvent) {
    this.searchQuery = e.detail.value;
    if (this._debounceTimeout) {
      clearTimeout(this._debounceTimeout);
    }

    if (!this.searchQuery.trim()) {
      this.suggestions = [];
      this.showSuggestions = false;
      return;
    }

    this._debounceTimeout = setTimeout(() => {
      const query = this.searchQuery.toLowerCase();

      const isNoteSearch = query.startsWith('note1');
      const isEventSearch = query.startsWith('nevent1');
      const isPubkeySearch = query.startsWith('npub1');

      this.suggestions = this.events
        .filter((event: NDKEvent) => {
          if (event.kind === 11 || event.kind === 1111) return false; // hide old forum events
          if (event.kind === 30890 || event.kind === 30891) return false; // ignore old-in-dev events
          if (event.kind === 60890) return false; // don't include the actual forum
          if (event.kind === 60891) {
            const categoryId = event.tags.find((tag) => tag[0] === 'd')?.[1] || '';
            const forum = this.events.find(
              (e) => e.kind === 60890 && e.tags.some((tag) => tag[0] === 'forum' && tag[1] === `60891:${categoryId}`),
            );
            if (!forum) return false; // ignore orphan forum categories
          }

          if (event.id.includes(query)) return true;

          if (isNoteSearch) {
            const noteId = nip19.noteEncode(event.id);
            return noteId.includes(query);
          }

          if (isEventSearch) {
            const eventId = event.encode();
            return eventId.includes(query);
          }

          if (isPubkeySearch && event.kind === 0) {
            const pubkey = nip19.npubEncode(event.pubkey);
            return pubkey.includes(query);
          }

          if (event.content.toLowerCase().includes(query)) return true;
          return event.tags.some((tag) => tag.length > 1 && tag[1].toLowerCase().includes(query));
        })
        .slice(0, 20);

      this.showSuggestions = this.suggestions.length > 0;
    }, 50);
    this.showSuggestions = true;
  }

  private _handleSearch(e: KeyboardEvent) {
    if (e.key !== 'Enter') return;

    this.showSuggestions = false;

    if (this.searchQuery.startsWith('npub1')) {
      try {
        const { type } = nip19.decode(this.searchQuery);
        if (type === 'npub') {
          window.location.hash = `profile/${this.searchQuery}`;
          return;
        }
      } catch (e) {}
    }

    const hash = this.searchQuery.replace('eve://', '#');
    window.location.hash = hash;
  }

  private _handleGoBack() {
    this.dispatchEvent(new CustomEvent('go-back'));
  }

  private _handleGoForward() {
    this.dispatchEvent(new CustomEvent('go-forward'));
  }

  private _handleGoHome() {
    window.location.hash = '#';
  }

  private _handleSuggestionClick(suggestion: NDKEvent) {
    window.location.hash = '#';
    this.showSuggestions = false;
    console.log(suggestion);
    switch (suggestion.kind) {
      case 0:
        window.location.hash = `profile/${suggestion.pubkey}`;
        break;
      case 60890:
      case 60891:
        window.location.hash = 'arbor';
        break;
      case 892:
        window.location.hash = `arbor/threads/${suggestion.id}`;
        break;
      case 893: {
        const threadId = suggestion.tags.find((tag) => tag[0] === 'E')?.[1]!;
        window.location.hash = `arbor/threads/${threadId}`;
        break;
      }
      default:
        window.location.hash = `event/${suggestion.id}`;
    }
  }
}
