// Pagination -- page controls over a known total.
//
//   <Pagination page={2} pageSize={10} total={137} variant="numbered" />
//
// The component owns no data. It reports the requested page through its
// change output and lets the caller fetch or slice.
//
// NOTE: the style block uses /* */ comments only -- // is not a CSS comment
// and silently swallows the rule that follows it.
component Pagination {
  outputs {
    change(payload: { page: number; pageSize: number })
    previous(payload: { page: number })
    next(payload: { page: number })
  }

  props {
    color: string = "primary"
    size: string = "default"
    page: number = 1
    pageSize: number = 10
    total: number = 0
    variant: string = "compact"
    siblingCount: number = 1
    showSummary: boolean = true
    label: string = "Pagination"
    previousLabel: string = "Previous"
    nextLabel: string = "Next"
    class: string = ""
  }

  functions {
    shared function lastPage() {
      var size = Number(pageSize) > 0 ? Number(pageSize) : 10
      var count = Number(total) > 0 ? Number(total) : 0
      return Math.max(1, Math.ceil(count / size))
    }

    // Out-of-range values arrive routinely: page travels as an HTML attribute
    // and callers compute it from data that may have shrunk underneath them.
    shared function currentPage() {
      var value = Number(page)
      if (!value || value < 1) {
        return 1
      }
      return Math.min(value, lastPage())
    }

    shared function firstShown() {
      if (Number(total) < 1) {
        return 0
      }
      return (currentPage() - 1) * (Number(pageSize) || 10) + 1
    }

    shared function lastShown() {
      return Math.min(currentPage() * (Number(pageSize) || 10), Number(total) || 0)
    }

    shared function pageNumbers() {
      var last = lastPage()
      var current = currentPage()
      var siblings = Math.max(0, Number(siblingCount) || 0)
      var start = Math.max(1, current - siblings)
      var end = Math.min(last, current + siblings)
      var pages = []
      if (start > 1) {
        pages.push({ value: 1, label: "1", gap: false })
        if (start > 2) {
          pages.push({ value: 0, label: "...", gap: true })
        }
      }
      for (var index = start; index <= end; index += 1) {
        pages.push({ value: index, label: String(index), gap: false })
      }
      if (end < last) {
        if (end < last - 1) {
          pages.push({ value: 0, label: "...", gap: true })
        }
        pages.push({ value: last, label: String(last), gap: false })
      }
      return pages
    }

    client function goToPage(target) {
      var next = Math.min(Math.max(1, Number(target) || 1), lastPage())
      output.change({ page: next, pageSize: Number(pageSize) || 10 })
    }

    client function goPrevious() {
      var target = Math.max(1, currentPage() - 1)
      output.previous({ page: target })
      output.change({ page: target, pageSize: Number(pageSize) || 10 })
    }

    client function goNext() {
      var target = Math.min(lastPage(), currentPage() + 1)
      output.next({ page: target })
      output.change({ page: target, pageSize: Number(pageSize) || 10 })
    }
  }

  view {
    <nav
      {...attrs}
      data-ui-component="Pagination"
      class='wrn-pagination {class}'
      data-variant='{variant}'
      data-color='{color}'
      data-size='{size}'
      role="navigation"
      aria-label='{label}'
    >
      <p class="wrn-pagination__summary" data-show="showSummary">
        {firstShown()} to {lastShown()} of {total}
      </p>

      <div class="wrn-pagination__controls">
        <button
          type="button"
          class="wrn-pagination__step"
          aria-label='{previousLabel}'
          @click='goPrevious()'
        >
          <span class="wrn-pagination__step-icon" aria-hidden="true">&#8249;</span>
          <span class="wrn-pagination__step-label">{previousLabel}</span>
        </button>

        <ol class="wrn-pagination__pages" data-show="variant === 'numbered'">
          {#each pageNumbers() as entry}
            <li class="wrn-pagination__slot">
              <span class="wrn-pagination__gap" data-show="entry.gap">{entry.label}</span>
              <button
                type="button"
                class="wrn-pagination__page"
                data-show="!entry.gap"
                data-active='{entry.value === currentPage()}'
                aria-current='{entry.value === currentPage() ? "page" : "false"}'
                @click='goToPage(entry.value)'
              >
                {entry.label}
              </button>
            </li>
          {/each}
        </ol>

        <p class="wrn-pagination__compact" data-show="variant !== 'numbered'">
          {currentPage()} / {lastPage()}
        </p>

        <button
          type="button"
          class="wrn-pagination__step"
          aria-label='{nextLabel}'
          @click='goNext()'
        >
          <span class="wrn-pagination__step-label">{nextLabel}</span>
          <span class="wrn-pagination__step-icon" aria-hidden="true">&#8250;</span>
        </button>
      </div>

      <slot />
    </nav>
  }

  style {
    .wrn-pagination {
      --pagination-accent: var(--wrn-color-primary);
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      justify-content: space-between;
      gap: 0.75rem;
      max-width: 100%;
    }

    .wrn-pagination[data-color="secondary"] {
      --pagination-accent: var(--wrn-color-secondary);
    }

    .wrn-pagination[data-color="success"] {
      --pagination-accent: var(--wrn-color-success);
    }

    .wrn-pagination[data-color="danger"] {
      --pagination-accent: var(--wrn-color-danger);
    }

    .wrn-pagination[data-color="info"] {
      --pagination-accent: var(--wrn-color-info);
    }

    .wrn-pagination[data-size="sm"] {
      font-size: 0.82rem;
    }

    .wrn-pagination[data-size="lg"] {
      font-size: 1rem;
    }

    .wrn-pagination__summary {
      margin: 0;
      color: var(--wrn-color-text-muted);
      font-size: 0.82rem;
    }

    .wrn-pagination__controls {
      display: flex;
      align-items: center;
      gap: 0.35rem;
      flex-wrap: wrap;
    }

    .wrn-pagination__pages {
      display: flex;
      align-items: center;
      gap: 0.25rem;
      margin: 0;
      padding: 0;
      list-style: none;
    }

    .wrn-pagination__slot {
      display: inline-flex;
    }

    .wrn-pagination__page,
    .wrn-pagination__step {
      appearance: none;
      display: inline-flex;
      align-items: center;
      gap: 0.35rem;
      min-width: 2.25rem;
      justify-content: center;
      padding: 0.4rem 0.6rem;
      border: 1px solid var(--wrn-color-border);
      border-radius: var(--wrn-radius-sm);
      background: var(--wrn-color-surface);
      color: var(--wrn-color-text);
      font: inherit;
      font-size: 0.85rem;
      cursor: pointer;
    }

    .wrn-pagination__page:hover,
    .wrn-pagination__step:hover {
      background: var(--wrn-color-surface-soft);
    }

    .wrn-pagination__page:focus-visible,
    .wrn-pagination__step:focus-visible {
      outline: 2px solid var(--pagination-accent);
      outline-offset: 2px;
    }

    .wrn-pagination__page[data-active="true"] {
      border-color: var(--pagination-accent);
      background: var(--pagination-accent);
      color: var(--wrn-color-primary-contrast);
      font-weight: 700;
    }

    .wrn-pagination__gap {
      padding: 0 0.35rem;
      color: var(--wrn-color-text-muted);
    }

    .wrn-pagination__compact {
      margin: 0;
      padding: 0 0.5rem;
      color: var(--wrn-color-text-muted);
      font-size: 0.85rem;
    }

    /* Below the small breakpoint the word labels crowd the arrows out. */
    @media (max-width: 639px) {
      .wrn-pagination {
        justify-content: center;
      }

      .wrn-pagination__step-label {
        display: none;
      }

      .wrn-pagination__summary {
        width: 100%;
        text-align: center;
      }
    }
  }
}
