////
/// @group data-list
/// A highly flexible, responsive list layout designed for displaying self-explanatory 
/// or loosely structured data without relying on rigid table markup. On large screens, 
/// it perfectly aligns item content into distinct columns using CSS Subgrid, while 
/// seamlessly adapting to a clean, stacked flex view on smaller devices. Because it 
/// is fundamentally a list and not a data table, content within should be comprehensible 
/// when stacked without relying on explicit column headers. It handles complex structures 
/// through nested groupings, supports optional visual headers, and provides interactive 
/// states for clickable rows using simple presets or custom grids.
////

/// Benchmarks:
/// - size: 3kb (gzip 0.7 KB) 

@use "sass:map";
@use "sass:math";
@use "sass:meta";

@use "../selector";
@use "../utils";
@use "../color";
@use "../breakpoint";
@use "../element";

// Used for function fallback
$-fallbacks: (
  "stacked-breakpoint" : (
    "function" : meta.get-function("get", false, "breakpoint"),
    "property" : "default"
  )
);

/// Module Settings
/// @type Map
/// @prop {String} grid-template-columns [1fr] The default master grid columns.
/// @prop {String} grid-template-columns-stacked [100%] The stacked grid columns (default is single column stack).
/// @prop {Dimension} row-gap [0] The space between list items (rows). Forced to 0 if overlap-borders is true.
/// @prop {Dimension} column-gap [1rem] The space between columns.
/// @prop {Dimension} column-gap-stacked [0.5rem] The space between stacked elements when stacked within an item.
/// @prop {Dimension} group-gap-stacked [0.25rem] The space between stacked elements inside a nested column when stacked.
/// @prop {Dimension} padding [1rem clamp(0.65rem, 3vw, 1.5rem),] The padding inside list items.
/// @prop {Boolean} overlap-borders [true] If true, applies a negative top margin to items to prevent double-thick borders between touching rows, and forces row-gap to 0.
/// @prop {Dimension} border-width [1px] The border width for the list items.
/// @prop {String} border-color ["rule-light"] The border color key for the list items.
/// @prop {Dimension} border-radius [null] The border radius for the list items.
/// @prop {CssValue} box-shadow [null] The box shadow for the list items.
/// @prop {Color} background-color [transparent] The default background color for items.
/// @prop {Color} background-color-even [null] The background color for even-numbered items (for striping).
/// @prop {Color} background-color-hover [null] The background color for items on hover.
/// @prop {Color} clickable-background-color-hover [#e8e8e8] The background color for clickable items on hover.
/// @prop {String} clickable-border-color-hover ["control-border-hover"] The border color for interactive (clickable) items on hover/focus.
/// @prop {String} stacked-breakpoint [true] The breakpoint below which groups stack. Defaults to the global default breakpoint via function fallback.
/// @prop {Number} span-count [4] The number of span modifiers to create, increase if needed, (ie. data-list__column--span-2, --span-3, ...)
/// @prop {CssValue} header-font-weight [bold] The font weight for the header row text.
/// @prop {Dimension} header-border-bottom-width [2px] The width for the bottom border of the header row.
/// @prop {String} header-border-bottom-color ["rule"] The color key for the bottom border of the header row.

$config: (
  "grid-template-columns": 1fr,
  "grid-template-columns-stacked": 100%,
  "row-gap": 0,
  "column-gap": 1rem,
  "column-gap-stacked": 0.5rem,
  "group-gap-stacked": 0.25rem,
  "padding": 1rem clamp(0.65rem, 3vw, 1.5rem),
  "overlap-borders": true,
  "border-width": 1px,
  "border-color": "rule-light",
  "border-radius": null,
  "box-shadow": null,
  "background-color": transparent,
  "background-color-even": #f9f9f9,
  "background-color-hover": #f0f0f0,
  "clickable-background-color-hover": #e8e8e8, // Slightly darker for interactive indication
  "clickable-border-color-hover": "control-border-hover",
  "stacked-breakpoint": true,
  "span-count" : 6,
  "header-font-weight": bold,
  "header-border-bottom-width": 2px,
  "header-border-bottom-color": "rule",
) !default;

/// Change modules $config
/// @param {Map} $changes Map of changes
@mixin set($changes) {
  $config: map.merge($config, $changes) !global;
}

/// Get a config option
/// @param {Map} $name Name of property
@function get($name) {
  $value: utils.require-map-get($config, $name, "data-list [config]");
  @return utils.function-fallback($name, $value, $-fallbacks);
}

/// Prints component styles
/// @demo data-list
@mixin styles {
  @include utils.file-header('component', 'data-list');

  $prefix: selector.class("data-list");
  $stacked-bp: get("stacked-breakpoint");
  $overlap: get("overlap-borders");
  $border-width: get("border-width");
  
  #{ $prefix } {
    display: grid;
    
    @if $overlap {
      gap: 0; // Forced to 0 when borders overlap to prevent disjointed negative margins
    } @else {
      gap: var(--ulu-data-list-row-gap, get("row-gap"));
    }
    
    // Allows inline override via custom property, falls back to config default
    grid-template-columns: var(--ulu-data-list-columns, get("grid-template-columns"));
    list-style: none;
    margin: 0;
    padding: 0;

    @include breakpoint.max($stacked-bp) {
      // Switch to stacked grid template (defaults to 100% stack, but can be overridden for persistent cols)
      grid-template-columns: var(--ulu-data-list-columns-stacked, get("grid-template-columns-stacked"));
    }
  }

  // Row Item (Passes the grid down)
  #{ $prefix }__item {
    display: grid;
    grid-template-columns: subgrid;
    grid-column: 1 / -1;
    gap: var(--ulu-data-list-column-gap, get("column-gap"));
    padding: get("padding");
    background-color: color.get(get("background-color"));
    border: element.optional-border($border-width, get("border-color"));
    border-radius: get("border-radius");
    box-shadow: get("box-shadow");

    @if $overlap {
      margin-top: calc(-1 * #{ $border-width });
      &:first-child {
        margin-top: 0;
      }
    }

    

    @include breakpoint.max($stacked-bp) {
      // We keep display: grid/subgrid here to respect the stacked parent grid
      gap: var(--ulu-data-list-column-gap-stacked, get("column-gap-stacked")); 
    }

    @if (get("background-color-hover")) {
      &:hover {
        background-color: color.get(get("background-color-hover"));
      }
    }
  }

  // Interactive z-index management for borders/shadows
  #{ $prefix }__item:hover,
  #{ $prefix }__item:focus-within,
  #{ $prefix }__header #{ $prefix }__item {
    position: relative;
    z-index: 2;
  }

  // Columns (The cells / wrappers)
  #{ $prefix }__column {
    display: flex;
    align-items: center;
    gap: var(--ulu-data-list-column-gap, get("column-gap"));
    // Defensive Layout: Prevents flexbox/grid from refusing to shrink below intrinsic content size.
    // Without this, a long unbroken word or URL could force the column to expand, blowing out the grid.
    // It allows text-overflow: ellipsis to work safely within a column without breaking the layout.
    min-width: 0; 
  }

  // Automatic Groups (Subgrid on desktop, stack on smaller screens)
  #{ $prefix }__column:has(> #{ $prefix }__column) {
    display: grid;
    grid-template-columns: subgrid;
    // Default span is 1, use modifiers below for larger spans
    
    @include breakpoint.max($stacked-bp) {
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: stretch;
      gap: var(--ulu-data-list-group-gap-stacked, get("group-gap-stacked")); // Tighter vertical gap when stacked
    }
  }

  // Header Row (Optional)
  #{ $prefix }__header {
    display: contents; // Removes wrapper so children participate in grid

    // Hide headers when stacked since columns stack
    @include breakpoint.max($stacked-bp) {
      display: none;
    }

    #{ $prefix }__item {
      font-weight: get("header-font-weight");
      background-color: transparent;
      border-bottom: element.optional-border(get("header-border-bottom-width"), get("header-border-bottom-color"));
      border-radius: 0; // Prevent rounding on headers
      &:hover {
        background-color: transparent; // No hover effect on headers
      }
    }
  }

  // Modifiers

  // Structural Edge Modifiers (Decorating the default 1fr track)
  #{ $prefix }--prefixed {
    grid-template-columns: var(--ulu-data-list-columns, auto 1fr);
    @include breakpoint.max($stacked-bp) {
      grid-template-columns: var(--ulu-data-list-columns-stacked, auto 1fr);
    }
  }
  #{ $prefix }--suffixed {
    grid-template-columns: var(--ulu-data-list-columns, 1fr auto);
    @include breakpoint.max($stacked-bp) {
      grid-template-columns: var(--ulu-data-list-columns-stacked, 1fr auto);
    }
  }
  #{ $prefix }--prefixed#{ $prefix }--suffixed {
    grid-template-columns: var(--ulu-data-list-columns, auto 1fr auto);
    @include breakpoint.max($stacked-bp) {
      grid-template-columns: var(--ulu-data-list-columns-stacked, auto 1fr auto);
    }
  }

  // Striped Rows
  #{ $prefix }--striped {
    @if (get("background-color-even")) {
      #{ $prefix }__item:nth-child(even) {
        background-color: color.get(get("background-color-even"));
      }
    }
  }

  // Interactive Rows (Proxy Click Support)
  // Applied to parent to indicate all rows are interactive
  #{ $prefix }--clickable {
    #{ $prefix }__item {
      cursor: pointer;
      &:hover,
      &:focus-within {
        background-color: color.get(get("clickable-background-color-hover"));
        border-color: color.get(get("clickable-border-color-hover"));
      }
    }
  }

  // Spanning (Required when a subgrid contains multiple child columns)
  @for $i from 2 through get("span-count") {
    #{ $prefix }__column--span-#{$i} {
      grid-column: span #{$i};
      
      // Reset span when stacked so it fits the simplified grid
      @include breakpoint.max($stacked-bp) {
        grid-column: auto;
      }
    }
  }
}