/* Lodestay — Stays. The one canvas in the product: the places that can be
   booked for the dates in the scope, beside a real map of where they are.

   Two levels of filter, and the rule they follow (AGENTS §5.3):
     · The SCOPE — dates and party size — sits above the figures and moves them.
       Change it and the count, the median and every price on the screen change,
       because they are computed from the scope.
     · The list filters — text, neighbourhood, kind, order — sit inside the list
       container below the figures and narrow the list only. The figures do not
       move, and the line above them says so.
   One reset each, and clearing one never clears the other.

   The map and the list are the same array: `rows`. A pin is a place in it, a
   card is a place in it, and the count in the heading is its length. */
(() => {
  const { Button, Input, Select, ToggleGroup, Badge, Empty, EmptyHeader, EmptyMedia, EmptyTitle, EmptyDescription, EmptyContent } = window.OriginDesignSystem_7c998b;

  const KIND_FILTER = [{ value: "all", label: "Any kind of place" }].concat(PLACE_KINDS.map((k) => ({ value: k.value, label: k.label })));
  const HOOD_FILTER = [{ value: "all", label: "Anywhere in Lisbon" }].concat(NEIGHBOURHOODS.map((n) => ({ value: n.value, label: n.label })));
  const GUEST_OPTIONS = [1, 2, 3, 4, 5, 6].map((n) => ({ value: String(n), label: formatGuests(n) }));

  function SearchScreen({ data, scope, onScopeChange, filters, onFilterChange, saved, onSave, onNavigate, onRun }) {
    const [selected, setSelected] = React.useState(null);
    const [hovered, setHovered] = React.useState(null);
    const [pane, setPane] = React.useState("list");

    const bookable = bookableFor(data.listings);
    const rows = searchResults(data.listings, scope, filters);
    const stats = resultStats(rows, scope);
    const nights = nightsBetween(scope.checkIn, scope.checkOut);
    const filtered = rows.length !== bookable.length;
    const dateItems = SEARCH_DATE_OPTIONS.map((o) => ({ value: o.value, label: formatStayRange(o.checkIn, o.checkOut) + " · " + formatNights(nightsBetween(o.checkIn, o.checkOut)) }));

    const openPlace = (listing) => onNavigate("/stays/" + listing.id);
    const points = rows.map((listing) => ({
      id: listing.id,
      lat: listing.lat,
      lng: listing.lng,
      label: formatPrice(listing.nightlyCents),
      title: listing.name + " · " + formatPrice(listing.nightlyCents) + " a night",
      variant: LISTING_FLAGS.isHeld(listing) ? "held" : "price",
      marked: saved.indexOf(listing.id) > -1,
    }));
    const active = hovered || selected;
    const selectedListing = selected ? listingById(rows, selected) : null;

    return (
      <div className={"ls-page ls-page--flush" + (pane === "list" ? " ls-listonly" : " ls-maponly")}>
        {/* Scope. Above the figures, because it moves them. */}
        <div className="ls-scope">
          <div className="ls-scope__group">
            <Icon name="map-pin" size={15} />
            <span style={{ fontSize: "var(--text-sm)", fontWeight: "var(--font-weight-medium)" }}>{LODESTAY_PRODUCT.city}</span>
          </div>
          <span className="ls-scope__rule" aria-hidden="true" />
          <div className="ls-scope__group">
            <Select
              size="sm" items={dateItems} value={scope.dates} aria-label="Dates"
              onValueChange={(value) => { const option = SEARCH_DATE_OPTIONS.find((o) => o.value === value); onScopeChange({ dates: value, checkIn: option.checkIn, checkOut: option.checkOut, guests: scope.guests }); setSelected(null); }}
            />
            <Select
              size="sm" items={GUEST_OPTIONS} value={String(scope.guests)} aria-label="Guests"
              onValueChange={(value) => onScopeChange(Object.assign({}, scope, { guests: parseInt(value, 10) }))}
            />
            {scope.dates !== SEARCH_SCOPE.dates || scope.guests !== SEARCH_SCOPE.guests ? (
              <Button variant="ghost" size="sm" onClick={() => { onScopeChange(SEARCH_SCOPE); setSelected(null); }}>Reset dates</Button>
            ) : null}
          </div>
          <div className="ls-filters">
            <span className="ls-mapswitch">
              <ToggleGroup
                variant="outline" size="sm" toggleMultiple={false} value={[pane]}
                items={[{ value: "list", text: "List", label: "Show the list" }, { value: "map", text: "Map", label: "Show the map" }]}
                onValueChange={(value) => setPane(value[0] || pane)}
              />
            </span>
          </div>
        </div>

        <div className="ls-split">
          <div className="ls-listpane">
            {/* The figures. Every one of them counts or sums `rows`. */}
            <div className="ls-stack ls-stack--tight">
              <div className="ls-resultline">
                <span className="ls-resultline__lead">{rows.length} {rows.length === 1 ? "place" : "places"} for {formatStayRange(scope.checkIn, scope.checkOut)}</span>
                {stats ? <span className="ls-muted" style={{ fontSize: "var(--text-sm)" }}>Median {formatPrice(stats.medianNightly)} a night · cheapest {formatNights(nights)} {formatPrice(stats.cheapestTotal)} all in</span> : null}
              </div>
              <span className="ls-note">
                {formatGuests(scope.guests)}, {formatNights(nights)}, everything the hosts will take for these dates.
                {filtered ? " The figures cover all " + bookable.length + " places in Lisbon for these dates; the filters below narrow the list only." : ""}
              </span>
            </div>

            {/* List filters. Inside the list container, below the figures, text
                filter leftmost — the same order on every list screen. */}
            <div className="ls-row">
              <span className="ls-filters__text">
                <Input
                  size="sm" placeholder="Alfama, terrace, quiet…" aria-label="Filter these places"
                  value={filters.text} startAddon={<Icon name="search" size={14} />}
                  onChange={(e) => onFilterChange(Object.assign({}, filters, { text: e.target.value }))}
                />
              </span>
              <span className="ls-filter"><Select size="sm" items={HOOD_FILTER} value={filters.neighbourhood} aria-label="Neighbourhood" onValueChange={(v) => onFilterChange(Object.assign({}, filters, { neighbourhood: v }))} /></span>
              <span className="ls-filter"><Select size="sm" items={KIND_FILTER} value={filters.kind} aria-label="Kind of place" onValueChange={(v) => onFilterChange(Object.assign({}, filters, { kind: v }))} /></span>
              <span className="ls-filter ls-filter--wide"><Select size="sm" items={SORTS} value={filters.sort} aria-label="Order" onValueChange={(v) => onFilterChange(Object.assign({}, filters, { sort: v }))} /></span>
              {filtered ? <Button variant="ghost" size="sm" onClick={() => onFilterChange({ text: "", neighbourhood: "all", kind: "all", sort: "recommended" })}>Clear filters</Button> : null}
            </div>

            {rows.length === 0 ? (
              <Empty>
                <EmptyHeader>
                  <EmptyMedia variant="icon"><Icon name="search-x" size={18} /></EmptyMedia>
                  <EmptyTitle>Nothing matches those filters</EmptyTitle>
                  <EmptyDescription>{bookable.length} places in Lisbon are open for {formatStayRange(scope.checkIn, scope.checkOut)}. The filters are hiding all of them.</EmptyDescription>
                </EmptyHeader>
                <EmptyContent>
                  <Button onClick={() => onFilterChange({ text: "", neighbourhood: "all", kind: "all", sort: "recommended" })}>Clear filters</Button>
                </EmptyContent>
              </Empty>
            ) : (
              <div className="ls-cards">
                {rows.map((listing) => (
                  <PlaceCard
                    key={listing.id}
                    listing={listing}
                    scope={scope}
                    saved={saved.indexOf(listing.id) > -1}
                    selected={active === listing.id}
                    onOpen={openPlace}
                    onSave={onSave}
                    onHover={setHovered}
                    transitions={listingTransitions(listing, Object.assign({ nights: nights }, scope), data.now)}
                    onRun={(t) => onRun(listing, t)}
                  />
                ))}
              </div>
            )}
          </div>

          <div className="ls-mappane">
            <MapPane
              points={points}
              center={LODESTAY_PRODUCT.center}
              zoom={LODESTAY_PRODUCT.zoom}
              selectedId={active}
              onSelect={(id) => setSelected(id === selected ? null : id)}
            />
            <div className="ls-maplegend">
              <span className="ls-row ls-row--tight"><span className="ls-pin" aria-hidden="true">€</span>Nightly rate</span>
              <span className="ls-row ls-row--tight"><span className="ls-pin ls-pin--saved" aria-hidden="true">€</span>Saved</span>
              <span className="ls-row ls-row--tight"><span className="ls-pin ls-pin--held" aria-hidden="true">€</span>On hold</span>
            </div>
            {selectedListing ? (
              <MapSelectionCard listing={selectedListing} scope={scope} onOpen={openPlace} onClose={() => setSelected(null)} />
            ) : null}
          </div>
        </div>
      </div>
    );
  }

  Object.assign(window, { SearchScreen });
})();
