import { ConnectedPosition, Overlay, OverlayConfig, OverlayRef } from '@angular/cdk/overlay'
import { CdkPortal } from '@angular/cdk/portal'
import { AfterViewInit, Component, ContentChild, ElementRef, inject, viewChild, input } from '@angular/core'
import { UntilDestroy } from '@ngneat/until-destroy'
import { OverlayContentDirective, OverlayTriggerDirective } from './directives'

type OverlayPosition = 'Top-Left' | 'Top-Center' | 'Top-Right' | 'Bottom-Left' | 'Bottom-Center' | 'Bottom-Right'

@UntilDestroy({ checkProperties: true })
@Component({
	selector: 'kadi-overlay',
	templateUrl: './overlay.component.html',
	standalone: false,
})
export class OverlayComponent implements AfterViewInit {
	private readonly _overlay = inject(Overlay)

	// TODO: Skipped for migration because:
	//  This query is used in a control flow expression (e.g. `@if` or `*ngIf`)
	//  and migrating would break narrowing currently.
	@ContentChild(OverlayTriggerDirective) trigger!: OverlayTriggerDirective
	// TODO: Skipped for migration because:
	//  This query is used in a control flow expression (e.g. `@if` or `*ngIf`)
	//  and migrating would break narrowing currently.
	@ContentChild(OverlayContentDirective) content!: OverlayContentDirective

	readonly overlayOrigin = viewChild.required<ElementRef<HTMLElement>>('overlayOrigin')
	readonly contentTemplateRef = viewChild.required<CdkPortal>('contentTemplate')

	readonly overlayStartPosition = input<OverlayPosition>('Bottom-Center')
	readonly transparentBackdrop = input(false)
	readonly width = input<number>()

	private overlayPositions!: ConnectedPosition[]

	private overlayRef: OverlayRef | undefined

	ngAfterViewInit(): void {
		this.overlayPositions = this.getConnectedPosition(this.overlayStartPosition())
		this.createOverlay()
	}

	openModal() {
		if (this.content === undefined) return
		this.overlayRef?.attach(this.contentTemplateRef())

		// TODO Refactoring Candidate: Find a better way to attach click event
		// eslint-disable-next-line unicorn-x/no-array-for-each
		document.querySelectorAll('[kadioverlayclosetrigger]').forEach((element) => {
			element.addEventListener('click', () => this.closeOverlay())
		})
	}

	closeOverlay(): void {
		this.overlayRef?.detach()
	}

	private createOverlay(): void {
		const position = this._overlay
			.position()
			.flexibleConnectedTo(this.overlayOrigin())
			.withPositions(this.overlayPositions)
		const config: OverlayConfig = {
			positionStrategy: position,
			hasBackdrop: true,
		}
		const width = this.width()
		if (width !== undefined) config.width = width
		if (this.transparentBackdrop()) config.backdropClass = 'bg-transparent'

		this.overlayRef = this._overlay.create(config)
		this.overlayRef.backdropClick().subscribe({
			next: () => this.closeOverlay(),
		})
	}

	private getConnectedPosition(position: OverlayPosition): ConnectedPosition[] {
		switch (position) {
			case 'Top-Left': {
				return [{ originX: 'start', originY: 'top', overlayX: 'end', overlayY: 'top' }]
			}
			case 'Top-Center': {
				return [{ originX: 'center', originY: 'top', overlayX: 'center', overlayY: 'top' }]
			}
			case 'Top-Right': {
				return [{ originX: 'end', originY: 'top', overlayX: 'start', overlayY: 'top' }]
			}
			case 'Bottom-Left': {
				return [{ originX: 'start', originY: 'bottom', overlayX: 'end', overlayY: 'top' }]
			}
			case 'Bottom-Center': {
				return [{ originX: 'center', originY: 'bottom', overlayX: 'center', overlayY: 'top' }]
			}
			case 'Bottom-Right': {
				return [{ originX: 'end', originY: 'bottom', overlayX: 'start', overlayY: 'top' }]
			}
		}
	}
}
