import { html, nothing } from 'lit'
import componentStyles from '../../styles/component.styles.js'
import TerraElement from '../../internal/terra-element.js'
import styles from './data-subsetter.styles.js'
import type { CSSResultGroup } from 'lit'
import { property, query, state } from 'lit/decorators.js'
import { DataSubsetterController } from './data-subsetter.controller.js'
import TerraAccordion from '../accordion/accordion.component.js'
import {
    Status,
    type BoundingBox,
    type CollectionWithAvailableServices,
    type Variable,
} from '../../data-services/types.js'
import TerraDatePicker from '../date-picker/date-picker.component.js'
import TerraIcon from '../icon/icon.component.js'
import TerraInput from '../input/input.component.js'
import TerraSpatialPicker from '../spatial-picker/spatial-picker.component.js'
import type { TerraMapChangeEvent } from '../../events/terra-map-change.js'
import { getBasePath } from '../../utilities/base-path.js'
import {
    defaultSubsetFileMimeType,
    getFriendlyNameForMimeType,
} from '../../utilities/mimetypes.js'
import { watch } from '../../internal/watch.js'
import { debounce } from '../../internal/debounce.js'
import type { CmrSearchResult } from '../../metadata-catalog/types.js'
import type { LatLng, LatLngBounds } from 'leaflet'
import { MapEventType } from '../map/type.js'
import { AuthController } from '../../auth/auth.controller.js'
import TerraLogin from '../login/login.component.js'
import TerraLoader from '../loader/loader.component.js'
import { sendDataToJupyterNotebook } from '../../lib/jupyter.js'
import { getNotebook } from './notebooks/subsetter-notebook.js'
import TerraDataAccess from '../data-access/data-access.component.js'
import type { TerraDateRangeChangeEvent } from '../../events/terra-date-range-change.js'
import TerraDialog from '../dialog/dialog.component.js'
import TerraDropdown from '../dropdown/dropdown.component.js'
import TerraMenu from '../menu/menu.component.js'
import TerraMenuItem from '../menu-item/menu-item.component.js'
import TerraButton from '../button/button.component.js'
import type { TerraSelectEvent } from '../../events/terra-select.js'
import { TaskStatus } from '@lit/task'
import { extractHarmonyError } from '../../utilities/harmony.js'
import TerraAlert from '../alert/alert.component.js'
import { convertVariableEntryIdToGiovanniFormat } from '../../utilities/giovanni.js'

/**
 * @summary Easily allow users to select, subset, and download NASA Earth science data collections with spatial, temporal, and variable filters.
 * @documentation https://terra-ui.netlify.app/components/data-subsetter
 * @status stable
 * @since 1.0
 *
 * @dependency terra-accordion
 * @dependency terra-date-picker
 * @dependency terra-icon
 * @dependency terra-spatial-picker
 *
 * @event terra-subset-job-complete - called when a subset job enters a final state (e.g. successful, failed, completed_with_errors)
 */
export default class TerraDataSubsetter extends TerraElement {
    static styles: CSSResultGroup = [componentStyles, styles]
    static dependencies: Record<string, typeof TerraElement> = {
        'terra-accordion': TerraAccordion,
        'terra-date-picker': TerraDatePicker,
        'terra-icon': TerraIcon,
        'terra-input': TerraInput,
        'terra-spatial-picker': TerraSpatialPicker,
        'terra-login': TerraLogin,
        'terra-loader': TerraLoader,
        'terra-data-access': TerraDataAccess,
        'terra-dialog': TerraDialog,
        'terra-dropdown': TerraDropdown,
        'terra-menu': TerraMenu,
        'terra-menu-item': TerraMenuItem,
        'terra-button': TerraButton,
        'terra-alert': TerraAlert,
    }

    @property({ reflect: true, attribute: 'collection-entry-id' })
    collectionEntryId?: string

    @property({ reflect: true, attribute: 'short-name' })
    shortName?: string

    @property({ reflect: true, attribute: 'version' })
    version?: string

    @property({ reflect: true, type: Boolean, attribute: 'show-collection-search' })
    showCollectionSearch?: boolean = true

    @property({ reflect: true, type: Boolean, attribute: 'show-history-panel' })
    showHistoryPanel?: boolean = true

    @property({ reflect: true, attribute: 'job-id' })
    jobId?: string

    @property({ attribute: 'bearer-token' })
    bearerToken?: string

    /**
     * Optional dialog ID. When set, the subsetter will render inside a dialog with this ID.
     */
    @property({ reflect: true }) dialog?: string

    @property({ reflect: true, type: Boolean, attribute: 'is-history-view' })
    isHistoryView: boolean = false

    @state()
    collectionWithServices?: CollectionWithAvailableServices

    @state()
    selectedVariables: Variable[] = []

    @state()
    expandedVariableGroups: Set<string> = new Set()

    @state()
    variableFilterText: string = ''

    @state()
    touchedFields: Set<string> = new Set()

    @state()
    spatialSelection: BoundingBox | LatLng | null = null

    @state()
    selectedDateRange: { startDate: string | null; endDate: string | null } = {
        startDate: null,
        endDate: null,
    }

    @state()
    selectedFormat: string = defaultSubsetFileMimeType

    @state()
    cancelingGetData: boolean = false

    @state()
    selectedTab: 'web-links' | 'selected-params' = 'web-links'

    @state()
    refineParameters: boolean = false

    @state()
    collectionSearchType: 'collection' | 'variable' | 'all' = 'all'

    @state()
    collectionSearchQuery?: string

    @state()
    collectionSearchLoading: boolean = false

    @state()
    collectionSearchResults?: Array<CmrSearchResult>

    @state()
    collectionLoading: boolean = false

    @state()
    collectionAccordionOpen: boolean = true

    @state()
    dataAccessMode: 'original' | 'subset' = 'original'

    @state()
    validationError?: string

    @state()
    granuleMinDate?: string

    @state()
    granuleMaxDate?: string

    @state()
    giovanniConfiguredVariables?: Set<string>

    @query('[part~="spatial-picker"]')
    spatialPicker: TerraSpatialPicker

    @query('terra-dialog')
    dialogElement?: TerraDialog

    controller = new DataSubsetterController(this)
    #authController = new AuthController(this)

    @watch(['jobId'], { waitUntilFirstUpdate: true })
    jobIdChanged() {
        if (this.jobId) {
            this.controller.fetchJobByID(this.jobId)
            this.dataAccessMode = 'subset'
        }
    }

    @watch(['shortName', 'version'])
    shortNameAndVersionChanged() {
        if (this.shortName && this.version) {
            this.collectionEntryId = `${this.shortName}_${this.version}`
        }
    }

    @watch('collectionEntryId', { waitUntilFirstUpdate: true })
    collectionEntryIdChanged() {
        if (this.collectionEntryId) {
            this.showCollectionSearch = false
        } else {
            this.showCollectionSearch = true
        }
    }

    firstUpdated() {
        if (this.collectionEntryId) {
            this.showCollectionSearch = false
        }

        if (this.jobId) {
            this.controller.fetchJobByID(this.jobId)
            this.dataAccessMode = 'subset'
        }

        this.renderHistoryPanel()
    }

    updated(changedProps: Map<string, unknown>) {
        super.updated(changedProps)

        const taskStatus = this.controller?.jobStatusTask?.status

        // Check if task has an error and handle it
        if (taskStatus === TaskStatus.ERROR) {
            const taskError = this.controller?.jobStatusTask?.error
            if (taskError) {
                // Extract error information using the utility
                const errorDetails = extractHarmonyError(taskError)

                // Don't show errors for user-initiated cancellations
                if (errorDetails.isCancellation) {
                    return
                }

                // Set the job to failed state with the error message
                if (this.controller.currentJob) {
                    this.controller.currentJob = {
                        ...this.controller.currentJob,
                        status: Status.FAILED,
                        message:
                            errorDetails.message || 'Failed to create subset job',
                    }
                }
            }
        }
    }

    @watch(['collectionWithServices'])
    collectionChanged() {
        const { startDate, endDate } = this.#getCollectionDateRange()
        this.selectedDateRange = { startDate, endDate }

        const formats = Array.from(
            new Set(this.collectionWithServices?.outputFormats || [])
        )

        // Consolidate NetCDF formats - if both exist, only keep netcdf4
        const hasNetcdf4 = formats.includes('application/x-netcdf4')
        const hasNetcdfClassic = formats.includes('application/netcdf')

        let displayFormats = formats
        if (hasNetcdf4 && hasNetcdfClassic) {
            displayFormats = formats.filter(f => f !== 'application/netcdf')
        }

        // auto-select default format
        if (displayFormats.length === 1) {
            this.selectedFormat = displayFormats[0] // only one option
        } else {
            // Prefer NetCDF if available, otherwise first option
            this.selectedFormat =
                displayFormats.find(f => f === 'application/x-netcdf4') ||
                displayFormats[0]
        }

        this.collectionLoading = false
        this.collectionAccordionOpen = false
    }

    @watch(['granuleMinDate', 'granuleMaxDate'])
    granuleDatesChanged() {
        const newRange = {
            ...(this.granuleMinDate && { startDate: this.granuleMinDate }),
            ...(this.granuleMaxDate && { endDate: this.granuleMaxDate }),
        }

        if (Object.keys(newRange).length > 0) {
            this.selectedDateRange = {
                ...this.selectedDateRange,
                ...newRange,
            }
        }
    }

    @watch('selectedFormat')
    selectedFormatChanged() {
        // When switching to Giovanni format, keep only the first selected variable
        if (this.#isGiovanniFormat() && this.selectedVariables.length > 1) {
            this.selectedVariables = [this.selectedVariables[0]]
        }
    }

    showDialog() {
        this.dialogElement?.show()
    }

    render() {
        const showJobStatus = this.controller.currentJob && !this.refineParameters
        const showMinimizeButton = showJobStatus && !!this.dialog
        const title =
            this.collectionWithServices?.collection?.EntryTitle ?? 'Download Data'

        if (!this.collectionWithServices) {
            if (this.controller.fetchCollectionTask.status === TaskStatus.PENDING) {
                return html`
                    <div class="loading-collection">
                        <terra-loader indeterminate variant="small"></terra-loader>
                        <span>Loading</span>
                    </div>
                `
            }

            if (this.controller.fetchCollectionTask.status === TaskStatus.ERROR) {
                return html`
                    <terra-alert open variant="danger" appearance="white">
                        Failed to find the requested collection.
                    </terra-alert>
                `
            }
        }

        const content = html`
            <div class="container">
                ${!this.dialog
                    ? html`
                          <div class="header">
                              <h1>
                                  <svg
                                      class="download-icon"
                                      viewBox="0 0 24 24"
                                      fill="currentColor"
                                  >
                                      <path
                                          d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"
                                      />
                                  </svg>
                                  ${title}
                              </h1>

                              ${showMinimizeButton
                                  ? html`<button
                                        class="minimize-btn"
                                        @click=${() => this.minimizeDialog()}
                                    >
                                        -
                                    </button>`
                                  : nothing}
                          </div>
                      `
                    : nothing}
                ${!this.isHistoryView && this.collectionWithServices?.services?.length
                    ? html`
                          <div class="section">
                              ${this.#renderDataAccessModeSelection()}
                          </div>
                      `
                    : nothing}
                ${this.dataAccessMode === 'original'
                    ? html`
                          <div class="section">
                              <terra-data-access
                                  short-name=${this.shortName ??
                                  this.collectionWithServices?.collection?.ShortName}
                                  version=${this.version ??
                                  this.collectionWithServices?.collection?.Version}
                                  ?footer-slot=${!!this.dialog}
                              >
                                  ${this.dialog
                                      ? html`
                                            <div
                                                slot="footer"
                                                style="margin-top: 15px;"
                                            >
                                                <slot
                                                    name="data-access-footer"
                                                ></slot>
                                            </div>
                                        `
                                      : nothing}
                              </terra-data-access>
                          </div>
                      `
                    : showJobStatus
                      ? this.#renderJobStatus()
                      : this.#renderSubsetOptions()}
            </div>
        `

        // If dialog is set, wrap content in dialog with slots for header/footer
        if (this.dialog) {
            return html`
                <terra-dialog id=${this.dialog} style="--title-font-size: 16px;">
                    <span
                        slot="label"
                        style="display: flex; align-items: center; gap: 8px; color: #0066cc; font-weight: 600;"
                    >
                        <svg
                            class="download-icon"
                            viewBox="0 0 24 24"
                            fill="currentColor"
                            style="width: 16px; height: 16px; display: inline-block; vertical-align: middle; flex-shrink: 0;"
                        >
                            <path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z" />
                        </svg>
                        ${title}
                    </span>
                    ${showMinimizeButton
                        ? html`
                              <button
                                  slot="header-actions"
                                  class="minimize-btn"
                                  @click=${() => this.dialogElement?.hide()}
                                  aria-label="Minimize"
                              >
                                  -
                              </button>
                          `
                        : nothing}
                    ${content} ${this.#renderFooterForDialog()}
                </terra-dialog>
            `
        }

        // Otherwise render normally with internal header
        return html`
            <div class="container">
                <div class="header">
                    <h1>
                        <svg
                            class="download-icon"
                            viewBox="0 0 24 24"
                            fill="currentColor"
                        >
                            <path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z" />
                        </svg>
                        ${title}
                    </h1>

                    ${showMinimizeButton
                        ? html`<button
                              class="minimize-btn"
                              @click=${() => this.minimizeDialog()}
                          >
                              -
                          </button>`
                        : nothing}
                </div>
                ${!this.isHistoryView && this.collectionWithServices?.services?.length
                    ? html`
                          <div class="section">
                              ${this.#renderDataAccessModeSelection()}
                          </div>
                      `
                    : nothing}
                ${this.dataAccessMode === 'original'
                    ? html`
                          <div class="section">
                              <terra-data-access
                                  short-name=${this.shortName ??
                                  this.collectionWithServices?.collection?.ShortName}
                                  version=${this.version ??
                                  this.collectionWithServices?.collection?.Version}
                                  ?footer-slot=${!!this.dialog}
                              >
                                  ${this.dialog
                                      ? html`
                                            <div
                                                slot="footer"
                                                style="margin-top: 15px;"
                                            >
                                                <slot
                                                    name="data-access-footer"
                                                ></slot>
                                            </div>
                                        `
                                      : nothing}
                              </terra-data-access>
                          </div>
                      `
                    : showJobStatus
                      ? this.#renderJobStatus()
                      : this.#renderSubsetOptions()}
            </div>
        `
    }

    #renderFooterForDialog() {
        const showJobStatus = this.controller.currentJob && !this.refineParameters

        if (showJobStatus && this.controller.currentJob) {
            // Job status footer - return the footer content with slot="footer"
            return html`
                <div slot="footer" class="footer">
                    ${this.controller.currentJob.status === Status.SUCCESSFUL ||
                    this.controller.currentJob.status === Status.COMPLETE_WITH_ERRORS
                        ? html`
                              <div
                                  style="display: flex; align-items: center; gap: 8px;"
                              >
                                  <terra-dropdown
                                      @terra-select=${this.#handleDownloadSelect}
                                  >
                                      <terra-button slot="trigger" caret>
                                          Download Options
                                      </terra-button>
                                      <terra-menu>
                                          <terra-menu-item value="file-list">
                                              <svg
                                                  slot="prefix"
                                                  viewBox="0 0 24 24"
                                                  width="16"
                                                  height="16"
                                                  style="width: 16px; height: 16px;"
                                              >
                                                  <path
                                                      fill="currentColor"
                                                      d="M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm2 16H8v-2h8v2zm0-4H8v-2h8v2zm-3-5V3.5L18.5 9H13z"
                                                  />
                                              </svg>
                                              File List
                                          </terra-menu-item>
                                          <terra-menu-item value="python-script">
                                              <svg
                                                  slot="prefix"
                                                  viewBox="0 0 128 128"
                                                  width="16"
                                                  height="16"
                                                  style="width: 16px; height: 16px;"
                                              >
                                                  <path
                                                      fill="currentColor"
                                                      d="M49.33 62h29.159C86.606 62 93 55.132 93 46.981V19.183c0-7.912-6.632-13.856-14.555-15.176-5.014-.835-10.195-1.215-15.187-1.191-4.99.023-9.612.448-13.805 1.191C37.098 6.188 35 10.758 35 19.183V30h29v4H23.776c-8.484 0-15.914 5.108-18.237 14.811-2.681 11.12-2.8 17.919 0 29.53C7.614 86.983 12.569 93 21.054 93H31V79.952C31 70.315 39.428 62 49.33 62zm-1.838-39.11c-3.026 0-5.478-2.479-5.478-5.545 0-3.079 2.451-5.581 5.478-5.581 3.015 0 5.479 2.502 5.479 5.581-.001 3.066-2.465 5.545-5.479 5.545zm74.789 25.921C120.183 40.363 116.178 34 107.682 34H97v12.981C97 57.031 88.206 65 78.489 65H49.33C41.342 65 35 72.326 35 80.326v27.8c0 7.91 6.745 12.564 14.462 14.834 9.242 2.717 17.994 3.208 29.051 0C85.862 120.831 93 116.549 93 108.126V97H64v-4h43.682c8.484 0 11.647-5.776 14.599-14.66 3.047-9.145 2.916-17.799 0-29.529zm-41.955 55.606c3.027 0 5.479 2.479 5.479 5.547 0 3.076-2.451 5.579-5.479 5.579-3.015 0-5.478-2.502-5.478-5.579 0-3.068 2.463-5.547 5.478-5.547z"
                                                  ></path>
                                              </svg>
                                              Python Script
                                          </terra-menu-item>
                                          <terra-menu-item value="earthdata-download">
                                              <svg
                                                  slot="prefix"
                                                  viewBox="0 0 64 64"
                                                  fill="none"
                                                  width="16"
                                                  height="16"
                                                  style="width: 16px; height: 16px;"
                                              >
                                                  <circle
                                                      cx="32"
                                                      cy="32"
                                                      r="28"
                                                      fill="currentColor"
                                                  />
                                                  <path
                                                      d="M32 14v26M32 40l-9-9M32 40l9-9"
                                                      stroke="#fff"
                                                      stroke-width="4"
                                                      stroke-linecap="round"
                                                      stroke-linejoin="round"
                                                      fill="none"
                                                  />
                                              </svg>
                                              Earthdata Download
                                          </terra-menu-item>
                                      </terra-menu>
                                  </terra-dropdown>

                                  <terra-button
                                      outline
                                      @click=${() =>
                                          this.#handleJupyterNotebookClick()}
                                  >
                                      <terra-icon
                                          name="outline-code-bracket"
                                          library="heroicons"
                                          font-size="1.5em"
                                          style="margin-right: 5px;"
                                      ></terra-icon>
                                      Open in Jupyter Notebook
                                  </terra-button>
                              </div>
                          `
                        : nothing}
                    ${this.controller.currentJob.status === 'running'
                        ? html`<button
                              class="btn btn-success"
                              @click=${this.#cancelJob}
                              ?disabled=${this.cancelingGetData}
                          >
                              ${this.cancelingGetData
                                  ? 'Canceling...'
                                  : 'Cancel request'}
                          </button>`
                        : nothing}

                    <div class="job-info">
                        Job ID:
                        <span class="job-id">
                            ${this.bearerToken
                                ? html`<a
                                      href="https://harmony.earthdata.nasa.gov/jobs/${this
                                          .controller.currentJob.jobID}"
                                      target="_blank"
                                      >${this.controller.currentJob.jobID}</a
                                  >`
                                : this.controller.currentJob.jobID}
                        </span>
                        <span class="info-icon">?</span>
                    </div>
                </div>
            `
        } else if (this.dataAccessMode === 'subset') {
            // Get Data footer
            return html`
                <div slot="footer" class="footer">
                    <button class="btn btn-secondary" @click=${this.#resetAllParameters}>Reset All</button>
                    <div>
                        <button class="btn btn-primary" @click=${this.#getData}>
                            Get Data
                        </button>
                            ${
                                this.jobId
                                    ? html`
                                          <terra-button
                                              variant="default"
                                              @click=${this.#viewRunningJob}
                                          >
                                              View Running Job
                                          </terra-button>
                                      `
                                    : nothing
                            }
                            </div>
                        </div>
                    </div>
                </div>
            `
        }

        return nothing
    }

    minimizeDialog() {
        this.closest('terra-dialog')?.hide()
    }

    #renderSizeInfo(estimates: { days: number; links: number }) {
        if (
            !this.#authController.state.isLoading &&
            !this.#authController.state.user
        ) {
            return html`
                <div class="size-info warning">
                    <terra-login>
                        <h2 slot="logged-out">Limited access as a guest.</h2>

                        <p slot="logged-out">
                            Your results will be capped at 10 links. Log in for full
                            access to all data.
                        </p>
                    </terra-login>
                </div>
            `
        }

        return html`<div
            class="size-info ${estimates.links >= 150 ? 'warning' : 'neutral'}"
        >
            <h2>Estimated size of results</h2>
            <div class="size-stats">
                ${estimates.days.toLocaleString()} days,
                ${estimates.links.toLocaleString()} links
            </div>
            ${estimates.links >= 150
                ? html`<div class="size-warning">
                      You are about to retrieve ${estimates.links.toLocaleString()}
                      file links from the archive. You may
                      <strong>speed up the request</strong> by limiting the scope of
                      your search.
                  </div>`
                : nothing}
        </div>`
    }

    #renderSubsetOptions() {
        const estimates = this.#estimateJobSize()
        const hasSubsetOption = this.#hasAtLeastOneSubsetOption()
        const collection = this.collectionWithServices?.collection
        const temporalExtents = collection?.TemporalExtents
        const spatialExtent = collection?.SpatialExtent

        const showTemporalSection = temporalExtents && temporalExtents.length
        const showSpatialSection =
            spatialExtent &&
            spatialExtent.HorizontalSpatialDomain?.Geometry?.BoundingRectangles

        return html`
            ${this.dataAccessMode === 'original'
                ? nothing
                : hasSubsetOption
                  ? html`
                        ${hasSubsetOption && estimates
                            ? this.#renderSizeInfo(estimates)
                            : nothing}
                        ${this.showCollectionSearch
                            ? html`
                                  <div class="section">
                                      <h2 class="section-title">
                                          Select Data Collection
                                      </h2>

                                      ${this.#renderSearchForCollection()}
                                  </div>
                              `
                            : nothing}
                        ${this.collectionWithServices?.outputFormats?.length &&
                        hasSubsetOption
                            ? html`
                                  <div class="section">
                                      <h2 class="section-title">Output Format</h2>

                                      ${this.#renderOutputFormatSelection()}
                                  </div>
                              `
                            : nothing}
                        <div class="section">
                            <h2 class="section-title">Subset Options</h2>
                            <p style="color: #666; margin-bottom: 16px;">
                                Generate file links that support spatial subsetting,
                                date/time range selection, and variable selection.
                            </p>

                            ${this.collectionWithServices?.temporalSubset
                                ? this.#renderDateRangeSelection()
                                : nothing}
                            ${this.#hasSpatialSubset()
                                ? this.#renderSpatialSelection()
                                : nothing}
                            ${this.collectionWithServices?.variableSubset
                                ? this.#renderVariableSelection()
                                : nothing}
                        </div>
                    `
                  : html`
                        ${showTemporalSection &&
                        !this.collectionWithServices?.temporalSubset
                            ? this.#renderAvailableTemporalRangeSection()
                            : nothing}
                        ${showSpatialSection && !this.#hasSpatialSubset()
                            ? this.#renderAvailableSpatialRangeSection()
                            : nothing}
                    `}
            ${!hasSubsetOption && estimates
                ? html`
                      <div
                          class="neutral-info"
                          style="margin-top: 24px; padding: 16px 20px; border-radius: 6px; background: #f8f9fa; color: #555; border: 1px solid #ccc;"
                      >
                          <strong>Estimated result size:</strong><br />
                          Your request will return approximately
                          <b>${estimates.links.toLocaleString()}</b> files covering
                          <b>${estimates.days.toLocaleString()}</b> days.
                      </div>
                  `
                : nothing}
            ${this.dataAccessMode === 'subset' && !this.dialog
                ? html`
                      <div class="footer">
                          <button class="btn btn-secondary" @click=${this.#resetAllParameters}>Reset All</button>
                          <div>
                          <button
                              class="btn btn-primary"
                              @click=${this.#getData}
                          >
                              Get Data
                          </button>
                                  ${
                                      this.jobId
                                          ? html`
                                                <terra-button
                                                    variant="default"
                                                    @click=${this.#viewRunningJob}
                                                >
                                                    View Running Job
                                                </terra-button>
                                            `
                                          : nothing
                                  }
                              </div>
                                </div>
                          </div>
                      </div>
                  `
                : nothing}
        `
    }

    #resetAllParameters = () => {
        // Reset variables
        this.selectedVariables = []

        // Reset spatial to collection bounds (not null)
        if (this.#hasSpatialSubset()) {
            this.#resetSpatialSelection()
        }

        // Reset date range
        this.selectedDateRange = {
            startDate: null,
            endDate: null,
        }

        // Clear validation state
        this.touchedFields = new Set()
        this.validationError = undefined

        // Collapse variable tree
        this.expandedVariableGroups = new Set()

        this.requestUpdate()
    }

    #renderSearchForCollection() {
        let placeholder =
            'Search all types of resources (e.g. rainfall, GPM, hurricanes, etc.)'

        if (this.collectionSearchType === 'collection') {
            placeholder = 'Search collections (e.g. AQUA, GPM_3IMERGH, etc.)'
        }

        if (this.collectionSearchType === 'variable') {
            placeholder = 'Search variables (e.g. rainfall, hurricanes, etc.)'
        }

        return html`
            <terra-accordion .open=${this.collectionAccordionOpen}>
                <div slot="summary">
                    <span class="accordion-title">Collection:</span>
                </div>

                <div
                    slot="summary-right"
                    style="display: flex; align-items: center; gap: 10px"
                >
                    ${this.collectionEntryId
                        ? html` <span
                                  class="accordion-value"
                                  id="selected-collection-display"
                                  >${this.collectionEntryId}</span
                              >

                              <button
                                  class="reset-btn"
                                  @click=${() => (this.collectionEntryId = undefined)}
                              >
                                  Reset
                              </button>`
                        : nothing}
                </div>

                <div class="search-tabs-mini">
                    <button
                        class="search-tab-mini ${this.collectionSearchType === 'all'
                            ? 'active'
                            : ''}"
                        @click=${() => (this.collectionSearchType = 'all')}
                    >
                        All
                    </button>
                    <button
                        class="search-tab-mini ${this.collectionSearchType ===
                        'collection'
                            ? 'active'
                            : ''}"
                        @click=${() => (this.collectionSearchType = 'collection')}
                    >
                        Collections
                    </button>
                    <button
                        class="search-tab-mini ${this.collectionSearchType ===
                        'variable'
                            ? 'active'
                            : ''}"
                        @click=${() => (this.collectionSearchType = 'variable')}
                    >
                        Variables
                    </button>
                </div>

                <div class="search-container-mini">
                    <input
                        type="text"
                        class="search-input-mini"
                        id="search-input"
                        placeholder=${placeholder}
                        @input="${(e: InputEvent) =>
                            this.handleCollectionSearch(
                                (e.target as HTMLInputElement).value
                            )}"
                    />

                    <button class="search-button-mini">
                        <svg
                            class="search-icon-mini"
                            viewBox="0 0 24 24"
                            fill="currentColor"
                        >
                            <path
                                d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"
                            />
                        </svg>
                        Search
                    </button>
                </div>

                <!-- TODO: it may be nice to have a quick search, perhaps by recent trends? 
                <div class="quick-links-mini">
                    <a href="#" class="quick-link-mini" onclick="quickSearch('GPM')"
                        >GPM Precipitation</a
                    >
                    <a href="#" class="quick-link-mini" onclick="quickSearch('MODIS')"
                        >MODIS Data</a
                    >
                    <a
                        href="#"
                        class="quick-link-mini"
                        onclick="quickSearch('Landsat')"
                        >Landsat Imagery</a
                    >
                    <a href="#" class="quick-link-mini" onclick="quickSearch('AIRS')"
                        >Atmospheric Data</a
                    >
                </div>
                -->

                <div id="search-results-section" class="search-results-section">
                    ${this.collectionSearchLoading
                        ? html`
                              <div id="loading-mini" class="loading-mini">
                                  <div class="spinner-mini"></div>
                                  <div>Searching NASA CMR...</div>
                              </div>
                          `
                        : this.collectionSearchResults?.length
                          ? html` <div
                                id="results-container-mini"
                                class="results-container-mini"
                            >
                                ${this.collectionSearchResults?.map(
                                    item => html`
                                        <div
                                            class="result-item-mini"
                                            @click=${() => {
                                                this.collectionEntryId =
                                                    item.collectionEntryId
                                                this.collectionAccordionOpen = false
                                                this.collectionLoading = true

                                                // if this item is a variable, we'll also go ahead and select the variable
                                                if (item.type === 'variable') {
                                                    this.selectedVariables = [
                                                        {
                                                            name: item.entryId,
                                                            href: '',
                                                            conceptId: item.conceptId,
                                                        },
                                                    ]
                                                }

                                                this.requestUpdate()
                                            }}
                                            style="cursor: pointer;"
                                        >
                                            <div class="result-title-mini">
                                                ${item.title}
                                            </div>
                                            <div class="result-id-mini">
                                                ${item.entryId}
                                            </div>
                                            <div class="result-description-mini">
                                                ${item.summary || item.title}
                                            </div>
                                            <div class="result-meta-mini">
                                                <span>📅 2000-02-24 - ongoing</span>
                                                <span>🌍 Global</span>
                                                <span>🏢 ${item.provider}</span>
                                                ${item.type === 'variable'
                                                    ? html` <span
                                                          >📊
                                                          ${item.collectionEntryId}</span
                                                      >`
                                                    : nothing}
                                                <span class="tag-mini"
                                                    >${item.type.toUpperCase()}</span
                                                >
                                            </div>
                                        </div>
                                    `
                                )}
                            </div>`
                          : this.collectionSearchResults &&
                              this.collectionSearchResults.length === 0
                            ? html`<div id="no-results-mini" class="no-results-mini">
                                  <p>
                                      No results found for
                                      '${this.collectionSearchQuery}'. Try adjusting
                                      your search term.
                                  </p>
                              </div>`
                            : nothing}
                </div>
            </terra-accordion>

            ${this.collectionLoading
                ? html`
                      <div
                          class="collection-loading-bar"
                          style="display: flex; align-items: center; gap: 10px; margin: 16px 0;"
                      >
                          <span
                              class="loading-spinner"
                              style="width: 20px; height: 20px; border: 3px solid #ccc; border-top: 3px solid #31708f; border-radius: 50%; display: inline-block; animation: spin 1s linear infinite;"
                          ></span>
                          Retrieving collection, please wait...
                      </div>
                      <style>
                          @keyframes spin {
                              0% {
                                  transform: rotate(0deg);
                              }
                              100% {
                                  transform: rotate(360deg);
                              }
                          }
                      </style>
                  `
                : nothing}
        `
    }

    @debounce(500)
    handleCollectionSearch(searchTerm: string) {
        this.collectionSearchQuery = searchTerm
    }

    #renderOutputFormatSelection() {
        return html`
            <terra-accordion>
                <div slot="summary">
                    <span class="accordion-title">File Format:</span>
                </div>

                <div
                    slot="summary-right"
                    style="display: flex; align-items: center; gap: 10px;"
                >
                    <span>${getFriendlyNameForMimeType(this.selectedFormat)}</span>

                    <button class="reset-btn" @click=${this.#resetFormatSelection}>
                        Reset
                    </button>
                </div>

                <div class="accordion-content" style="margin-top: 12px;">
                    ${(() => {
                        const allFormats =
                            this.collectionWithServices?.outputFormats || []
                        const uniqueFormats = Array.from(new Set(allFormats))

                        // Consolidate NetCDF formats - if both exist, only show netcdf4
                        const hasNetcdf4 = uniqueFormats.includes(
                            'application/x-netcdf4'
                        )
                        const hasNetcdfClassic =
                            uniqueFormats.includes('application/netcdf')

                        let displayFormats = uniqueFormats
                        if (hasNetcdf4 && hasNetcdfClassic) {
                            // Both exist - remove netcdf classic, keep netcdf4
                            displayFormats = uniqueFormats.filter(
                                f => f !== 'application/netcdf'
                            )
                        }

                        return displayFormats.map(
                            format => html`
                                <label
                                    style="display: flex; align-items: center; gap: 8px; padding: 5px;"
                                >
                                    <input
                                        type="radio"
                                        name="output-format"
                                        value="${format}"
                                        .checked=${this.selectedFormat === format}
                                        @change=${() =>
                                            (this.selectedFormat = format)}
                                    />
                                    ${getFriendlyNameForMimeType(format)}
                                </label>
                            `
                        )
                    })()}
                </div>
            </terra-accordion>
        `
    }

    #renderDateRangeSelection() {
        const { startDate: defaultStartDate, endDate: defaultEndDate } =
            this.#getCollectionDateRange()
        const startDate =
            this.selectedDateRange.startDate ??
            this.granuleMinDate ??
            defaultStartDate
        const endDate =
            this.selectedDateRange.endDate ?? this.granuleMaxDate ?? defaultEndDate
        const showError =
            this.touchedFields.has('date') &&
            (!this.selectedDateRange.startDate || !this.selectedDateRange.endDate)

        return html`
            <terra-accordion>
                <div slot="summary">
                    <span class="accordion-title">Refine Date Range:</span>
                </div>

                <div
                    slot="summary-right"
                    style="display: flex; align-items: center; gap: 10px;"
                >
                    ${showError
                        ? html`<span class="accordion-value error"
                              >Please select a date range</span
                          >`
                        : this.touchedFields.has('date') && startDate && endDate
                          ? html`<span class="accordion-value"
                                >${startDate} to ${endDate}</span
                            >`
                          : nothing}
                    <button class="reset-btn" @click=${this.#resetDateRangeSelection}>
                        Reset
                    </button>
                </div>

                <div style="width: 300px">
                    <terra-date-picker
                        allow-input
                        inline
                        range
                        split-inputs
                        show-presets
                        ?enable-time=${this.controller.isSubDaily}
                        start-label="Start Date"
                        end-label="End Date"
                        .minDate=${this.granuleMinDate ?? defaultStartDate}
                        .maxDate=${this.granuleMaxDate ?? defaultEndDate}
                        .startDate=${this.selectedDateRange.startDate}
                        .endDate=${this.selectedDateRange.endDate}
                        @terra-date-range-change=${this.#handleDateChange}
                    ></terra-date-picker>
                </div>

                <div
                    style="display: flex; gap: 16px; margin-top: 15px; color: #31708f;"
                >
                    <span
                        ><strong>Available Range:</strong> ${defaultStartDate} to
                        ${defaultEndDate}</span
                    >
                    ${this.controller.isSubDaily
                        ? html`<span
                              ><strong>Note:</strong> All dates and times are in
                              UTC.</span
                          >`
                        : nothing}
                </div>
            </terra-accordion>
        `
    }

    #handleDateChange = (e: TerraDateRangeChangeEvent) => {
        this.#markFieldTouched('date')
        this.selectedDateRange = {
            ...this.selectedDateRange,
            startDate: e.detail.startDate,
            endDate: e.detail.endDate,
        }
    }

    #resetDateRangeSelection = () => {
        this.selectedDateRange = { startDate: null, endDate: null }
    }

    #resetFormatSelection = () => {
        // Reset to NetCDF if available, otherwise first available format from collection, or fall back to default
        if (this.collectionWithServices?.outputFormats?.length) {
            const netcdfFormat = this.collectionWithServices.outputFormats.find(
                format =>
                    format === 'application/x-netcdf4' ||
                    format === 'application/netcdf'
            )
            this.selectedFormat =
                netcdfFormat || this.collectionWithServices.outputFormats[0]
        } else {
            this.selectedFormat = defaultSubsetFileMimeType
        }
    }

    #getCollectionDateRange() {
        // Prefer sampling data for accurate date ranges
        const samplingMinDate = this.controller.granuleMinDate
        const samplingMaxDate = this.controller.granuleMaxDate

        if (samplingMinDate && samplingMaxDate) {
            return {
                startDate: samplingMinDate.slice(0, 10),
                endDate: samplingMaxDate.slice(0, 10),
            }
        }

        // Fallback to collection metadata if sampling is not available
        const temporalExtents =
            this.collectionWithServices?.collection?.TemporalExtents
        if (!temporalExtents || !temporalExtents.length)
            return {
                startDate: null,
                endDate: null,
            }

        let minStart = null
        let maxEnd = null
        const today = new Date()

        for (const temporal of temporalExtents) {
            for (const range of temporal.RangeDateTimes) {
                const start = new Date(range.BeginningDateTime)
                let end
                if (temporal.EndsAtPresentFlag || !range.EndingDateTime) {
                    end = today
                } else {
                    end = new Date(range.EndingDateTime)
                }
                if (!minStart || start < minStart) minStart = start
                if (!maxEnd || end > maxEnd) maxEnd = end
            }
        }

        return {
            startDate: minStart ? minStart.toISOString().slice(0, 10) : null,
            endDate: maxEnd ? maxEnd.toISOString().slice(0, 10) : null,
        }
    }

    #handleRegionAccordionToggle() {
        // sometimes the map will show up kind of wonky when it's in an accordion
        // this makes sure it resets itself if that occurs
        this.spatialPicker?.invalidateSize()
    }

    isLatLng(value: any): value is LatLng {
        return value && typeof value.lat === 'number' && typeof value.lng === 'number'
    }

    isLatLngBounds(value: any): value is LatLngBounds {
        return (
            value &&
            typeof value.getSouthWest === 'function' &&
            typeof value.getNorthEast === 'function'
        )
    }

    #renderSpatialSelection() {
        const showError = this.touchedFields.has('spatial') && !this.spatialSelection
        let boundingRects: any =
            this.collectionWithServices?.collection?.SpatialExtent
                ?.HorizontalSpatialDomain?.Geometry?.BoundingRectangles

        if (boundingRects && !Array.isArray(boundingRects)) {
            boundingRects = [boundingRects]
        }

        let spatialString = ''

        // convert spatial to string
        if (this.isLatLng(this.spatialSelection)) {
            spatialString = `${this.spatialSelection.lat}, ${this.spatialSelection.lng}`
        } else if (this.isLatLngBounds(this.spatialSelection)) {
            spatialString = `${this.spatialSelection.getSouthWest().lat}, ${this.spatialSelection.getSouthWest().lng}, ${this.spatialSelection.getNorthEast().lat}, ${this.spatialSelection.getNorthEast().lng}`
        } else if (
            this.spatialSelection &&
            'w' in this.spatialSelection &&
            's' in this.spatialSelection &&
            'e' in this.spatialSelection &&
            'n' in this.spatialSelection
        ) {
            spatialString = `${this.spatialSelection.w}, ${this.spatialSelection.s}, ${this.spatialSelection.e}, ${this.spatialSelection.n}`
        } else if (this.spatialSelection) {
            spatialString = this.spatialSelection
        }

        return html`
            <terra-accordion
                @terra-accordion-toggle=${this.#handleRegionAccordionToggle}
            >
                <div slot="summary">
                    <span class="accordion-title">Refine Region:</span>
                </div>

                <div
                    slot="summary-right"
                    style="display: flex; align-items: center; gap: 10px;"
                >
                    ${showError
                        ? html`<span class="accordion-value error"
                              >Please select a region</span
                          >`
                        : spatialString
                          ? html`<span class="accordion-value"
                                >${spatialString}</span
                            >`
                          : nothing}
                    <button class="reset-btn" @click=${this.#resetSpatialSelection}>
                        Reset
                    </button>
                </div>
                <div class="accordion-content">
                    <terra-spatial-picker
                        part="spatial-picker"
                        inline
                        hide-label
                        hide-point-selection
                        no-world-wrap
                        .spatialConstraints=${this.controller.spatialConstraints ||
                        '-180, -90, 180, 90'}
                        .initialValue=${spatialString}
                        @terra-map-change=${this.#handleSpatialChange}
                    ></terra-spatial-picker>
                    <div
                        style="display: flex; gap: 16px; margin-top: 15px; color: #31708f;"
                    >
                        <span
                            ><strong>Available Range:</strong> ${this.controller
                                .spatialConstraints}</span
                        >
                    </div>
                </div>
            </terra-accordion>
        `
    }

    #handleSpatialChange = (e: TerraMapChangeEvent) => {
        this.#markFieldTouched('spatial')
        const round2 = (n: number) => parseFloat(Number(n).toFixed(2))

        if (e.detail.type === MapEventType.BBOX) {
            this.spatialSelection = {
                e: round2(e.detail.bounds.getNorthEast().lng),
                n: round2(e.detail.bounds.getNorthEast().lat),
                w: round2(e.detail.bounds.getSouthWest().lng),
                s: round2(e.detail.bounds.getSouthWest().lat),
            }
        } else if (e.detail.type === MapEventType.POINT) {
            this.spatialSelection = e.detail.latLng
        } else {
            this.spatialSelection = null
        }
    }

    #resetSpatialSelection = () => {
        const spatial_constraints =
            this.collectionWithServices?.collection?.SpatialExtent
                ?.HorizontalSpatialDomain?.Geometry?.BoundingRectangles

        if (!spatial_constraints) {
            this.spatialSelection = null
            return
        }

        type BoundingRect = {
            WestBoundingCoordinate: number
            SouthBoundingCoordinate: number
            EastBoundingCoordinate: number
            NorthBoundingCoordinate: number
        }

        const normalized: BoundingRect[] = Array.isArray(spatial_constraints)
            ? spatial_constraints
            : [spatial_constraints]

        const rect = normalized[0]

        this.spatialSelection = {
            w: Number(rect.WestBoundingCoordinate),
            s: Number(rect.SouthBoundingCoordinate),
            e: Number(rect.EastBoundingCoordinate),
            n: Number(rect.NorthBoundingCoordinate),
        }

        this.#markFieldTouched('spatial')
    }

    #renderVariableSelection() {
        const variables = this.collectionWithServices?.variables || []
        const giovanniError =
            this.touchedFields.has('variables') && this.#getGiovanniValidationError()
        const basicError =
            this.touchedFields.has('variables') && this.selectedVariables.length === 0
        const showError = giovanniError || basicError
        const errorMessage =
            giovanniError || (basicError ? 'Please select at least one variable' : '')

        const tree = this.#buildVariableTree(variables)
        const allGroups = this.#getAllGroupPaths(tree)
        const allExpanded =
            allGroups.length > 0 &&
            allGroups.every(g => this.expandedVariableGroups.has(g))

        return html`
            <terra-accordion>
                <div slot="summary">
                    <span class="accordion-title">Select Variables:</span>
                </div>
                <div
                    slot="summary-right"
                    style="display: flex; align-items: center; gap: 10px;"
                >
                    ${showError
                        ? html`<span class="accordion-value error"
                              >${errorMessage}</span
                          >`
                        : this.selectedVariables.length
                          ? html`<span class="accordion-value"
                                >${this.selectedVariables.length} selected</span
                            >`
                          : nothing}

                    <button class="reset-btn" @click=${this.#resetVariableSelection}>
                        Reset
                    </button>
                </div>
                <div class="accordion-content">
                    <terra-input
                        label="Filter variables"
                        placeholder="Search by variable name..."
                        .value=${this.variableFilterText}
                        @input=${(e: Event) => {
                            const input = e.target as HTMLInputElement
                            this.variableFilterText = input.value
                            this.#handleVariableFilterChange()
                        }}
                        style="margin-bottom: 10px;"
                    ></terra-input>
                    <button
                        class="reset-btn"
                        style="margin-bottom: 10px;"
                        @click=${() => this.#toggleExpandCollapseAll(tree)}
                    >
                        ${allExpanded ? 'Collapse Tree' : 'Expand Tree'}
                    </button>

                    ${this.#isGiovanniFormat() && this.giovanniConfiguredVariables
                        ? html`
                              <terra-alert
                                  open
                                  appearance="white"
                                  style="margin: 10px 0"
                              >
                                  <terra-icon
                                      slot="icon"
                                      name="outline-information-circle"
                                      library="heroicons"
                                  ></terra-icon>
                                  Only certain variables are supported for the
                                  selected output format. (Giovanni service)
                              </terra-alert>
                              <terra-alert
                                  open
                                  appearance="white"
                                  style="margin: 10px 0"
                              >
                                  <terra-icon
                                      slot="icon"
                                      name="outline-information-circle"
                                      library="heroicons"
                                  ></terra-icon>
                                  User's are allowed to select only one variable for
                                  the selected output format. (Giovanni service)
                              </terra-alert>
                          `
                        : nothing}
                    ${variables.length === 0
                        ? html`<p style="color: #666; font-style: italic;">
                              No variables available for this collection.
                          </p>`
                        : this.#renderVariableTree(
                              this.#filterVariableTree(tree),
                              []
                          )}
                </div>
            </terra-accordion>
        `
    }

    #filterVariableTree(tree: Record<string, any>): Record<string, any> {
        if (!this.variableFilterText.trim()) {
            return tree
        }

        const filterText = this.variableFilterText.toLowerCase().trim()

        const filterNode = (node: Record<string, any>): Record<string, any> => {
            const result: Record<string, any> = {}
            for (const [key, value] of Object.entries(node)) {
                if (value.__isLeaf) {
                    // Check if variable name matches filter
                    const variableName = value.__variable.name.toLowerCase()
                    if (variableName.includes(filterText)) {
                        result[key] = value
                    }
                } else {
                    // Recursively filter children
                    const filteredChildren = filterNode(value.__children)
                    // Include group if it has matching children or if group name matches
                    if (
                        Object.keys(filteredChildren).length > 0 ||
                        key.toLowerCase().includes(filterText)
                    ) {
                        result[key] = {
                            ...value,
                            __children: filteredChildren,
                        }
                    }
                }
            }
            return result
        }

        return filterNode(tree)
    }

    #handleVariableFilterChange() {
        if (!this.variableFilterText.trim()) {
            return
        }

        const variables = this.collectionWithServices?.variables || []
        const tree = this.#buildVariableTree(variables)
        const filterText = this.variableFilterText.toLowerCase().trim()

        // Find all groups that contain matching variables and auto-expand them
        const groupsToExpand = new Set<string>()

        const findMatchingGroups = (
            node: Record<string, any>,
            path: string[] = []
        ) => {
            for (const [key, value] of Object.entries(node)) {
                if (value.__isLeaf) {
                    const variableName = value.__variable.name.toLowerCase()
                    if (variableName.includes(filterText)) {
                        // Add all parent groups to the expand set
                        for (let i = 0; i < path.length; i++) {
                            const groupPath = path.slice(0, i + 1).join('/')
                            groupsToExpand.add(groupPath)
                        }
                    }
                } else {
                    const groupPath = [...path, key].join('/')
                    findMatchingGroups(value.__children, [...path, key])
                    // Also check if group name matches
                    if (key.toLowerCase().includes(filterText)) {
                        groupsToExpand.add(groupPath)
                    }
                }
            }
        }

        findMatchingGroups(tree)

        // Update expanded groups
        if (groupsToExpand.size > 0) {
            this.expandedVariableGroups = new Set([
                ...this.expandedVariableGroups,
                ...groupsToExpand,
            ])
        }
    }

    #buildVariableTree(variables: Variable[]): Record<string, any> {
        let filteredVariables = variables

        if (this.#isGiovanniFormat() && this.giovanniConfiguredVariables) {
            const originalCount = variables.length

            filteredVariables = variables.filter(v => {
                // Convert internal format (dots) to Giovanni format (underscores)
                // Example: M2T1NXSLV_5.12.4_CLDPRS -> M2T1NXSLV_5_12_4_CLDPRS
                const shortName = this.collectionWithServices?.shortName
                const version = this.collectionWithServices?.collection?.Version

                if (!shortName || !version) {
                    return false
                }

                const giovanniVariableName = convertVariableEntryIdToGiovanniFormat(
                    shortName,
                    version,
                    v.name
                )

                return this.giovanniConfiguredVariables!.has(giovanniVariableName)
            })

            console.log(
                `Filtered ${originalCount - filteredVariables.length} variables for Giovanni format. Showing ${filteredVariables.length} of ${originalCount}.`
            )
        }

        const root: Record<string, any> = {}
        for (const v of filteredVariables) {
            const parts = v.name.split('/')
            let node = root
            for (let i = 0; i < parts.length; i++) {
                const part = parts[i]
                if (!node[part]) node[part] = { __children: {}, __isLeaf: false }
                if (i === parts.length - 1) {
                    node[part].__isLeaf = true
                    node[part].__variable = v
                }
                node = node[part].__children
            }
        }
        return root
    }

    #renderVariableTree(node: Record<string, any>, path: string[]): unknown {
        const isGiovanni = this.#isGiovanniFormat()
        return html`
            <div style="margin-left: ${path.length * 20}px;">
                ${Object.entries(node).map(([key, value]: [string, any]) => {
                    const groupPath = [...path, key].join('/')
                    if (value.__isLeaf) {
                        // Leaf node (variable)
                        return html`
                            <div class="option-row">
                                <label class="checkbox-option">
                                    <input
                                        type="${isGiovanni ? 'radio' : 'checkbox'}"
                                        name="${isGiovanni
                                            ? 'variable-selection'
                                            : ''}"
                                        .checked=${this.selectedVariables.some(
                                            v => v.name === value.__variable.name
                                        )}
                                        @change=${(e: Event) =>
                                            this.#toggleVariableSelection(
                                                e,
                                                value.__variable
                                            )}
                                    />
                                    <span>${key}</span>
                                </label>
                            </div>
                        `
                    } else {
                        // Group node
                        const expanded = this.expandedVariableGroups.has(groupPath)
                        return html`
                            <div class="option-row" style="align-items: flex-start;">
                                <span
                                    style="cursor: pointer; display: flex; align-items: center;"
                                    @click=${() => this.#toggleGroupExpand(groupPath)}
                                >
                                    <terra-icon
                                        library="heroicons"
                                        name="${expanded
                                            ? 'outline-minus-circle'
                                            : 'outline-plus-circle'}"
                                        style="margin-right: 4px;"
                                    ></terra-icon>
                                    <span style="font-weight: 500;">${key}</span>
                                </span>
                            </div>
                            ${expanded
                                ? this.#renderVariableTree(value.__children, [
                                      ...path,
                                      key,
                                  ])
                                : ''}
                        `
                    }
                })}
            </div>
        `
    }

    #getAllGroupPaths(node: Record<string, any>, path: string[] = []): string[] {
        let groups: string[] = []
        for (const [key, value] of Object.entries(node)) {
            if (!value.__isLeaf) {
                const groupPath = [...path, key].join('/')
                groups.push(groupPath)
                groups = groups.concat(
                    this.#getAllGroupPaths(value.__children, [...path, key])
                )
            }
        }
        return groups
    }

    #toggleGroupExpand(groupPath: string) {
        const set = new Set(this.expandedVariableGroups)
        if (set.has(groupPath)) {
            set.delete(groupPath)
        } else {
            set.add(groupPath)
        }
        this.expandedVariableGroups = set
    }

    #toggleExpandCollapseAll(tree: Record<string, any>) {
        const allGroups = this.#getAllGroupPaths(tree)
        const allExpanded =
            allGroups.length > 0 &&
            allGroups.every((g: string) => this.expandedVariableGroups.has(g))
        if (allExpanded) {
            this.expandedVariableGroups = new Set()
        } else {
            this.expandedVariableGroups = new Set(allGroups)
        }
    }

    #toggleVariableSelection(e: Event, variable: Variable) {
        this.#markFieldTouched('variables')
        const checked = (e.target as HTMLInputElement).checked

        if (this.#isGiovanniFormat()) {
            // Radio button behavior for Giovanni - replace selection with only this variable
            if (checked) {
                this.selectedVariables = [variable]
            }
        } else {
            // Checkbox behavior for non-Giovanni - allow multiple selections
            if (checked) {
                if (!this.selectedVariables.some(v => v.name === variable.name)) {
                    this.selectedVariables = [...this.selectedVariables, variable]
                }
            } else {
                this.selectedVariables = this.selectedVariables.filter(
                    v => v.name !== variable.name
                )
            }
        }
    }

    #markFieldTouched(field: string) {
        this.touchedFields = new Set(this.touchedFields).add(field)
    }

    #resetVariableSelection = () => {
        this.selectedVariables = []
    }

    #renderJobStatus() {
        if (!this.controller.currentJob?.jobID) {
            return html`<div class="results-section" id="job-status-section">
                <div
                    style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px;"
                >
                    <h2 class="results-title" style="margin: 0;">Results:</h2>
                    ${!this.isHistoryView
                        ? html`
                              <terra-button
                                  variant="default"
                                  size="small"
                                  @click=${this.#backToSubsetOptions}
                              >
                                  ← Back to Subset Options
                              </terra-button>
                          `
                        : nothing}
                </div>

                <div class="progress-container">
                    <div class="progress-text">
                        <span class="spinner"></span>
                        <span class="status-running">Searching for data...</span>
                    </div>

                    <div class="progress-bar">
                        <div class="progress-fill" style="width: 0%"></div>
                    </div>
                </div>

                ${this.#renderJobMessage()}
            </div>`
        }

        return html`
            <div class="results-section" id="job-status-section">
                <div
                    style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px;"
                >
                    <h2 class="results-title" style="margin: 0;">Results:</h2>
                    ${!this.isHistoryView
                        ? html`
                              <terra-button
                                  variant="default"
                                  size="small"
                                  @click=${this.#backToSubsetOptions}
                              >
                                  ← Back to Subset Options
                              </terra-button>
                          `
                        : nothing}
                </div>

                ${this.controller.currentJob!.status !== 'canceled' &&
                this.controller.currentJob!.status !== 'failed'
                    ? html` <div class="progress-container">
                          <div class="progress-text">
                              ${this.controller.currentJob!.progress >= 100
                                  ? html`
                                        <span class="status-complete"
                                            >✓ Search complete</span
                                        >
                                    `
                                  : html`
                                        <span class="spinner"></span>
                                        <span class="status-running"
                                            >Searching for data...
                                            (${this.controller.currentJob!
                                                .progress}%)</span
                                        >
                                    `}
                          </div>

                          <div class="progress-bar">
                              <div
                                  class="progress-fill"
                                  style="width: ${this.controller.currentJob!
                                      .progress}%"
                              ></div>
                          </div>
                      </div>`
                    : nothing}

                <div class="search-status">
                    <span class="file-count"
                        >Found ${this.#numberOfFilesFoundEstimate()} files</span
                    >
                    out of estimated
                    <span class="estimated-total"
                        >${this.controller.currentJob!.numInputGranules.toLocaleString()}</span
                    >
                </div>

                ${this.#renderJobMessage()}
                ${this.controller.currentJob!.errors?.length
                    ? html`
                          <terra-accordion>
                              <div slot="summary">
                                  <span
                                      class="accordion-title"
                                      style="color: #dc3545;"
                                      >Errors
                                      (${this.controller.currentJob!.errors
                                          .length})</span
                                  >
                              </div>
                              <div class="accordion-content">
                                  <ul
                                      style="color: #dc3545; font-size: 14px; padding-left: 20px;"
                                  >
                                      ${this.controller.currentJob!.errors.map(
                                          (err: {
                                              url: string
                                              message: string
                                          }) => html`
                                              <li style="margin-bottom: 12px;">
                                                  <a
                                                      href="${err.url}"
                                                      target="_blank"
                                                      style="word-break: break-all; color: #dc3545; text-decoration: underline;"
                                                  >
                                                      ${err.url}
                                                  </a>
                                                  <div style="margin-top: 2px;">
                                                      ${err.message}
                                                  </div>
                                              </li>
                                          `
                                      )}
                                  </ul>
                              </div>
                          </terra-accordion>
                      `
                    : nothing}

                <div class="tabs">
                    <button
                        class="tab ${this.selectedTab === 'web-links'
                            ? 'active'
                            : ''}"
                        @click=${() => (this.selectedTab = 'web-links')}
                    >
                        Web Links
                    </button>

                    ${!this.isHistoryView
                        ? html`
                              <button
                                  class="tab ${this.selectedTab === 'selected-params'
                                      ? 'active'
                                      : ''}"
                                  @click=${() =>
                                      (this.selectedTab = 'selected-params')}
                              >
                                  Selected Parameters
                              </button>
                          `
                        : nothing}
                </div>
                <div
                    id="web-links"
                    class="tab-content ${this.selectedTab === 'web-links'
                        ? 'active'
                        : ''}"
                >
                    ${this.#getDocumentationLinks().length
                        ? html`
                              <div class="documentation-links">
                                  ${this.#getDocumentationLinks().map(
                                      link => html`
                                          <a href="${link.href}" class="doc-link"
                                              >${link.title}</a
                                          >
                                      `
                                  )}
                              </div>
                          `
                        : nothing}

                    <ul class="file-list">
                        ${this.#getDataLinks().map(
                            link => html`
                                <li class="file-item">
                                    <a
                                        href="${link.href}"
                                        class="file-link"
                                        target="_blank"
                                    >
                                        ${link.title}
                                    </a>
                                </li>
                            `
                        )}
                    </ul>
                </div>

                <div
                    id="selected-params"
                    class="tab-content ${this.selectedTab === 'selected-params'
                        ? 'active'
                        : ''}"
                >
                    ${this.#renderSelectedParams()}
                </div>
            </div>

            ${!this.dialog
                ? html`
                      <div class="footer">
                          ${this.controller.currentJob!.status ===
                              Status.SUCCESSFUL ||
                          this.controller.currentJob!.status ===
                              Status.COMPLETE_WITH_ERRORS
                              ? html`
                                    <div
                                        style="display: flex; align-items: center; gap: 8px;"
                                    >
                                        <terra-dropdown
                                            @terra-select=${this
                                                .#handleDownloadSelect}
                                        >
                                            <terra-button slot="trigger" caret>
                                                Download Options
                                            </terra-button>
                                            <terra-menu>
                                                <terra-menu-item value="file-list">
                                                    <svg
                                                        slot="prefix"
                                                        viewBox="0 0 24 24"
                                                        width="16"
                                                        height="16"
                                                        style="width: 16px; height: 16px;"
                                                    >
                                                        <path
                                                            fill="currentColor"
                                                            d="M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm2 16H8v-2h8v2zm0-4H8v-2h8v2zm-3-5V3.5L18.5 9H13z"
                                                        />
                                                    </svg>
                                                    File List
                                                </terra-menu-item>
                                                <terra-menu-item
                                                    value="python-script"
                                                >
                                                    <svg
                                                        slot="prefix"
                                                        viewBox="0 0 128 128"
                                                        width="16"
                                                        height="16"
                                                        style="width: 16px; height: 16px;"
                                                    >
                                                        <path
                                                            fill="currentColor"
                                                            d="M49.33 62h29.159C86.606 62 93 55.132 93 46.981V19.183c0-7.912-6.632-13.856-14.555-15.176-5.014-.835-10.195-1.215-15.187-1.191-4.99.023-9.612.448-13.805 1.191C37.098 6.188 35 10.758 35 19.183V30h29v4H23.776c-8.484 0-15.914 5.108-18.237 14.811-2.681 11.12-2.8 17.919 0 29.53C7.614 86.983 12.569 93 21.054 93H31V79.952C31 70.315 39.428 62 49.33 62zm-1.838-39.11c-3.026 0-5.478-2.479-5.478-5.545 0-3.079 2.451-5.581 5.478-5.581 3.015 0 5.479 2.502 5.479 5.581-.001 3.066-2.465 5.545-5.479 5.545zm74.789 25.921C120.183 40.363 116.178 34 107.682 34H97v12.981C97 57.031 88.206 65 78.489 65H49.33C41.342 65 35 72.326 35 80.326v27.8c0 7.91 6.745 12.564 14.462 14.834 9.242 2.717 17.994 3.208 29.051 0C85.862 120.831 93 116.549 93 108.126V97H64v-4h43.682c8.484 0 11.647-5.776 14.599-14.66 3.047-9.145 2.916-17.799 0-29.529zm-41.955 55.606c3.027 0 5.479 2.479 5.479 5.547 0 3.076-2.451 5.579-5.479 5.579-3.015 0-5.478-2.502-5.478-5.579 0-3.068 2.463-5.547 5.478-5.547z"
                                                        ></path>
                                                    </svg>
                                                    Python Script
                                                </terra-menu-item>
                                                <terra-menu-item
                                                    value="earthdata-download"
                                                >
                                                    <svg
                                                        slot="prefix"
                                                        viewBox="0 0 64 64"
                                                        fill="none"
                                                        width="16"
                                                        height="16"
                                                        style="width: 16px; height: 16px;"
                                                    >
                                                        <circle
                                                            cx="32"
                                                            cy="32"
                                                            r="28"
                                                            fill="currentColor"
                                                        />
                                                        <path
                                                            d="M32 14v26M32 40l-9-9M32 40l9-9"
                                                            stroke="#fff"
                                                            stroke-width="4"
                                                            stroke-linecap="round"
                                                            stroke-linejoin="round"
                                                            fill="none"
                                                        />
                                                    </svg>
                                                    Earthdata Download
                                                </terra-menu-item>
                                            </terra-menu>
                                        </terra-dropdown>

                                        <terra-button
                                            outline
                                            @click=${() =>
                                                this.#handleJupyterNotebookClick()}
                                        >
                                            <terra-icon
                                                name="outline-code-bracket"
                                                library="heroicons"
                                                font-size="1.5em"
                                                style="margin-right: 5px;"
                                            ></terra-icon>
                                            Open in Jupyter Notebook
                                        </terra-button>
                                    </div>
                                `
                              : nothing}
                          ${this.controller.currentJob!.status === 'running'
                              ? html`<button
                                    class="btn btn-success"
                                    @click=${this.#cancelJob}
                                    ?disabled=${this.cancelingGetData}
                                >
                                    ${this.cancelingGetData
                                        ? 'Canceling...'
                                        : 'Cancel request'}
                                </button>`
                              : nothing}

                          <div class="job-info">
                              Job ID:
                              <span class="job-id">
                                  ${this.bearerToken
                                      ? html`<a
                                            href="https://harmony.earthdata.nasa.gov/jobs/${this
                                                .controller.currentJob!.jobID}"
                                            target="_blank"
                                            >${this.controller.currentJob!.jobID}</a
                                        >`
                                      : this.controller.currentJob!.jobID}
                              </span>
                              <span class="info-icon">?</span>
                          </div>
                      </div>
                  `
                : nothing}
        `
    }

    #renderSelectedParams() {
        const collection = this.collectionWithServices?.collection
        const variables = this.selectedVariables.length
            ? this.selectedVariables.map(v => v.name)
            : ['All']
        const dateRange =
            this.selectedDateRange.startDate && this.selectedDateRange.endDate
                ? `${this.selectedDateRange.startDate} to ${this.selectedDateRange.endDate}`
                : '—'
        let spatial = '—'

        if (this.spatialSelection) {
            if ('w' in this.spatialSelection) {
                spatial = `Bounding Box: ${this.spatialSelection.w}, ${this.spatialSelection.s}, ${this.spatialSelection.e}, ${this.spatialSelection.n}`
            } else if (
                'lat' in this.spatialSelection &&
                'lng' in this.spatialSelection
            ) {
                spatial = `Point: ${this.spatialSelection.lat}, ${this.spatialSelection.lng}`
            }
        }

        return html`
            <dl class="params-summary">
                <div>
                    <dt><strong>Dataset</strong></dt>
                    <dd>${collection?.EntryTitle ?? '—'}</dd>
                </div>
                <div>
                    <dt><strong>Variables</strong></dt>
                    <dd>${variables.map(v => html`<div>${v}</div>`)}</dd>
                </div>
                <div>
                    <dt><strong>Date Range</strong></dt>
                    <dd>${dateRange}</dd>
                </div>
                <div>
                    <dt><strong>Spatial</strong></dt>
                    <dd>${spatial}</dd>
                </div>
            </dl>

            <terra-button @click=${this.#refineParameters}
                >Refine Parameters</terra-button
            >
        `
    }

    #cancelJob() {
        this.cancelingGetData = true
        this.controller.cancelCurrentJob()
    }

    #getData() {
        // Validate before proceeding
        const validationError = this.#getGiovanniValidationError()
        if (validationError) {
            this.validationError = validationError
            this.#markFieldTouched('variables')
            return
        }

        // Clear any previous validation errors
        this.validationError = undefined

        this.cancelingGetData = false
        this.#touchAllFields() // touch all fields, so errors will show if fields are invalid

        // cancel any existing running job
        this.controller.cancelCurrentJob()
        this.controller.currentJob = null

        // Clear the jobId so we can create a new job
        this.jobId = undefined

        this.controller.jobStatusTask.run().then(() => {
            // After job is created, update jobId
            if (this.controller.currentJob?.jobID) {
                this.jobId = this.controller.currentJob.jobID
            }
        })

        // scroll the job-status-section into view
        setTimeout(() => {
            const el = this.renderRoot.querySelector('#job-status-section')
            el?.scrollIntoView({ behavior: 'smooth' })
        }, 100)

        this.refineParameters = false // reset refine parameters, if the user had previously clicked that button
        this.isHistoryView = false // this is a new job being created, not viewing from history
    }

    #touchAllFields() {
        this.touchedFields = new Set(['variables', 'spatial'])
    }

    #numberOfFilesFoundEstimate() {
        return Math.floor(
            (this.controller.currentJob!.numInputGranules *
                this.controller.currentJob!.progress) /
                100
        )
    }

    #getDocumentationLinks() {
        return this.controller.currentJob!.links.filter(
            link => link.rel === 'stac-catalog-json'
        )
    }

    #getDataLinks() {
        return this.controller.currentJob!.links.filter(link => link.rel === 'data')
    }

    #hasAtLeastOneSubsetOption() {
        return (
            this.collectionWithServices?.bboxSubset ||
            this.collectionWithServices?.shapeSubset ||
            this.collectionWithServices?.variableSubset ||
            this.collectionWithServices?.temporalSubset
        )
    }

    #hasSpatialSubset() {
        return (
            this.collectionWithServices?.bboxSubset ||
            this.collectionWithServices?.shapeSubset
        )
    }

    #renderJobMessage() {
        const warningStatuses = [
            Status.CANCELED,
            Status.COMPLETE_WITH_ERRORS,
            Status.RUNNING_WITH_ERRORS,
        ]
        const errorStatuses = [Status.FAILED]

        let type = 'normal'
        if (warningStatuses.includes(this.controller.currentJob!.status)) {
            type = 'warning'
        } else if (errorStatuses.includes(this.controller.currentJob!.status)) {
            type = 'error'
        }

        let color, bg
        if (type === 'error') {
            color = '#dc3545'
            bg = '#f8d7da'
        } else if (type === 'warning') {
            color = '#856404'
            bg = '#fff3cd'
        } else {
            color = '#555'
            bg = '#f8f9fa'
        }

        return html`
            <div
                style="
                margin: 24px 0 16px 0;
                padding: 16px 20px;
                border-radius: 6px;
                background: ${bg};
                color: ${color};
                border: 1px solid ${color}22;
            "
            >
                ${this.#getJobMessageText()}
            </div>
        `
    }

    #getJobMessageText() {
        return this.controller.currentJob?.message.replace(
            /\b(The job|the job|job|Job)\b/g,
            match => {
                switch (match) {
                    case 'The job':
                        return 'Your request'
                    case 'the job':
                        return 'Your Request'
                    case 'job':
                        return 'request'
                    case 'Job':
                        return 'Request'
                }
                return match
            }
        )
    }

    #estimateJobSize() {
        const collection = this.collectionWithServices?.collection
        if (!collection) return

        const range = this.#getCollectionDateRange()
        let startDate: string | null
        let endDate: string | null
        let links = collection.granuleCount ?? 0

        if (this.selectedDateRange.startDate && this.selectedDateRange.endDate) {
            // Use the user selected date range if available
            startDate = this.selectedDateRange.startDate
            endDate = this.selectedDateRange.endDate
        } else {
            // fallback to the collection's full date range
            startDate = this.granuleMinDate ?? range.startDate
            endDate = this.granuleMaxDate ?? range.endDate
        }

        if (!startDate || !endDate) return

        const start = new Date(startDate)
        const end = new Date(endDate)
        const days =
            Math.floor((end.getTime() - start.getTime()) / (1000 * 60 * 60 * 24)) + 1

        if (range.startDate && range.endDate) {
            const availableDaysInCollection =
                Math.floor(
                    (new Date(range.endDate).getTime() -
                        new Date(range.startDate).getTime()) /
                        (1000 * 60 * 60 * 24)
                ) + 1
            const granulesPerDay = links / availableDaysInCollection

            links = Math.ceil(days * granulesPerDay)
        }

        return { days, links }
    }

    #refineParameters() {
        this.refineParameters = true
    }

    #backToSubsetOptions() {
        this.refineParameters = true
        // Scroll to the top of the component
        setTimeout(() => {
            const container = this.renderRoot.querySelector('.container')
            container?.scrollIntoView({ behavior: 'smooth', block: 'start' })
        }, 100)
    }

    #viewRunningJob() {
        this.refineParameters = false
        // Scroll to job status section
        setTimeout(() => {
            const el = this.renderRoot.querySelector('#job-status-section')
            el?.scrollIntoView({ behavior: 'smooth' })
        }, 100)
    }

    #handleDownloadSelect(event: TerraSelectEvent) {
        const item = event.detail.item
        const value = item.value || item.getTextLabel()

        if (value === 'file-list') {
            this.#downloadLinksAsTxt(event)
        } else if (value === 'python-script') {
            this.#downloadPythonScript(event)
        } else if (value === 'earthdata-download') {
            this.#downloadEarthdataDownload(event)
        }
    }

    #downloadLinksAsTxt(event: Event) {
        event.stopPropagation()
        if (!this.controller.currentJob?.links) {
            return
        }

        const dataLinks = this.#getDataLinks()

        if (dataLinks.length === 0) {
            return
        }

        const content = dataLinks.map(link => link.href).join('\n')
        const blob = new Blob([content], { type: 'text/plain' })
        const url = URL.createObjectURL(blob)

        // Create a temporary link element and trigger download
        const a = document.createElement('a')
        a.href = url
        a.download = `subset_links_${this.controller.currentJob!.jobID}.txt`
        document.body.appendChild(a)
        a.click()

        document.body.removeChild(a)
        URL.revokeObjectURL(url)
    }

    async #downloadPythonScript(event: Event) {
        event.stopPropagation()
        if (!this.controller.currentJob?.links) {
            return
        }

        const response = await fetch(
            getBasePath('assets/data-subsetter/download_subset_files.py.txt')
        )

        if (!response.ok) {
            alert(
                'Sorry, there was a problem generating the Python script. We are investigating the issue.\nYou could try using the Jupyter Notebook in the meantime'
            )
        }

        const content = (await response.text())
            .replace(/{{jobId}}/gi, this.controller.currentJob!.jobID)
            .replace(
                /{{HARMONY_ENV}}/gi,
                `Environment.${this.environment?.toUpperCase()}`
            )
            .replace(
                /{{EARTHACCESS_ENV}}/gi,
                `earthaccess.${this.environment?.toUpperCase()}`
            )

        const blob = new Blob([content], { type: 'text/plain' })
        const url = URL.createObjectURL(blob)

        // Create a temporary link element and trigger download
        const a = document.createElement('a')
        a.href = url
        a.download = `download_subset_files_${this.controller.currentJob!.jobID}.py`
        document.body.appendChild(a)
        a.click()

        document.body.removeChild(a)
        URL.revokeObjectURL(url)
    }

    async #downloadEarthdataDownload(event: Event) {
        event.stopPropagation()
        if (!this.controller.currentJob?.links) {
            return
        }

        alert('Sorry, Earthdata Download is not currently supported')
    }

    #handleJupyterNotebookClick() {
        const notebook = getNotebook(this)

        console.log('sending data to JupyterLite')

        sendDataToJupyterNotebook('load-notebook', {
            filename: `subset_${this.controller.currentJob?.jobID}.ipynb`,
            notebook,
            bearerToken: this.bearerToken,
        })
    }

    renderHistoryPanel() {
        const existingHistoryPanel = document.querySelector(
            'terra-data-subsetter-history'
        )

        if (!existingHistoryPanel && this.bearerToken) {
            // let's add a history panel to the page
            const historyPanel = document.createElement(
                'terra-data-subsetter-history'
            )

            if (this.bearerToken) {
                historyPanel.setAttribute('bearer-token', this.bearerToken)
            }

            if (this.environment) {
                historyPanel.setAttribute('environment', this.environment)
            }

            document.body.appendChild(historyPanel)
        }
    }

    #renderAvailableTemporalRangeSection() {
        const { startDate, endDate } = this.#getCollectionDateRange()
        if (!startDate || !endDate) return nothing
        return html`
            <div class="section" style="margin-bottom: 16px;">
                <h2 class="section-title">Available Date Range</h2>
                <div style="color: #31708f; margin-top: 8px;">
                    <strong>${startDate}</strong> to <strong>${endDate}</strong>
                </div>
                <div style="font-size: 0.95em; color: #666;">
                    This collection does not support temporal subsetting.
                </div>
            </div>
        `
    }

    #renderAvailableSpatialRangeSection() {
        const boundingRects =
            this.collectionWithServices?.collection?.SpatialExtent
                ?.HorizontalSpatialDomain?.Geometry?.BoundingRectangles
        if (!boundingRects || !Array.isArray(boundingRects) || !boundingRects.length)
            return nothing
        return html`
            <div class="section" style="margin-bottom: 16px;">
                <h2 class="section-title">Available Spatial Area</h2>
                <div style="color: #31708f; margin-top: 8px;">
                    ${boundingRects.map(
                        (rect: any) =>
                            html`<div>
                                <strong>Bounding Box:</strong>
                                ${rect.WestBoundingCoordinate},
                                ${rect.SouthBoundingCoordinate},
                                ${rect.EastBoundingCoordinate},
                                ${rect.NorthBoundingCoordinate}
                            </div>`
                    )}
                </div>
                <div style="font-size: 0.95em; color: #666;">
                    This collection does not support spatial subsetting.
                </div>
            </div>
        `
    }

    #renderDataAccessModeSelection() {
        return html`
            <div class="mode-selection">
                <div class="mode-options">
                    <label
                        class="mode-option ${this.dataAccessMode === 'original'
                            ? 'selected'
                            : ''}"
                    >
                        <input
                            type="radio"
                            name="data-access-mode"
                            value="original"
                            .checked=${this.dataAccessMode === 'original'}
                            @change=${() => (this.dataAccessMode = 'original')}
                        />
                        <div class="mode-content">
                            <div class="mode-title">Get Original Files</div>
                            <div class="mode-description">
                                Filter file links directly from the archive.
                            </div>
                        </div>
                    </label>

                    <label
                        class="mode-option ${this.dataAccessMode === 'subset'
                            ? 'selected'
                            : ''}"
                    >
                        <input
                            type="radio"
                            name="data-access-mode"
                            value="subset"
                            .checked=${this.dataAccessMode === 'subset'}
                            @change=${() => (this.dataAccessMode = 'subset')}
                        />
                        <div class="mode-content">
                            <div class="mode-title">Subset Data</div>
                            <div class="mode-description">
                                Subset the data to your specific needs.
                            </div>
                        </div>
                    </label>
                </div>
            </div>
        `
    }

    #isGiovanniFormat(): boolean {
        return (
            this.selectedFormat === 'text/csv' || this.selectedFormat === 'image/tiff'
        )
    }

    #getGiovanniValidationError(): string | null {
        if (!this.#isGiovanniFormat()) {
            return null
        }

        if (this.selectedVariables.length === 0) {
            return 'Please select a variable to subset.'
        }

        if (this.selectedVariables.length > 1) {
            return 'The selected format only supports subsetting one variable at a time.'
        }

        return null
    }
}
