/**
 * Copyright Aquera Inc 2025
 *
 * This source code is licensed under the BSD-3-Clause license found in the
 * LICENSE file in the root directory of this source tree.
 */

import { LitElement, html, CSSResultArray, TemplateResult } from 'lit';
import { customElement, property, query, state } from 'lit/decorators.js';
import { styles } from './nile-pagination.css';
import NileElement from '../internal/nile-element';
import {
  calculateTotalPages,
  getPaginationItems,
  getHiddenPages,
  getRangeText,
} from './nile-pagination-utils';

@customElement('nile-pagination')
export class NilePagination extends NileElement {
  public static get styles(): CSSResultArray {
    return [styles];
  }

  @property({attribute: 'totalitems',reflect: true,converter: {
      fromAttribute: (v: string) => {
        const n = Number(v);
        return Number.isFinite(n) && n >= 0 ? Math.floor(n) : 0;
      },
    },
  })totalItems: number = 0;

  @property({attribute: 'currentpage', reflect: true, converter: {
      fromAttribute: (v: string) => {
        const n = Number(v);
        return Number.isFinite(n) && n >= 1 ? Math.floor(n) : 1;
      },
    },
  })currentPage: number = 1;

  @property({attribute: 'pagesize',reflect: true,converter: {
      fromAttribute: (v: string) => {
        const n = Number(v);
        return Number.isFinite(n) && n >= 1 ? Math.floor(n) : 50;
      },
    },
  })pageSize: number = 50;

  @property({ attribute: 'pagesizeoptions', reflect: false, converter: { fromAttribute: (v: string) => {
        try {
          const arr = JSON.parse(v);
          if (Array.isArray(arr) && arr.every(x => typeof x === 'number')) {
            return arr as number[];
          }
        } catch {}
        return [10, 25, 50, 100];
  }}})
 pageSizeOptions: number[] = [10, 25, 50, 100];

  @property({ type: String })variant: 'fluid' | 'compact' | 'mini' = 'fluid';
  @property({ type: Boolean, reflect: true }) disabled = false;
  @property({ type: Boolean }) showTitle = true;

  @state() private _pageSizeOpen = false;
  @state() private _pageOpen = false;
  @state() private _miniPageOpen = false;
  @query('.page-size-dropdown') private _pageSizeDropdown!: HTMLElement;

  firstUpdated() {
    if (this._pageSizeDropdown) { 
    this._pageSizeDropdown.addEventListener('nile-show', () => {
      this._pageSizeOpen = true;
    });
    this._pageSizeDropdown.addEventListener('nile-after-hide', () => {
      this._pageSizeOpen = false;
    });
  }
  }

  private get totalPages(): number {
    return Math.max(1, calculateTotalPages(this.totalItems, this.pageSize));
  }

  private goToPage(newPage: number) {
    
    if (this.disabled) return;
    const previousPage = this.currentPage;
    this.currentPage = newPage;
    this.emit('nile-change', { page: newPage, previousPage, pageSize: this.pageSize });
  }

 private onPageSizeSelect(newSize: number) {
  if (this.disabled || this.pageSize === newSize) return;

  const previousPage = this.currentPage;
  this.pageSize = newSize;
  this.currentPage = 1;
  this.emit('nile-change', {
    page: 1,
    previousPage,
    pageSize: newSize
  });
}

private renderCompactRangeText(): TemplateResult {
  const full = getRangeText(this.totalItems, this.pageSize, this.currentPage);
  const trimmed = full.replace(/^Showing\s*/, ''); 
  return html`<div class="range-text">${trimmed}</div>`;
}


  private renderRangeText(): TemplateResult {
    if (this.totalItems === 0) {
      return html`<div class="range-text">Showing 0 of 0</div>`;
    }
    return html`
      <div part="range-text" class="range-text">
        ${getRangeText(this.totalItems, this.pageSize, this.currentPage)}
      </div>
    `;
  }

  private renderPageSizeSelect(): TemplateResult | null {
    if (this.variant !== 'fluid') return null;
    return html`
      <div class="page-size-select">
        <nile-dropdown class="page-size-dropdown" ?disabled=${this.disabled}>
          <nile-button
            slot="trigger"
            variant="tertiary"
            class="down ${this._pageSizeOpen ? 'open' : ''}"
            ?disabled=${this.disabled}
          >
            ${this.pageSize}
            <nile-icon
                 name="var(--nile-icon-chevron-down, var(--ng-icon-chevron-down))"
              size="14"
              method="var(--nile-svg-method-fill, var(--ng-svg-method-stroke))"
              class="chevron"
            ></nile-icon>
          </nile-button>
          <nile-menu>
            <div class="down-scroll-wrapper">
              ${this.pageSizeOptions.map(
                size => html`
                  <nile-menu-item
                    ?disabled=${this.disabled}
                    @click=${() => this.onPageSizeSelect(size)}
                  >
                    ${size}
                  </nile-menu-item>
                `
              )}
            </div>
          </nile-menu>
        </nile-dropdown>
        <span part="pagesize-label" class="page-size-label">Items per page</span>
      </div>
    `;
  }


  private renderCompactPageSize(): TemplateResult {
    return html`
      <nile-dropdown
        class="compact-dropdown"
        ?disabled=${this.disabled}
        @nile-show=${() => (this._pageSizeOpen = true)}
        @nile-after-hide=${() => (this._pageSizeOpen = false)}
      >
        <nile-button
          slot="trigger"
          variant="tertiary"
          class="down ${this._pageSizeOpen ? 'open' : ''}"
          ?disabled=${this.disabled}
        >
          ${this.pageSize}
          <nile-icon
               name="var(--nile-icon-chevron-down, var(--ng-icon-chevron-down))"
            size="14"
            method="var(--nile-svg-method-fill, var(--ng-svg-method-stroke))"
            class="chevron"
          ></nile-icon>
        </nile-button>
        <nile-menu>
          <div class="compact-scroll-wrapper">
            ${this.pageSizeOptions.map(
              size => html`
                <nile-menu-item
                  ?disabled=${this.disabled}
                  @click=${() => this.onPageSizeSelect(size)}
                >
                  ${size}
                </nile-menu-item>
              `
            )}
          </div>
        </nile-menu>
      </nile-dropdown>
    `;
  }
  

  private renderPrevButton(): TemplateResult {
    return html`
      <li>
        <nile-button
          variant="tertiary"
          ?disabled=${this.currentPage === 1 || this.disabled}
          @click=${() => this.goToPage(this.currentPage - 1)}
          class="prev-button"
        >
          <nile-icon name="var(--nile-icon-arrow-left, var(--ng-icon-chevron-left))" method="var(--nile-svg-method-fill, var(--ng-svg-method-stroke))" size="14"></nile-icon>
        </nile-button>
      </li>
    `;
  }

  private renderNextButton(): TemplateResult {
    return html`
      <li>
        <nile-button
          variant="tertiary"
          ?disabled=${this.currentPage === this.totalPages || this.disabled}
          @click=${() => this.goToPage(this.currentPage + 1)}
          class="next-button"
        >
          <nile-icon name="var(--nile-icon-arrow-right, var(--ng-icon-chevron-right))" method="var(--nile-svg-method-fill, var(--ng-svg-method-stroke))" size="14"></nile-icon>
        </nile-button>
      </li>
    `;
  }

  private renderPageItem(
    item: number | string,
    idx: number,
    items: (number | string)[]
  ): TemplateResult {
    if (item === '…') {
      return html`
        <li>
          <nile-dropdown class="ellipsis-dropdown" ?disabled=${this.disabled}>
            <nile-button slot="trigger" variant="ghost" ?disabled=${this.disabled}>
              …
            </nile-button>
            <nile-menu>
              <div class="ellipsis-scroll-wrapper">
                ${getHiddenPages(
                  this.totalPages,
                  items,
                  this.currentPage,
                  idx < items.indexOf(this.currentPage) ? 'left' : 'right'
                ).map(
                  page => html`
                    <nile-menu-item
                      ?disabled=${this.disabled}
                      @click=${() => this.goToPage(page)}
                    >
                      ${page}
                    </nile-menu-item>
                  `
                )}
              </div>
            </nile-menu>
          </nile-dropdown>
        </li>
      `;
    }
    return html`
      <li>
        <nile-button
          variant=${item === this.currentPage ? 'primary' : 'ghost'}
          ?disabled=${this.disabled}
          @click=${() => this.goToPage(item as number)}
        >
          ${item}
        </nile-button>
      </li>
    `;
  }

  private renderMiniPrevButton(): TemplateResult {
    return html`
      <li>
        <nile-button
          variant="tertiary"
          ?disabled=${this.currentPage === 1 || this.disabled}
          @click=${() => this.goToPage(this.currentPage - 1)}
          class="mini-prev-button"
        >
          <nile-icon name="var(--nile-icon-arrow-left, var(--ng-icon-chevron-left))" method="var(--nile-svg-method-fill, var(--ng-svg-method-stroke))" size="12"></nile-icon>
        </nile-button>
      </li>
    `;
  }

  private renderMiniNextButton(): TemplateResult {
    return html`
      <li>
        <nile-button
          variant="tertiary"
          ?disabled=${this.currentPage === this.totalPages || this.disabled}
          @click=${() => this.goToPage(this.currentPage + 1)}
          class="mini-next-button"
        >
          <nile-icon name="var(--nile-icon-arrow-right, var(--ng-icon-chevron-right))" method="var(--nile-svg-method-fill, var(--ng-svg-method-stroke))" size="12"></nile-icon>
        </nile-button>
      </li>
    `;
  }

  private renderMini(): TemplateResult {
    return html`
      <div part="wrapper" class="pagination-wrapper mini">
        <span part="mini-showing-label" class="mini-showing-label">Showing</span>
        <nile-dropdown
          part="mini-page-dropdown"
          class="mini-page-dropdown"
          ?disabled=${this.disabled}
          @nile-show=${() => (this._miniPageOpen = true)}
          @nile-after-hide=${() => (this._miniPageOpen = false)}
        >
          <nile-button
            slot="trigger"
            variant="tertiary"
            class="mini-page-btn ${this._miniPageOpen ? 'open' : ''}"
            ?disabled=${this.disabled}
          >
            ${this.currentPage}
            <nile-icon
              name="var(--nile-icon-chevron-down, var(--ng-icon-chevron-down))"
              size="12"
              method="var(--nile-svg-method-fill, var(--ng-svg-method-stroke))"
              class="chevron"
            ></nile-icon>
          </nile-button>
          <nile-menu>
            <div class="mini-scroll-wrapper">
              ${Array.from({ length: this.totalPages }, (_, i) => i + 1).map(
                p => html`
                  <nile-menu-item
                    ?disabled=${this.disabled}
                    @click=${() => this.goToPage(p)}
                  >
                    ${p}
                  </nile-menu-item>
                `
              )}
            </div>
          </nile-menu>
        </nile-dropdown>
        <span part="mini-of-label" class="mini-of-label">of ${this.totalPages}</span>
        <nav aria-label="Pagination" part="mini-nav" class="mini-nav">
          <ul part="mini-page-list" class="pagination mini-pagination">
            ${this.renderMiniPrevButton()}
            ${this.renderMiniNextButton()}
          </ul>
        </nav>
      </div>
    `;
  }

  private renderPageList(): TemplateResult {
    if (this.variant === 'compact') {
      return html`
        <nav aria-label="Pagination">
          <ul class="pagination compact-pagination">
            ${this.renderPrevButton()}
            <li>
              <nile-dropdown
                class="compact-dropdown1"
                ?disabled=${this.disabled}
                @nile-show=${() => (this._pageOpen = true)}
                @nile-after-hide=${() => (this._pageOpen = false)}
              >
                <nile-button
                  slot="trigger"
                  variant="tertiary"
                  class="current-page-btn ${this._pageOpen ? 'open' : ''}"
                  ?disabled=${this.disabled}
                >
                  ${this.currentPage}
                  <nile-icon
                    name="var(--nile-icon-chevron-down, var(--ng-icon-chevron-down))"
                    size="14"
                    method="var(--nile-svg-method-fill, var(--ng-svg-method-stroke))"
                    class="chevron"
                  ></nile-icon>
                </nile-button>
                <nile-menu>
                  <div class="compact-scroll-wrapper1">
                    ${Array.from({ length: this.totalPages }, (_, i) => i + 1).map(
                      p => html`
                        <nile-menu-item
                          ?disabled=${this.disabled}
                          @click=${() => this.goToPage(p)}
                        >
                          ${p}
                        </nile-menu-item>
                      `
                    )}
                  </div>
                </nile-menu>
              </nile-dropdown>
            </li>
            ${this.renderNextButton()}
          </ul>
        </nav>
      `;
    }
    const items = getPaginationItems(this.totalPages, this.currentPage);
    return html`
      <nav aria-label="Pagination">
        <ul part="page-list" class="pagination">
          ${this.renderPrevButton()}
          ${items.map((item, idx) => this.renderPageItem(item, idx, items))}
          ${this.renderNextButton()}
        </ul>
      </nav>
    `;
  }

 public render(): TemplateResult {
  if (this.variant === 'mini') {
    return this.renderMini();
  }
  return html`
    <div part="wrapper" class="pagination-wrapper ${this.variant}">
      <div part="pager-container" class="pager-container">
        ${this.variant === 'fluid' && this.showTitle
            ? this.renderRangeText()
          : this.variant === 'compact'
            ? this.renderCompactRangeText()
            : null}
        ${this.variant === 'fluid'
          ? this.renderPageSizeSelect()
          : this.renderCompactPageSize()}
      </div>
      ${this.renderPageList()}
    </div>
  `;
}
}

declare global {
  interface HTMLElementTagNameMap {
    'nile-pagination': NilePagination;
  }
}
