import {Component, Inject, inject, signal} from '@angular/core';
import {FormsModule} from '@angular/forms';
import {MatButtonModule} from '@angular/material/button';
import {MatFormFieldModule} from '@angular/material/form-field';
import {MatInput, MatLabel} from '@angular/material/input';
import {MatCheckboxModule} from '@angular/material/checkbox';
import {
  MAT_DIALOG_DATA,
  MatDialogActions,
  MatDialogContent,
  MatDialogRef,
  MatDialogTitle
} from '@angular/material/dialog';
import {HistoryService, PunishmentHistory} from '@api';
import {firstValueFrom} from 'rxjs';
import {MatDatepickerModule} from '@angular/material/datepicker';

interface EditPunishmentData {
  punishment: PunishmentHistory;
}

@Component({
  selector: 'app-edit-punishment-dialog',
  standalone: true,
  imports: [
    FormsModule,
    MatButtonModule,
    MatFormFieldModule,
    MatInput,
    MatLabel,
    MatCheckboxModule,
    MatDialogTitle,
    MatDialogContent,
    MatDialogActions,
    MatDatepickerModule,
  ],
  templateUrl: './edit-punishment-dialog.component.html',
  styleUrl: './edit-punishment-dialog.component.scss'
})
export class EditPunishmentDialogComponent {
  // Form model
  protected reason: string = '';
  protected isPermanent: boolean = false;
  protected expiresAt: Date;
  protected expiryDate: Date | null = null;
  protected expiryTime: string = '';

  // UI state
  protected isBusy = signal<boolean>(false);
  protected errorMessage = signal<string | null>(null);

  private historyApi = inject(HistoryService);

  constructor(
    public dialogRef: MatDialogRef<EditPunishmentDialogComponent, PunishmentHistory | { removed: true } | null>,
    @Inject(MAT_DIALOG_DATA) public data: EditPunishmentData
  ) {
    const punishment = data.punishment;
    this.reason = punishment.reason ?? '';
    this.isPermanent = punishment.expiryTime <= 0;
    this.expiresAt = new Date(punishment.expiryTime);

    if (this.expiresAt && !isNaN(this.expiresAt.getTime())) {
      this.expiryDate = new Date(this.expiresAt);

      const hours = this.expiresAt.getHours().toString().padStart(2, '0');
      const minutes = this.expiresAt.getMinutes().toString().padStart(2, '0');
      this.expiryTime = `${hours}:${minutes}`;
    }
  }

  onCancel(): void {
    if (this.isBusy()) {
      return;
    }
    this.dialogRef.close(null);
  }

  private computeUntilMs(): number {
    if (this.isPermanent) {
      return 0;
    }

    if (!this.expiryDate) {
      return 0;
    }

    const combinedDateTime = new Date(this.expiryDate);

    if (this.expiryTime) {
      const [hours, minutes] = this.expiryTime.split(':').map(Number);
      combinedDateTime.setHours(hours, minutes, 0, 0);
    }

    this.expiresAt = combinedDateTime;

    const ms = combinedDateTime.getTime();
    return isNaN(ms) ? -1 : ms;
  }

  onUpdate(): void {
    const punishment = this.data.punishment;
    if (!window.confirm('Are you sure you want to update this punishment?')) {
      return;
    }
    this.isBusy.set(true);
    this.errorMessage.set(null);

    const updates: Array<Promise<PunishmentHistory>> = [] as any;

    if ((this.reason ?? '') !== (punishment.reason ?? '')) {
      console.log('Changing reason to ', this.reason, ' from ', punishment.reason, '')
      updates.push(firstValueFrom(this.historyApi.updatePunishmentReason(punishment.type, punishment.id, this.reason)));
    }

    const newUntil = this.computeUntilMs();
    if (newUntil !== punishment.expiryTime) {
      console.log('Changing until to ', newUntil, ' from ', punishment.expiryTime, '')
      updates.push(firstValueFrom(this.historyApi.updatePunishmentUntil(punishment.type, punishment.id, newUntil)));
    }

    if (updates.length === 0) {
      this.isBusy.set(false);
      this.dialogRef.close(null);
      return;
    }

    Promise.all(updates)
      .then(results => {
        const updated = results[results.length - 1];
        this.isBusy.set(false);
        this.dialogRef.close(updated);
      })
      .catch(err => {
        console.error(err);
        this.errorMessage.set('Failed to update punishment');
        this.isBusy.set(false);
      });
  }

  onRemove(): void {
    const punishment = this.data.punishment;
    if (!window.confirm('Are you sure you want to remove this punishment?')) {
      return;
    }
    this.isBusy.set(true);
    this.errorMessage.set(null);

    this.historyApi.removePunishment(punishment.type as any, punishment.id).subscribe({
      next: () => {
        this.isBusy.set(false);
        this.dialogRef.close({removed: true});
      },
      error: (err) => {
        console.error(err);
        this.errorMessage.set('Failed to remove punishment');
        this.isBusy.set(false);
      }
    })
  }

  getTimezone() {
    return Intl.DateTimeFormat().resolvedOptions().timeZone ?? 'Unknown';
  }
}
