import * as plugins from '../plugins.js';

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

// third party catalogs
import '@uptime.link/webwidget';

import '@design.estate/dees-catalog';
import { DeesForm, DeesFormSubmit, DeesInputText } from '@design.estate/dees-catalog';
import { IdpState } from '../states/idp.state.js';

declare global {
  interface HTMLElementTagNameMap {
    'idp-registrationprompt': IdpRegistrationPrompt;
  }
}

@customElement('idp-registrationprompt')
export class IdpRegistrationPrompt extends DeesElement {
  public static demo = () => html`<idp-login></idp-login>`;

  @property()
  accessor productOfInterest: string;

  @property()
  accessor jwt: string;

  @property({
    reflect: true,
    type: Object,
  })
  accessor appData: plugins.idpInterfaces.data.IApp;

  public jwtObserable = new domtools.plugins.smartrx.rxjs.Subject<string>();

  constructor() {
    super();
    domtools.elementBasic.setup();
  }

  public static styles = [
    cssManager.defaultStyles,
    css`
      :host {
        --foreground: hsl(0 0% 98%);
        --muted-foreground: hsl(240 5% 64.9%);

        font-family: 'Geist Sans', -apple-system, BlinkMacSystemFont, sans-serif;
        display: block;
        color: var(--foreground);
      }

      .form-header {
        margin-bottom: 32px;
        text-align: center;
      }

      .form-header h2 {
        font-size: 24px;
        font-weight: 600;
        color: var(--foreground);
        margin: 0 0 8px 0;
        letter-spacing: -0.02em;
      }

      .form-header p {
        font-size: 14px;
        color: var(--muted-foreground);
        margin: 0;
      }

      dees-form {
        display: flex;
        flex-direction: column;
        gap: 16px;
      }

      .form-footer {
        margin-top: 24px;
        text-align: center;
        font-size: 14px;
        color: var(--muted-foreground);
      }

      .form-footer a {
        color: var(--foreground);
        text-decoration: none;
        font-weight: 500;
        cursor: pointer;
        transition: opacity 0.15s ease;
      }

      .form-footer a:hover {
        opacity: 0.8;
      }
    `,
  ];

  public render(): TemplateResult {
    return html`
      <idp-centercontainer>
        <div class="form-header">
          <h2>Create your account</h2>
          <p>Get started with your permanent identity</p>
        </div>
        <dees-form
          id="registrationForm"
          @formData="${(eventArg) => {
            this.register({
              emailAddress: eventArg.detail.data.emailAddress,
            });
          }}"
        >
          <dees-input-text
            .required=${true}
            key="emailAddress"
            label="Email Address"
          ></dees-input-text>
          <dees-input-checkbox
            .label="${'I agree to the Terms and Conditions'}"
            .required=${true}
          ></dees-input-checkbox>
          <dees-form-submit>Send Verification Email</dees-form-submit>
        </dees-form>
        <div class="form-footer">
          Already have an account? <a @click=${async () => {
            const idpState = await IdpState.getSingletonInstance();
            idpState.domtools.router.pushUrl('/login');
          }}>Sign in</a>
        </div>
      </idp-centercontainer>
    `;
  }

  public async firstUpdated() {
    await this.domtoolsPromise;
    const idpState = await IdpState.getSingletonInstance();
    const loggedIn = await idpState.idpClient.determineLoginStatus();
    if (loggedIn) {
      idpState.domtools.router.pushUrl('/');
    }
    const loginForm: DeesForm = this.shadowRoot.querySelector('#loginForm');
    const loginPasswordInput: DeesInputText = loginForm.querySelector('#loginPasswordInput');
    const loginSubmitButton: DeesFormSubmit = loginForm.querySelector('#loginSubmitButton');
    const setButtonText = async () => {
      if (loginPasswordInput.value) {
        console.log('updating text of registrationprompt.');
        loginSubmitButton.text = 'Login';
      } else {
        loginSubmitButton.text = 'Send magic link (or enter password)';
      }
    };
    loginForm.changeSubject.subscribe(() => {
      console.log(`checking button text ${loginPasswordInput.value}`);
      setButtonText();
    });
    setButtonText();
  }

  private register = async (valueArg: { emailAddress: string }) => {
    const registrationForm: DeesForm = this.shadowRoot.querySelector('#registrationForm');
    registrationForm.setStatus('pending', 'registering...');
    const firstSignupRequest =
      new domtools.TypedRequest<plugins.idpInterfaces.request.IReq_FirstRegistration>(
        '/typedrequest',
        'firstRegistrationRequest'
      );
    const response = await firstSignupRequest
      .fire({
        email: valueArg.emailAddress,
        productSlugOfInterest: this.productOfInterest,
      })
      .catch((err) => {
        registrationForm.setStatus('error', err.message);
        return null;
      });
    if (response.status === 'ok') {
      registrationForm.setStatus('success', 'Please check your email!');
    }
    console.log(response);
  };

  public async dispatchJwt(jwtArg?: string) {
    if (jwtArg !== undefined) {
      console.log(`dispatching jwt from loginprompt.`);
      this.jwt = jwtArg;
      await domtools.plugins.smartdelay.delayFor(200);
      this.dispatchEvent(
        new CustomEvent('leleLoginGotJwt', {
          detail: {
            jwt: this.jwt,
          },
        })
      );
      this.jwtObserable.next(this.jwt);
    }
  }

  public async handleRefreshToken(refreshTokenArg: string, delayDispatchMillisArg = 0) {
    // a refreshToken binds directly to a session.
    // the refresh token is used on a continuous basis to get fresh and short-lived jwts
    const refreshJwt = new domtools.TypedRequest<plugins.idpInterfaces.request.IReq_RefreshJwt>(
      '/typedrequest',
      'refreshJwt'
    );
    const responseJwt = await refreshJwt.fire({
      refreshToken: refreshTokenArg,
    });

    if (responseJwt.jwt) {
      this.domtools.convenience.smartdelay.delayFor(delayDispatchMillisArg).then(() => {
        this.dispatchJwt(responseJwt.jwt);
      });
      return responseJwt.jwt;
    } else {
      return null;
    }
  }

  public async show() {
    await this.updateComplete;
    const centerContainer = this.shadowRoot.querySelector('idp-centercontainer');
    await centerContainer.show();
  }

  public async hide() {
    await this.updateComplete;
    const centerContainer = this.shadowRoot.querySelector('idp-centercontainer');
    await centerContainer.hide();
  }
}
