import type { ArxInputChangeEvent } from '@components/General/Input';
import { animate } from '@lit-labs/motion';
import { randomBytes } from '@noble/ciphers/webcrypto';
import * as nip06 from '@nostr/tools/nip06';
import * as nip49 from '@nostr/tools/nip49';
import * as nostrTools from '@nostr/tools/pure';
import { encodeBase64 } from '@std/encoding/base64';
import { LitElement, css, html } from 'lit';
import { customElement, state } from 'lit/decorators.js';
import { when } from 'lit/directives/when.js';

import { ndk, setSigner } from '@/ndk';
import '@components/General/Button';
import '@components/General/Fieldset';
import '@components/General/Input';
import '@components/LoadingView';
import '@components/ProgressSteps';
import '@components/RelayLogs';
import '@components/Setup/CCNList';
import { NDKEvent, NDKKind, NDKPrivateKeySigner, NDKRelay, NDKRelaySet } from '@nostr-dev-kit/ndk';
import { nip19 } from '@nostr/tools';

@customElement('arx-initial-setup')
export class InitialSetup extends LitElement {
  @state() private currentPage = 1;
  @state() private isAnimating = false;
  @state() private seedPhrase = '';
  @state() private communityName = '';
  @state() private userName = '';
  @state() private profileImage = '';
  @state() private lightningAddress = '';
  @state() private relayStatus: { running: boolean; pid: number | null; logs: string[] } = {
    running: false,
    pid: null,
    logs: [],
  };
  @state() private selectedCCN: string | undefined;
  @state() private ccnList: { name: string; pubkey: string }[] = [];

  private readonly pageLabels = ['Welcome', 'Relay Setup', 'Seed Phrase', 'Profile', 'Complete'];

  get encryptionPassphrase() {
    let encryptionPassphrase = localStorage.getItem('encryption_key');
    if (!encryptionPassphrase) {
      encryptionPassphrase = encodeBase64(randomBytes(32));
      localStorage.setItem('encryption_key', encryptionPassphrase);
    }
    return encryptionPassphrase;
  }

  static override styles = css`
    :host {
      display: block;
      width: 100%;
      font-family: system-ui, -apple-system, sans-serif;
      -webkit-font-smoothing: antialiased;
      color: var(--color-base-content);

      --spacing-unit: 0.25rem;
    }

    .welcome-container {
      max-width: min(800px, 90vw);
      margin: 0 auto;
      padding: calc(var(--spacing-unit) * 8);
      animation: fadeIn var(--transition);
    }

    section {
      margin-bottom: calc(var(--spacing-unit) * 12);
    }

    .alpha-badge {
      display: inline-flex;
      align-items: center;
      background: var(--color-accent);
      color: var(--color-accent-content);
      padding: 0.15em 0.5em;
      border-radius: 999px;
      font-size: 0.75em;
      font-weight: 500;
      text-transform: uppercase;
      letter-spacing: 0.05em;
    }

    h1,
    h2,
    h3 {
      margin: 0;
      line-height: 1.2;
    }

    h1 {
      font-size: clamp(2rem, 5vw, 2.5rem);
      font-weight: 700;
      background: linear-gradient(
        45deg,
        var(--color-accent),
        oklch(from var(--color-accent) l calc(c * 1.2) h)
      );
      -webkit-background-clip: text;
      background-clip: text;
      color: transparent;
      margin-bottom: calc(var(--spacing-unit) * 8);
    }

    h2 {
      font-size: clamp(1.5rem, 3vw, 1.75rem);
      font-weight: 600;
      margin-bottom: calc(var(--spacing-unit) * 4);
      color: var(--color-base-content);
    }

    h3 {
      font-size: 1.25rem;
      font-weight: 600;
      margin-bottom: calc(var(--spacing-unit) * 4);
      color: var(--color-base-content);
    }

    p {
      margin: 0 0 calc(var(--spacing-unit) * 4);
      line-height: 1.6;
      color: var(--color-secondary);
    }

    .input-group {
      display: flex;
      gap: calc(var(--spacing-unit) * 4);
      margin-top: calc(var(--spacing-unit) * 6);
    }

    .navigation {
      display: flex;
      justify-content: space-between;
      margin-top: calc(var(--spacing-unit) * 8);
    }

    @keyframes fadeIn {
      from {
        opacity: 0;
        transform: translateY(20px);
      }
      to {
        opacity: 1;
        transform: translateY(0);
      }
    }

    @media (max-width: 640px) {
      .welcome-container {
        padding: calc(var(--spacing-unit) * 4);
      }
    }

    pre {
      background-color: var(--color-base-200);
      padding: calc(var(--spacing-unit) * 4);
      border-radius: var(--radius-field);
    }

    code {
      white-space: pre;
      font-family: monospace;
      background-color: var(--color-base-200);
      padding: calc(var(--spacing-unit) * 1) calc(var(--spacing-unit) * 2);
      border-radius: var(--radius-field);
    }

    .note {
      display: block;
      color: var(--color-secondary);
      font-size: 0.875rem;
      margin-top: 0.5rem;
      padding-left: 0.5rem;
      border-left: var(--border) solid var(--color-base-300);
      font-style: italic;
      line-height: 1.4;
      max-width: 600px;
      opacity: 0.9;
      transition: all 0.2s ease;
    }

    .note:hover {
      opacity: 1;
      border-left-color: var(--color-accent);
    }

    .external-link {
      color: var(--color-accent);
      text-decoration: none;
      font-weight: 500;
      transition: color 0.2s ease;
      position: relative;
    }

    .external-link:hover {
      color: oklch(from var(--color-accent) l calc(c * 1.2) h);
      text-decoration: underline;
    }

    .external-link:after {
      content: "↗";
      display: inline-block;
      margin-left: 0.25rem;
      font-size: 0.875rem;
    }
  `;

  private handleNavigation(page: number) {
    if (this.isAnimating) return;
    this.isAnimating = true;
    this.currentPage = page;
    setTimeout(() => {
      this.isAnimating = false;
    }, 300);
  }

  private nextStep() {
    if (this.currentPage === 1) return this.handleNavigation(2);
    if (this.currentPage === 2) {
      if (this.selectedCCN) return this.handleNavigation(4);
      return this.handleNavigation(3);
    }
    if (this.currentPage === 3) return this.handleNavigation(4);
    if (this.currentPage === 4) return this.goToFinalStep();
  }

  private previousStep() {
    if (this.currentPage === 2) return this.handleNavigation(1);
    if (this.currentPage === 3) return this.handleNavigation(2);
    if (this.currentPage === 4) return this.handleNavigation(3);
  }

  private onSeedPhraseInput(event: ArxInputChangeEvent) {
    this.seedPhrase = event.detail.value;
  }

  private onCommunityNameInput(event: ArxInputChangeEvent) {
    this.communityName = event.detail.value;
  }

  private generateSeedPhrase() {
    this.seedPhrase = nip06.generateSeedWords();
  }

  private isValidSeedPhrase() {
    const words = this.seedPhrase.split(' ');
    if (words.length !== 12) return false;
    if (!nip06.validateWords(words.join(' '))) return false;
    return true;
  }

  private isValidCommunityName() {
    const trimmedName = this.communityName.trim();
    return trimmedName.length > 0;
  }

  private renderWelcomePage() {
    return html`
      <main class="welcome-container" ${animate()}>
        <arx-progress-steps
          .currentPage=${this.currentPage}
          .pageLabels=${this.pageLabels}
        ></arx-progress-steps>
        <section>
          <h1>Welcome to Eve</h1>
          <h2>Your Private Community Network</h2>
          <p>
            Connect, share, and engage with your community in a secure,
            members-only space designed just for you.
          </p>
        </section>

        <section>
          <div class="alpha-badge">
            <iconify-icon icon="mdi:alpha"></iconify-icon> Alpha Preview
          </div>
          <p>
            We're actively developing Eve to create the best possible
            experience. Your feedback helps shape our platform.
          </p>
        </section>

        <div class="navigation">
          <span></span>
          <arx-button
            variant="primary"
            label="Next"
            @click=${() => this.nextStep()}
          ></arx-button>
        </div>
      </main>
    `;
  }

  private renderRelaySetupPage() {
    return html`
      <main class="welcome-container" ${animate()}>
        <arx-progress-steps
          .currentPage=${this.currentPage}
          .pageLabels=${this.pageLabels}
        ></arx-progress-steps>
        <section>
          <h2>Configure Eve Relay</h2>
          <p>
            During this alpha phase, manual relay configuration is required.
            This process will be automated in future releases.
          </p>
          <p>Please press the button below to start the relay.</p>
          <arx-button
            variant="primary"
            label=${this.relayStatus.running ? 'Relay Running' : 'Start Relay'}
            ?disabled=${this.relayStatus.running}
            @click=${() => this.startRelay()}
          >
            ${when(
              this.relayStatus.running,
              () => html`<iconify-icon slot="prefix" icon="mdi:check-circle"></iconify-icon>`,
            )}
          </arx-button>
          ${when(
            this.relayStatus.running,
            () => html`
              <p class="note">
              <iconify-icon icon="mdi:information"></iconify-icon>
              Relay is running with PID: ${this.relayStatus.pid}
            </p>
            <arx-relay-logs .logs=${this.relayStatus.logs}></arx-relay-logs>
            <arx-setup-ccn-list @ccn-selected=${this.onCCNSelected} .ccns=${this.ccnList}></arx-setup-ccn-list>`,
          )}
          <p>
            Having trouble? Our team is here to help if you encounter any
            issues.
          </p>
          <p>Click Continue once the relay is running.</p>
        </section>

        <div class="navigation">
          <arx-button
            @click=${() => this.previousStep()}
            variant="secondary"
            label="Back"
          >
          </arx-button>
          <arx-button
            @click=${() => this.nextStep()}
            variant="primary"
            ?disabled=${!this.relayStatus.running}
            label=${this.selectedCCN ? 'Continue' : 'Create CCN'}
          >
          </arx-button>
        </div>
      </main>
    `;
  }

  private onCCNSelected(e: CustomEvent<{ ccn: string }>) {
    this.selectedCCN = e.detail.ccn;
  }

  private async startRelay() {
    await window.relay.start(this.encryptionPassphrase);
    await this.updateRelayStatus();
    await new Promise((resolve) => {
      const ws = new WebSocket('ws://localhost:6942');
      ws.onopen = () => {
        ws.send(JSON.stringify(['CCN', 'LIST']));
      };
      ws.onmessage = ({ data }) => {
        const responseData = JSON.parse(data);
        if (responseData[0] !== 'OK' || responseData[1] !== 'CCN LIST' || responseData[2] !== true) return;
        this.ccnList = JSON.parse(responseData[3]);
        resolve(true);
        ws.close();
      };
      ws.onerror = () => {
        resolve(false);
      };
    });
  }

  private async updateRelayStatus() {
    this.relayStatus = await window.relay.getStatus();
    if (this.relayStatus.running) setTimeout(() => this.updateRelayStatus(), 2000);
  }

  private async createCCN() {
    await new Promise((resolve) => {
      const ws = new WebSocket('ws://localhost:6942');
      ws.onopen = () => {
        ws.send(
          JSON.stringify([
            'CCN',
            'CREATE',
            {
              name: this.communityName,
              seed: this.seedPhrase,
            },
          ]),
        );
      };
      ws.onmessage = ({ data }) => {
        const responseData = JSON.parse(data);
        if (responseData[0] !== 'OK' || responseData[1] !== 'CCN CREATED' || responseData[2] !== true) return;
        resolve(true);
        ws.close();
        this.selectedCCN = JSON.parse(responseData[3]).pubkey;
      };
      ws.onerror = () => {
        resolve(false);
      };
    });
    this.handleNavigation(4);
  }

  private renderSeedPhrasePage() {
    return html`
      <main class="welcome-container" ${animate()}>
        <arx-progress-steps
          .currentPage=${this.currentPage}
          .pageLabels=${this.pageLabels}
        ></arx-progress-steps>
        <section>
          <h1>Getting Started</h1>
          <h2>Creating a Community</h2>
          <p>
            Connect with others by joining an existing community or creating
            your own.
          </p>
          <p>
            During this alpha phase, community setup requires a few manual
            steps. We're actively working to streamline this process in future
            updates.
          </p>
        </section>

        <section>
          <h3>Seed Phrase</h3>
          <p>
            Enter your community's seed phrase below or generate a new one to
            create a community.
          </p>
          <p>
            <b>Important</b>: Keep your seed phrase secure. Anyone with access
            to it can join your community.
          </p>
          <p>
            In an upcoming release, we'll implement MLS (Messaging Layer
            Security) to enable simpler invitation-based community access, as
            well as improve your community's security.
          </p>
          <div class="input-group">
            <arx-input
              @change=${this.onSeedPhraseInput}
              .value=${this.seedPhrase}
              id="seed-input"
              type="text"
              placeholder="Enter seed phrase..."
            ></arx-input>
            <arx-button
              @click=${() => this.generateSeedPhrase()}
              label="Generate"
              variant="secondary"
            >
            </arx-button>
          </div>
        </section>

        <section>
          <h3>Community Name</h3>

          <p>
            Enter a name for your community. This will be used to identify your
            community in Eve
          </p>

          <arx-input
            type="text"
            placeholder="Enter Community Name..."
            .value=${this.communityName}
            @change=${this.onCommunityNameInput}
          ></arx-input>
        </section>

        <div class="navigation">
          <arx-button
            @click=${() => this.previousStep()}
            label="Back"
            variant="secondary"
          >
          </arx-button>
          <arx-button
            @click=${() => this.createCCN()}
            ?disabled=${!this.isValidSeedPhrase() || !this.isValidCommunityName()}
            label="Continue"
            variant="primary"
          >
          </arx-button>
        </div>
      </main>
    `;
  }

  private onUserNameInput(e: CustomEvent<{ value: string }>) {
    this.userName = e.detail.value;
  }

  private onProfileImageInput(e: CustomEvent<{ value: string }>) {
    this.profileImage = e.detail.value;
  }

  private renderProfileSetupPage() {
    return html`
      <main class="welcome-container" ${animate()}>
        <arx-progress-steps
          .currentPage=${this.currentPage}
          .pageLabels=${this.pageLabels}
        ></arx-progress-steps>
        <section>
          <h2>Complete Your Profile</h2>
          <p>Great progress! Let's set up your community profile.</p>
          <p>
            Your profile information will be encrypted and visible only to
            community members.
          </p>
          <div class="profile-form">
            <arx-fieldset legend="Your Name">
              <arx-input
                id="username"
                type="text"
                .value=${this.userName}
                @change=${this.onUserNameInput}
                placeholder="Enter your name"
              ></arx-input>
            </arx-fieldset>
            <arx-fieldset legend="Profile Picture">
              <arx-input
                id="profile-image"
                type="text"
                .value=${this.profileImage}
                @change=${this.onProfileImageInput}
                placeholder="Enter image URL"
              ></arx-input>
              <small class="note">
                Direct file uploads will be supported in a future update. For
                now, please provide an image URL or leave blank.
              </small>
            </arx-fieldset>
          </div>
        </section>
        <div class="navigation">
          <arx-button
            @click=${() => this.previousStep()}
            variant="secondary"
            label="Back"
          >
          </arx-button>
          <arx-button
            @click=${() => this.nextStep()}
            variant="primary"
            label="Next"
          >
          </arx-button>
        </div>
      </main>
    `;
  }

  private async goToFinalStep() {
    await new Promise((resolve) => {
      const ws = new WebSocket('ws://localhost:6942');
      ws.onopen = () => {
        ws.send(
          JSON.stringify([
            'CCN',
            'ACTIVATE',
            {
              pubkey: this.selectedCCN,
            },
          ]),
        );
      };
      ws.onmessage = ({ data }) => {
        const responseData = JSON.parse(data);
        if (responseData[0] !== 'OK' || responseData[1] !== 'CCN ACTIVATED' || responseData[2] !== true) return;
        resolve(true);
      };
      ws.onerror = () => {
        resolve(false);
      };
    });
    const randomPrivateKey = nostrTools.generateSecretKey();
    const encryptedNsec = nip49.encrypt(randomPrivateKey, this.encryptionPassphrase);
    const npub = nip19.npubEncode(nostrTools.getPublicKey(randomPrivateKey));
    this.lightningAddress = `${npub}@npub.cash`;
    setSigner(new NDKPrivateKeySigner(randomPrivateKey));
    await ndk.connect(10000);
    const event = new NDKEvent(ndk);
    event.kind = NDKKind.Metadata;
    event.content = JSON.stringify({
      name: this.userName,
      image: this.profileImage || undefined,
      lud16: this.lightningAddress,
    });
    await event.sign();
    const relaySet = new NDKRelaySet(new Set([new NDKRelay('ws://localhost:6942', undefined, ndk)]), ndk);
    await event.publish(relaySet, 10000);
    localStorage.setItem('ncryptsec', encryptedNsec);
    this.handleNavigation(5);
  }

  private renderFinalPage() {
    return html`
      <main class="welcome-container" ${animate()}>
        <arx-progress-steps
          .currentPage=${this.currentPage}
          .pageLabels=${this.pageLabels}
        ></arx-progress-steps>
        <section>
          <h2>Done!</h2>
          <p>
            That's it! You're all set to start using the community. We hope you
            enjoy it!
          </p>
          <p>Your community's seed phrase is: <b>${this.seedPhrase}</b></p>
          <p>
            Please store this seed phrase somewhere safe and secure. It will be
            required to invite new members to the community.
          </p>
          <p>Your username is: <b>${this.userName}</b></p>
          ${when(this.profileImage, () => html`<p>Your profile image is: <img .src=${this.profileImage} /></p>`)}
          <p>Your lightning address is: <b>${this.lightningAddress}</b></p>
        </section>

        <div class="navigation">
          <arx-button
            @click=${() => this.previousStep()}
            variant="secondary"
            label="Back"
          >
          </arx-button>
          <arx-button
            variant="accent"
            label="Finish"
            @click=${this.finish}
          ></arx-button>
        </div>
      </main>
    `;
  }

  finish() {
    this.dispatchEvent(
      new CustomEvent('finish', {
        detail: {
          userName: this.userName,
          profileImage: this.profileImage,
          lightningAddress: this.lightningAddress,
        },
        bubbles: true,
        composed: true,
      }),
    );
  }

  override render() {
    switch (this.currentPage) {
      case 1:
        return this.renderWelcomePage();
      case 2:
        return this.renderRelaySetupPage();
      case 3:
        return this.renderSeedPhrasePage();
      case 4:
        return this.renderProfileSetupPage();
      case 5:
        return this.renderFinalPage();
      default:
        return html`<div class="welcome-container">
          <arx-loading-view></arx-loading-view>
        </div>`;
    }
  }
}
