import { DOCUMENT, NgComponentOutlet, isPlatformBrowser } from '@angular/common';
import {
  ChangeDetectionStrategy,
  Component,
  Injector,
  PLATFORM_ID,
  computed,
  effect,
  inject,
  viewChild
} from '@angular/core';

import {
  MODAL_DATA,
  ModalRef,
  ModalService
} from '../../../core/services/modal.service';
import { ModalShellComponent } from '../modal-shell/modal-shell.component';

@Component({
  selector: 'app-modal-host',
  imports: [NgComponentOutlet, ModalShellComponent],
  templateUrl: './modal-host.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class ModalHostComponent {
  private readonly modalService = inject(ModalService);
  private readonly injector = inject(Injector);
  private readonly document = inject(DOCUMENT);
  private readonly platformId = inject(PLATFORM_ID);
  private readonly modalShell = viewChild(ModalShellComponent);
  private readonly isBrowser = isPlatformBrowser(this.platformId);

  readonly activeModal = this.modalService.activeModal;
  protected readonly contentInjector = computed<Injector | undefined>(() => {
    const modal = this.activeModal();

    if (!modal) {
      return undefined;
    }

    return Injector.create({
      providers: [
        { provide: ModalRef, useValue: modal.ref },
        { provide: MODAL_DATA, useValue: modal.config.data ?? null }
      ],
      parent: this.injector
    });
  });

  constructor() {
    effect((onCleanup) => {
      const modal = this.activeModal();

      if (!this.isBrowser || !modal) {
        return;
      }

      const body = this.document.body;
      const previousOverflow = body.style.overflow;
      body.style.overflow = 'hidden';

      const onKeyDown = (event: KeyboardEvent) => {
        if (event.key !== 'Escape' || !this.activeModal()?.config.closeOnEscape) {
          return;
        }

        event.preventDefault();
        this.activeModal()?.ref.dismiss('escape');
      };

      this.document.addEventListener('keydown', onKeyDown);
      queueMicrotask(() => this.modalShell()?.focusInitialElement());

      onCleanup(() => {
        this.document.removeEventListener('keydown', onKeyDown);
        body.style.overflow = previousOverflow;
      });
    });
  }

  protected onBackdropClick(): void {
    const modal = this.activeModal();

    if (modal?.config.closeOnBackdrop) {
      modal.ref.dismiss('backdrop');
    }
  }

  protected onCloseRequested(): void {
    this.activeModal()?.ref.dismiss('programmatic');
  }
}
