(() => {
  const DEFAULT_BASE_URL = (() => {
    try {
      return new URL(document.currentScript?.src || window.location.href).origin;
    } catch {
      return window.location.origin;
    }
  })();

  const STYLE = `
    :host {
      display: block;
      width: var(--rbw-width, 100%);
      height: var(--rbw-height, 260px);
    }
    .frame {
      position: relative;
      width: 100%;
      height: 100%;
      overflow: hidden;
      border-radius: var(--rbw-radius, 14px);
      background: #eef2f7;
      border: 1px solid rgba(15, 23, 42, 0.08);
      box-shadow: 0 10px 28px rgba(15, 23, 42, 0.06);
    }
    img {
      position: absolute;
      inset: 0;
      width: 100%;
      height: 100%;
      object-fit: var(--rbw-fit, cover);
      filter: blur(var(--rbw-blur, 0px));
      transform: scale(1.04);
      opacity: 0;
      transition: opacity 180ms ease;
      will-change: filter, opacity, transform;
    }
    .state {
      position: absolute;
      inset: 0;
      display: grid;
      place-items: center;
      padding: 16px;
      text-align: center;
      color: #5b657a;
      font: 13px/1.5 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
      background: linear-gradient(180deg, rgba(255,255,255,.45), rgba(255,255,255,.2));
      backdrop-filter: blur(4px);
    }
    :host([loaded]) .state,
    :host([error]) .state {
      opacity: 0;
      pointer-events: none;
    }
    :host([loaded]) img {
      opacity: 1;
    }
  `;

  const DEFAULTS = {
    mode: 'auto',
    blur: '0',
    radius: '14px',
    fit: 'cover',
    height: '260px',
    width: '100%',
  };

  class RandomBackgroundWidget extends HTMLElement {
    static observedAttributes = ['src', 'mode', 'blur', 'radius', 'fit', 'height', 'width'];

    constructor() {
      super();
      this.attachShadow({ mode: 'open' });
      this._manifest = null;
      this._requestSeq = 0;
      this._boundRefresh = this.refresh.bind(this);
    }

    connectedCallback() {
      this.render();
      this.refresh();
      window.addEventListener('resize', this._boundRefresh, { passive: true });
    }

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

    attributeChangedCallback() {
      if (this.isConnected) {
        this.render();
        this.refresh();
      }
    }

    get baseUrl() {
      return (this.getAttribute('src') || DEFAULT_BASE_URL).replace(/\/+$/, '');
    }

    get mode() {
      return (this.getAttribute('mode') || DEFAULTS.mode).toLowerCase();
    }

    get blur() {
      const raw = Number.parseFloat(this.getAttribute('blur') || DEFAULTS.blur);
      return Number.isFinite(raw) && raw > 0 ? raw : 0;
    }

    get radius() {
      return this.getAttribute('radius') || DEFAULTS.radius;
    }

    get fit() {
      return this.getAttribute('fit') || DEFAULTS.fit;
    }

    get height() {
      return this.getAttribute('height') || DEFAULTS.height;
    }

    get width() {
      return this.getAttribute('width') || DEFAULTS.width;
    }

    render() {
      if (!this.shadowRoot) return;
      this.style.setProperty('--rbw-width', this.width);
      this.style.setProperty('--rbw-height', this.height);
      this.style.setProperty('--rbw-radius', this.radius);
      this.style.setProperty('--rbw-fit', this.fit);
      this.style.setProperty('--rbw-blur', `${this.blur}px`);

      this.shadowRoot.innerHTML = `
        <style>${STYLE}</style>
        <div class="frame">
          <img part="image" alt="random background">
          <div class="state">加载中</div>
        </div>
      `;
    }

    async refresh() {
      const seq = ++this._requestSeq;
      const img = this.shadowRoot.querySelector('img');
      const state = this.shadowRoot.querySelector('.state');

      try {
        if (!this._manifest) {
          this._manifest = await this.fetchManifest();
        }
        if (seq !== this._requestSeq) return;

        const variant = this.resolveVariant();
        const data = this._manifest?.variants?.[variant] || {};
        const folder = data.folder || (variant === 'mobile' ? 'mobile-image' : 'desketop-image');
        const images = Array.isArray(data.images) ? data.images.filter((item) => typeof item === 'string') : [];

        if (!images.length) {
          throw new Error(`no images in ${folder}`);
        }

        const filename = images[Math.floor(Math.random() * images.length)];
        img.src = `${this.baseUrl}/${folder}/${filename}`;
        img.alt = `random background ${variant}`;
        this.setAttribute('loaded', '');
        this.removeAttribute('error');
        state.textContent = '';
      } catch (error) {
        this.removeAttribute('loaded');
        this.setAttribute('error', '');
        state.textContent = error instanceof Error ? error.message : 'load failed';
      }
    }

    resolveVariant() {
      if (this.mode === 'mobile' || this.mode === 'desktop') return this.mode;

      const orientation = window.matchMedia('(orientation: portrait)').matches ? 'portrait' : 'landscape';
      const device = this.detectDevice();

      if (orientation === 'portrait') return 'mobile';
      if (orientation === 'landscape') return 'desktop';
      return device;
    }

    detectDevice() {
      if (navigator.userAgentData && typeof navigator.userAgentData.mobile === 'boolean') {
        return navigator.userAgentData.mobile ? 'mobile' : 'desktop';
      }
      return /Mobi|Android|iPhone|iPad|iPod/i.test(navigator.userAgent) ? 'mobile' : 'desktop';
    }

    async fetchManifest() {
      const url = new URL('manifest.json', `${this.baseUrl}/`);
      const response = await fetch(url.toString(), { mode: 'cors', cache: 'no-store' });
      if (!response.ok) {
        throw new Error(`manifest ${response.status}`);
      }
      return await response.json();
    }
  }

  if (!customElements.get('random-background-widget')) {
    customElements.define('random-background-widget', RandomBackgroundWidget);
  }

  window.RandomBackgroundWidget = RandomBackgroundWidget;
})();
