import { Controller } from "@hotwired/stimulus"
import { debounce } from "solidus_admin/utils"

export default class extends Controller {
  static targets = [
    "checkbox",
    "headerCheckbox",
    "batchToolbar",
    "scopesToolbar",
    "searchToolbar",
    "searchField",
    "searchForm",
    "filterToolbar",
    "defaultHeader",
    "batchHeader",
    "tableBody",
    "selectedRowsCount",
  ]

  static classes = ["selectedRow"]
  static values = {
    mode: { type: String, default: "scopes" },
    sortable: { type: Boolean, default: false },
  }

  initialize() {
    // Debounced search function.
    // This method submits the search form after a delay of 200ms.
    // If the function is called again within this delay, the previous call is cleared,
    // effectively ensuring the form is only submitted 200ms after the last call (e.g., user stops typing).
    this.search = debounce(this.search.bind(this), 200)
  }

  // Determine if sortable should be enabled
  modeValueChanged() {
    const shouldSetSortable = this.sortableValue && this.modeValue !== "batch" && this.modeValue !== "search"

    if (shouldSetSortable) {
      this.tableBodyTarget.setAttribute("data-controller", "sortable")
    } else {
      this.tableBodyTarget.removeAttribute("data-controller")
    }
  }

  showSearch({ detail: { avoidFocus } }) {
    this.modeValue = "search"
    this.render()

    if (!avoidFocus) this.searchFieldTarget.focus()
  }

  search() {
    this.searchFormTarget.requestSubmit()
  }

  clearSearch() {
    this.searchFieldTarget.value = ""
    this.search()
  }

  resetSearchAndFilters() {
    if (this.hasFilterToolbarTarget) {
      this.filterToolbarTarget.querySelectorAll("fieldset").forEach((fieldset) => (fieldset.disabled = true))
    }

    this.searchFieldTarget.disabled = true
    this.searchFormTarget.submit()
  }

  selectRow(event) {
    if (this.checkboxTargets.some((checkbox) => checkbox.checked)) {
      this.modeValue = "batch"
    } else if (this.hasSearchFieldTarget && this.searchFieldTarget.value !== "") {
      this.modeValue = "search"
    } else if (this.hasScopesToolbarTarget) {
      this.modeValue = "scopes"
    } else {
      this.modeValue = "search"
    }

    this.render()
  }

  selectAllRows(event) {
    if (event.target.checked) {
      this.modeValue = "batch"
    } else if (this.hasSearchFieldTarget && this.searchFieldTarget.value !== "") {
      this.modeValue = "search"
    } else if (this.hasScopesToolbarTarget) {
      this.modeValue = "scopes"
    } else {
      this.modeValue = "search"
    }

    this.checkboxTargets.forEach((checkbox) => (checkbox.checked = event.target.checked))

    this.render()
  }

  rowClicked(event) {
    // If the user clicked on a link, button, input or summary, skip the row url visit
    if (event.target.closest("td").contains(event.target.closest("a,select,textarea,button,input,summary"))) return

    if (this.modeValue === "batch") {
      this.toggleCheckbox(event.currentTarget)
    } else {
      const url = new URL(event.params.url, "http://dummy.com")
      const params = new URLSearchParams(url.search)
      const frameId = params.get("_turbo_frame")
      const frame = frameId ? { frame: frameId } : {}
      // remove the custom _turbo_frame param from url search:
      params.delete("_turbo_frame")
      url.search = params.toString()

      window.Turbo.visit(url.pathname + url.search, frame)
    }
  }

  toggleCheckbox(row) {
    const checkbox = this.checkboxTargets.find((selection) => row.contains(selection))

    if (checkbox) {
      checkbox.checked = !checkbox.checked
      this.selectRow()
    }
  }

  selectedRows() {
    return this.checkboxTargets.filter((checkbox) => checkbox.checked)
  }

  confirmAction(event) {
    const message = event.params.message
      .replace("${count}", this.selectedRows().length)
      .replace(
        "${resource}",
        this.selectedRows().length > 1 ? event.params.resourcePlural : event.params.resourceSingular
      )

    if (!confirm(message)) {
      event.preventDefault()
    }
  }

  render() {
    const selectedRows = this.selectedRows()

    if (this.hasSearchFieldTarget) {
      this.searchToolbarTarget.toggleAttribute("hidden", this.modeValue !== "search")
    }

    if (this.hasFilterToolbarTarget) {
      this.filterToolbarTarget.toggleAttribute("hidden", this.modeValue !== "search")
    }

    this.batchToolbarTarget.toggleAttribute("hidden", this.modeValue !== "batch")
    this.batchHeaderTarget.toggleAttribute("hidden", this.modeValue !== "batch")
    this.defaultHeaderTarget.toggleAttribute("hidden", this.modeValue === "batch")

    if (this.hasScopesToolbarTarget) {
      this.scopesToolbarTarget.toggleAttribute("hidden", this.modeValue !== "scopes")
    }

    // Update the rows background color
    this.checkboxTargets.filter((checkbox) =>
      checkbox.closest("tr").classList.toggle(this.selectedRowClass, checkbox.checked)
    )

    // Update the selected rows count
    this.selectedRowsCountTarget.textContent = `${selectedRows.length}`

    // Update the header checkboxes
    this.headerCheckboxTargets.forEach((checkbox) => {
      checkbox.indeterminate = false
      checkbox.checked = false

      if (this.checkboxTargets.length > 0 && selectedRows.length === this.checkboxTargets.length)
        checkbox.checked = true
      else if (selectedRows.length > 0) checkbox.indeterminate = true
    })
  }
}
