import {
  Component,
  HostListener,
  computed,
  input,
  output,
  signal
} from '@angular/core';
import { ThemeNodeDirective } from '../../../domains/theme';

/**
 * Mobile bottom-sheet container.
 *
 * Renders a backdrop + a panel anchored to the bottom of the viewport that slides up from below.
 * Intended for use on phone-sized viewports where context menus, action sheets, and confirmation
 * dialogs are better presented as bottom sheets than as floating popovers or centered modals.
 *
 * The component is layout-only: callers project their content via `<ng-content>` and listen for
 * the `dismissed` output to close themselves. Drag-to-dismiss is supported via touch gestures.
 *
 * Desktop callers should not render this component; use the original popover/modal layout instead.
 *
 * @example
 * ```html
 * @if (isMobile()) {
 *   <app-bottom-sheet (dismissed)="close()">
 *     <my-menu-items />
 *   </app-bottom-sheet>
 * }
 * ```
 */
@Component({
  selector: 'app-bottom-sheet',
  standalone: true,
  imports: [ThemeNodeDirective],
  templateUrl: './bottom-sheet.component.html',
  styleUrl: './bottom-sheet.component.scss'
})
export class BottomSheetComponent {
  /** Optional title rendered at the top of the sheet. Omit for an unlabeled action sheet. */
  readonly title = input<string | null>(null);

  /** Optional ARIA label when no visible title is provided. */
  readonly ariaLabel = input<string>('Menu');

  /** Emits when the user dismisses the sheet (backdrop tap, swipe-down, or Escape). */
  readonly dismissed = output<undefined>();

  /** Pixels the sheet is currently dragged downward. Drives the translate transform. */
  protected readonly dragOffset = signal(0);

  /** Visible transform offset in CSS pixels (only positive values move the sheet down). */
  protected readonly translateY = computed(() => Math.max(0, this.dragOffset()));

  private touchStartY: number | null = null;

  @HostListener('document:keydown.escape')
  protected onEscape(): void {
    this.dismissed.emit(undefined);
  }

  protected onBackdropClick(): void {
    this.dismissed.emit(undefined);
  }

  protected onHandleTouchStart(event: TouchEvent): void {
    const touch = event.touches[0];

    if (!touch) {
      return;
    }

    this.touchStartY = touch.clientY;
  }

  protected onHandleTouchMove(event: TouchEvent): void {
    if (this.touchStartY === null) {
      return;
    }

    const touch = event.touches[0];

    if (!touch) {
      return;
    }

    const delta = touch.clientY - this.touchStartY;

    // Only allow dragging downward; ignore upward drags.
    this.dragOffset.set(Math.max(0, delta));
  }

  protected onHandleTouchEnd(): void {
    // Dismiss if the user dragged the sheet down by more than 80px; otherwise snap back.
    if (this.dragOffset() > 80) {
      this.dismissed.emit(undefined);
    }

    this.touchStartY = null;
    this.dragOffset.set(0);
  }
}
