@use "sass:map";
@use "config" as *;
@use "functions" as *;
@use "layout/breakpoints" as *;
@use "mixins/border-radius" as *;
@use "mixins/box-shadow" as *;
@use "mixins/dialog-shared" as *;
@use "mixins/transition" as *;
@use "mixins/tokens" as *;

// Native <dialog> component
// Uses the browser's native dialog element with showModal()/show()/close() APIs
// Leverages native [open] attribute and ::backdrop pseudo-element

// stylelint-disable custom-property-no-missing-var-function
$dialog-tokens: () !default;

// scss-docs-start dialog-tokens
// stylelint-disable-next-line scss/dollar-variable-default
$dialog-tokens: defaults(
  (
    --dialog-padding: 1rem,
    --dialog-width: 500px,
    --dialog-margin: 1.75rem,
    --dialog-color: var(--fg-body),
    --dialog-bg: var(--bg-body),
    --dialog-border-color: var(--border-color-translucent),
    --dialog-border-width: var(--border-width),
    --dialog-border-radius: var(--border-radius-lg),
    --dialog-box-shadow: var(--box-shadow-lg),
    --dialog-transition-duration: .3s,
    --dialog-transition-timing: cubic-bezier(.22, 1, .36, 1),
    --dialog-backdrop-bg: rgb(0 0 0 / 50%),
    --dialog-backdrop-blur: 8px,
    --dialog-header-padding: 1rem,
    --dialog-header-border-color: var(--border-color),
    --dialog-header-border-width: var(--border-width),
    --dialog-footer-padding: 1rem,
    --dialog-footer-border-color: var(--border-color),
    --dialog-footer-border-width: var(--border-width),
    --dialog-footer-gap: .5rem,
  ),
  $dialog-tokens
);
// scss-docs-end dialog-tokens
// stylelint-enable custom-property-no-missing-var-function

// scss-docs-start dialog-sizes
$dialog-sizes: () !default;
// stylelint-disable-next-line scss/dollar-variable-default
$dialog-sizes: defaults(
  (
    sm: 280px,
    lg: 800px,
    xl: 1140px,
  ),
  $dialog-sizes
);
// scss-docs-end dialog-sizes

@layer components {
  // Prevent body scroll when dialog is open
  .dialog-open {
    overflow: hidden;
    scrollbar-gutter: stable;
  }

  .dialog {
    @include tokens($dialog-tokens);

    // Override UA display:none so visibility controls the hidden state,
    // enabling reliable cross-browser exit animations after close().
    display: flex;
    flex-direction: column;
    width: var(--dialog-width);
    max-width: 100%;
    max-height: calc(100% - var(--dialog-margin) * 2);
    padding: 0;
    margin: auto;
    overflow: visible;
    color: var(--dialog-color);
    visibility: hidden;
    background-color: var(--dialog-bg);
    background-clip: padding-box;
    border: var(--dialog-border-width) solid var(--dialog-border-color);
    @include border-radius(var(--dialog-border-radius));
    @include box-shadow(var(--dialog-box-shadow));

    // Animated variant (default) — transitions, opacity fade, slide transforms.
    // Adding .dialog-instant skips all animations (instant show/hide).
    &:not(.dialog-instant) {
      // Exit state: faded out
      opacity: 0;

      // Exit transition: opacity and transform animate out, then visibility
      // flips hidden after the animation completes (via the delay).
      @include transition(
        opacity var(--dialog-transition-duration) var(--dialog-transition-timing),
        transform var(--dialog-transition-duration) var(--dialog-transition-timing),
        visibility 0s var(--dialog-transition-duration)
      );

      // Slide-down variant: enters from above, exits below.
      &.dialog-slide-down {
        transform: translateY(3rem);
      }

      // Slide-up variant: enters from below, exits above.
      &.dialog-slide-up {
        transform: translateY(-3rem);
      }

      // Open state: visible and faded in.
      // Entry transition: visibility flips visible immediately (0s, no delay),
      // then opacity and transform animate in.
      &[open] {
        overflow: visible;
        visibility: visible;
        opacity: 1;
        @include transition(
          opacity var(--dialog-transition-duration) var(--dialog-transition-timing),
          transform var(--dialog-transition-duration) var(--dialog-transition-timing),
          visibility 0s
        );
        transform: none;
      }

      // Static backdrop "bounce" animation (modal dialogs only)
      &.dialog-static {
        transform: scale(1.02);
      }

      // Native backdrop styling with transitions
      &::backdrop {
        background-color: var(--dialog-backdrop-bg);
        backdrop-filter: blur(var(--dialog-backdrop-blur));
        @include backdrop-transitions(var(--dialog-transition-duration), var(--dialog-transition-timing));
      }
    }

    // Instant variant — no transitions, just snap visibility
    &.dialog-instant {
      &::backdrop {
        background-color: var(--dialog-backdrop-bg);
        backdrop-filter: blur(var(--dialog-backdrop-blur));
      }
    }

    // Open state base (always applies, regardless of animation mode)
    &[open] {
      overflow: visible;
      visibility: visible;
      opacity: 1;
      transform: none;
    }

    // Non-modal dialog positioning
    // show() doesn't use the top layer, so we need explicit positioning and z-index
    &.dialog-nonmodal {
      position: fixed;
      inset-block-start: 50%;
      inset-inline-start: 50%;
      z-index: $zindex-dialog;
      margin-inline: 0;
      transform: translate(-50%, -50%);
    }

    // Overflow dialog - scrollable viewport container with dialog box inside
    &.dialog-overflow {
      // Make dialog element the full-viewport scrollable container
      position: fixed;
      inset: 0;
      width: 100%;
      max-width: 100%;
      height: 100%;
      max-height: 100%;
      padding: var(--dialog-margin);
      margin: 0;
      overflow-y: auto;
      overscroll-behavior: contain;
      background: transparent;
      border: 0;
      box-shadow: none;

      // The visual dialog box is a child wrapper
      > .dialog-box {
        max-width: var(--dialog-width);
        margin-block-end: var(--dialog-margin);
        margin-inline: auto;
        color: var(--dialog-color);
        background-color: var(--dialog-bg);
        background-clip: padding-box;
        border: var(--dialog-border-width) solid var(--dialog-border-color);
        @include border-radius(var(--dialog-border-radius));
        @include box-shadow(var(--dialog-box-shadow));
      }
    }

    // Scrollable dialog body (header/footer stay fixed)
    &.dialog-scrollable[open] {
      max-height: calc(100% - var(--dialog-margin) * 2);

      .dialog-body {
        overflow-y: auto;
      }
    }
  }

  // Entry animations via @starting-style.
  // Slide variants need this because the base transform is the EXIT position,
  // but entry must start from the opposite direction.
  // ::backdrop needs it since it only exists in the top layer.
  // Default dialog (fade only) does NOT need @starting-style — the base
  // opacity: 0 state serves as the entry-from state with visibility trick.
  @starting-style {
    // Slide-down: enters from above (negative Y), slides down into view
    .dialog:not(.dialog-instant).dialog-slide-down[open] {
      opacity: 0;
      transform: translateY(-3rem);
    }

    // Slide-up: enters from below (positive Y), slides up into view
    .dialog:not(.dialog-instant).dialog-slide-up[open] {
      opacity: 0;
      transform: translateY(3rem);
    }

    .dialog:not(.dialog-instant)::backdrop {
      background-color: transparent;
      backdrop-filter: blur(0);
    }
  }

  // Dialog sizes
  @each $size, $value in $dialog-sizes {
    .dialog-#{$size} { --dialog-width: #{$value}; }
  }

  // Fullscreen dialog
  .dialog-fullscreen {
    --dialog-width: 100vw;
    --dialog-margin: 0;
    --dialog-border-radius: 0;

    width: 100%;
    max-width: none;
    height: 100%;
    max-height: none;
  }

  // Responsive fullscreen dialogs
  @each $breakpoint in map.keys($breakpoints) {
    $prefix: breakpoint-prefix($breakpoint, $breakpoints);

    @if $prefix != "" {
      @include media-breakpoint-down($breakpoint) {
        .#{css-escape-ident($breakpoint)}-down\:dialog-fullscreen {
          --dialog-width: 100vw;
          --dialog-margin: 0;
          --dialog-border-radius: 0;

          width: 100%;
          max-width: none;
          height: 100%;
          max-height: none;
        }
      }
    }
  }

  // Dialog header
  .dialog-header {
    @include dialog-header(var(--dialog-header-padding));
    border-block-end: var(--dialog-header-border-width) solid var(--dialog-header-border-color);

    .btn-close {
      margin-inline-start: auto;
    }
  }

  // Dialog title
  .dialog-title {
    @include dialog-title();
    font-size: var(--font-size-md);
  }

  // Dialog body
  .dialog-body {
    position: relative;
    @include dialog-body(var(--dialog-padding));
  }

  // Dialog footer
  .dialog-footer {
    @include dialog-footer(var(--dialog-footer-padding), var(--dialog-footer-gap), var(--dialog-footer-border-width), var(--dialog-footer-border-color));
  }
}
