// FSLContainer.ts

function copyText(text: string): Promise<string> {
  if (navigator.clipboard) {
    return navigator.clipboard
      .writeText(text)
      .then(() => {
        return text;
      })
      .catch((error) => {
        return error;
      });
  }
  if (Reflect.has(document, 'execCommand')) {
    return new Promise<string>((resolve, reject) => {
      try {
        const textArea = document.createElement('textarea');
        textArea.value = text;
        // 在手机 Safari 浏览器中，点击复制按钮，整个页面会跳动一下
        textArea.style.width = '0';
        textArea.style.position = 'fixed';
        textArea.style.left = '-999px';
        textArea.style.top = '10px';
        textArea.setAttribute('readonly', 'readonly');
        document.body.appendChild(textArea);
        textArea.select();
        document.execCommand('copy');
        document.body.removeChild(textArea);

        resolve(text);
      } catch (error: any) {
        reject(error);
      }
    });
  }
  return Promise.reject(
    `"navigator.clipboard" 或 "document.execCommand" 中存在API错误, 拷贝失败!`,
  );
}

const formatEmail = (email: string | undefined) => {
  if (!email) {
    return '';
  }
  const [name, company] = email.split('@');
  let suffix = company;
  if (company && company.length > 11) {
    suffix = `***${company.slice(-11)}`;
  }
  if (name.length > 3) {
    return `${name.slice(0, 2)}***${name.slice(-1)}@${suffix}`;
  }
  return email;
};

export class FSLContainer extends HTMLElement {
  static get observedAttributes() {
    return ['avatar', 'name'];
  }

  avatar: string = '/assets/avatar.png';
  name: string = 'fsl@gmail.com';
  isPC: boolean = true;
  noCompress: boolean = true;
  copy: ((text: string) => void) | null = null;
  close: ((id: string) => void) | null = null;

  shadow: ShadowRoot;

  constructor() {
    super();
    document.body.style.margin = '0';
    this.shadow = this.attachShadow({ mode: 'open' });
  }

  connectedCallback() {
    this.updateState();
    this.render();
    window.addEventListener('resize', this.updateState.bind(this));
  }

  disconnectedCallback() {
    window.removeEventListener('resize', this.updateState.bind(this));
  }

  attributeChangedCallback(
    name: string,
    oldVal: string | ((text?: string) => void) | null,
    newVal: string | ((text?: string) => void) | null,
  ) {
    console.log('newVal', newVal);
    if (oldVal !== newVal) {
      if (typeof newVal === 'string') {
        this[name as 'avatar' | 'name'] = newVal;
      } else {
        this[name as 'copy' | 'close'] = newVal;
      }
      this.render();
    }
  }

  updateState() {
    const clientWidth = document.documentElement.clientWidth;
    const clientHeight = document.documentElement.clientHeight;
    this.isPC = clientWidth > 1024;
    this.noCompress = clientHeight > 844;
    this.render();
  }

  render() {
    this.shadow.innerHTML = `
      <style>
        :host {
          display: block;
          height: 100vh;
          min-width: 390px;
          position: relative;
        }

        .appContainer {
          background: url(/assets/background.png) center center/cover no-repeat;
          height: 100vh;
        }

        .appContainer::after {
          position: absolute;
          content: '';
          width: 100%;
          height: 100%;
          top: 0;
          left: 0;
          background: rgba(0, 0, 0, 0.5);
          z-index: 1;
        }

        .main {
          position: relative;
          z-index: 10;
          height: 100%;
          overflow: auto;
        }

        .centerContainer {
          display: flex;
          flex-direction: column;
          justify-content: center;
          min-height: 842px;
          position: relative;
          ${this.noCompress ? 'top: 50%; transform: translateY(-50%);' : ''}
        }

        .phoneFrame {
          width: 390px;
          height: 844px;
          ${this.isPC ? 'border: 1px solid #ddd;' : ''}
          border-radius: 30px;
          overflow: hidden;
          margin: 0 auto;
          background: white;
        }

        .header {
          display: flex;
          justify-content: space-between;
          align-items: center;
          padding: 32px 20px 0;
          color: #0E0F0C;
          background: #fff;
        }

        .header .left {
          display: flex;
          align-items: center;
        }

        .header .left img.avatar {
          width: 40px;
          height: 40px;
          border-radius: 50%;
        }

        .header .left span {
          margin-left: 10px;
          font-weight: 600;
        }

        .header .left img.copy {
          margin-left: 10px;
          width: 20px;
          cursor: pointer;
        }

        .header .right {
          display: flex;
          align-items: center;
        }

        .header .right img.close {
          width: 38px;
          cursor: pointer;
        }

        .page {
          flex: 1;
          padding: 20px 16px;
          overflow: auto;
          background: #fff;

        }

        .scroll-container {
          overflow: auto;
        }
        .container {
          position: relative;
          height: 100%;
          display: flex;
          flex-direction: column;
        }
      </style>

      <div class="appContainer">
        <div class="main">
          ${
            this.isPC
              ? `
            <div class="centerContainer">
              <div class="phoneFrame">
                ${this.renderContent()}
              </div>
            </div>`
              : `
            <div class="phoneFrame" style="width: 100%; height: 100%; border-radius: 0;">
              ${this.renderContent()}
            </div>`
          }
        </div>
      </div>
    `;

    this.shadow.querySelector('.copy')?.addEventListener('click', () => {
      copyText(this.name);
      this.copy?.(this.name);
    });

    this.shadow.querySelector('.close')?.addEventListener('click', () => {
      const uid = new URLSearchParams(location.search).get('uid');
      if (this.close) {
        this.close(uid!);
        return;
      }
      location.href = `https://id.fsl.com/application?uid=${uid}`;
    });
  }

  renderContent() {
    const maskedName = formatEmail(this.name);
    return `
      <div class="container">
      <div class="header">
        <div class="left">
          <img class="avatar" src="${this.avatar}" alt="avatar" />
          <span>${maskedName}</span>
          <img class="copy" src="/assets/copy.svg" alt="copy" />
        </div>
        <div class="right">
          <slot name="expand"></slot>
          <img class="close" src="/assets/close.svg" alt="close" />
        </div>
      </div>
      <div class="page scroll-container">
        <slot></slot>
      </div>
      </div>
    `;
  }
}
