import { AfterViewInit, Component, inject, signal, viewChild } from '@angular/core'
import { toSignal } from '@angular/core/rxjs-interop'
import { NonNullableFormBuilder, ReactiveFormsModule } from '@angular/forms'
import { RouterLink } from '@angular/router'
import { WeekDay } from '@core/types'
import { TimeUtils } from '@core/utils'
import { DefaultService, ScheduleSettings, TimingRule } from '@api-client/angular'
import { TranslocoDirective } from '@jsverse/transloco'
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy'
import { HotToastService } from '@ngxpert/hot-toast'
import { finalize, map } from 'rxjs'
import { SettingsStore } from '../../../+state'
import { I18nService } from '../../../core'
import { SpecialDaysSettingsComponent } from './special-days'
import { WeeklyScheduleSettingsComponent } from './weekly-schedule'
import { LucideChevronLeft } from '@lucide/angular'

@UntilDestroy({ checkProperties: true })
@Component({
	selector: 'kadi-schedule-settings',
	templateUrl: './schedule-settings.component.html',
	styleUrls: ['./schedule-settings.component.scss'],
	imports: [
		TranslocoDirective,
		RouterLink,
		ReactiveFormsModule,
		WeeklyScheduleSettingsComponent,
		SpecialDaysSettingsComponent,
		LucideChevronLeft,
	],
})
export class ScheduleSettingsComponent implements AfterViewInit {
	private readonly _toast = inject(HotToastService)
	private readonly _i18nService = inject(I18nService)
	private readonly _formBuilder = inject(NonNullableFormBuilder)
	private readonly _apiService = inject(DefaultService)
	private readonly _settingsStore = inject(SettingsStore)

	readonly weeklySettingsComponent = viewChild.required(WeeklyScheduleSettingsComponent)
	readonly specialDaysSettingsComponent = viewChild.required(SpecialDaysSettingsComponent)

	schedule = toSignal(this._apiService.settingsControllerFind().pipe(map(({ schedule }) => schedule)))
	loading = signal(false)

	form = this._formBuilder.group({})

	ngAfterViewInit(): void {
		this.form.addControl('weeklySchedule', this.weeklySettingsComponent().form.controls.schedule)
		this.form.addControl('specialDays', this.specialDaysSettingsComponent().form.controls.schedule)
	}

	save(): void {
		if (this.form.invalid) return

		this.loading.set(true)

		const schedule = this.form.value as ScheduleSettings

		for (const day of Object.keys(schedule.weeklySchedule)) {
			const rules = schedule.weeklySchedule[day as WeekDay].rules
			this.formatRuleTimes(rules ?? [])
		}

		for (const day of schedule.specialDays) {
			this.formatRuleTimes(day.rules ?? [])
		}

		this._apiService
			.settingsControllerSave({ schedule })
			.pipe(
				untilDestroyed(this),
				this._toast.observe({
					loading: this._i18nService.translate('update_schedule_loading'),
					success: this._i18nService.translate('update_schedule_success'),
					error: this._i18nService.translate('update_schedule_error'),
				}),
				finalize(() => this.loading.set(false)),
			)
			.subscribe({
				next: () => {
					this.form.markAsPristine()
				},
			})
	}

	private formatRuleTimes(rules: TimingRule[]): void {
		for (const rule of rules) {
			if (!rule) continue

			if (rule.closingTime && typeof rule.closingTime === 'string') {
				rule.closingTime = TimeUtils.localToUtc(
					TimeUtils.parseFromString(rule.closingTime as unknown as string),
					this._settingsStore.timezone(),
				)
			}
			if (rule.openingTime && typeof rule.openingTime === 'string') {
				rule.openingTime = TimeUtils.localToUtc(
					TimeUtils.parseFromString(rule.openingTime as unknown as string),
					this._settingsStore.timezone(),
				)
			}
		}
	}
}
