import {Component, computed, effect, inject, OnInit, signal} from '@angular/core';
import {AppealsService, BannedUserResponse, DiscordAppeal, EmailEntry, MailService} from '@api';
import {FullSizeComponent} from '@shared-components/full-size/full-size.component';
import {HeaderComponent} from '@header/header.component';
import {MatButton, MatIconButton} from '@angular/material/button';
import {NgOptimizedImage} from '@angular/common';
import {MatProgressSpinnerModule} from '@angular/material/progress-spinner';
import {AuthService} from '@services/auth.service';
import {FormControl, FormGroup, FormsModule, ReactiveFormsModule, Validators} from '@angular/forms';
import {MatFormFieldModule} from '@angular/material/form-field';
import {MatInputModule} from '@angular/material/input';
import {MatIconModule} from '@angular/material/icon';
import {VerifyMailDialogComponent} from '@pages/forms/verify-mail-dialog/verify-mail-dialog.component';
import {MatDialog} from '@angular/material/dialog';
import {Router} from '@angular/router';
import {finalize} from 'rxjs';

@Component({
  selector: 'app-discord-appeal',
  imports: [
    FullSizeComponent,
    HeaderComponent,
    MatButton,
    MatProgressSpinnerModule,
    NgOptimizedImage,
    FormsModule,
    MatFormFieldModule,
    MatInputModule,
    MatIconModule,
    ReactiveFormsModule,
    MatIconButton,
  ],
  templateUrl: './discord-appeal.component.html',
  styleUrl: './discord-appeal.component.scss'
})
export class DiscordAppealComponent implements OnInit {
  private readonly appealService: AppealsService = inject(AppealsService)
  private readonly mailService = inject(MailService);
  private readonly dialog = inject(MatDialog);
  private readonly router = inject(Router)

  private emails = signal<EmailEntry[]>([]);

  protected readonly authService = inject(AuthService);

  protected bannedUser: BannedUserResponse | null = null;
  protected discordId: string = window.location.hostname === 'localhost' ? '212303885988134914' : '';
  protected verifiedEmails = computed(() => this.emails()
    .filter(email => {
      console.log(email.verified)
      return email.verified
    })
    .map(email => {
      console.log(email.email.toLowerCase())
      return email.email.toLowerCase()
    }));
  protected emailIsValid = signal<boolean>(false);
  protected currentPageIndex: number = 0;
  protected totalPages: number[] = [0];
  protected form: FormGroup<WebDiscordAppeal>;

  constructor() {
    this.form = new FormGroup({
      email: new FormControl('', {nonNullable: true, validators: [Validators.required, Validators.email]}),
      appeal: new FormControl('', {nonNullable: true, validators: [Validators.required, Validators.minLength(10)]})
    });
    effect(() => {
      if (this.verifiedEmails().length > 0) {
        console.log('verified emails')
        console.log(this.verifiedEmails()[0])
        this.form.get('email')?.setValue(this.verifiedEmails()[0]);
        this.emailIsValid.set(true);
      }
    });
  }

  ngOnInit(): void {
    if (window.location.hostname === 'localhost') {
      this.emails.set([{email: 'dev@alttd.com', verified: true}])
    } else {
      this.mailService.getUserEmails().subscribe(emails => {
        this.emails.set(emails);
      });
    }
    this.form.valueChanges.subscribe(() => {
      if (this.verifiedEmails().includes(this.form.getRawValue().email.toLowerCase())) {
        this.emailIsValid.set(true);
      } else {
        this.emailIsValid.set(false);
      }
    });

  }

  protected validateMailOrNextPage() {
    if (this.emailIsValid()) {
      this.nextPage();
      return;
    }
    const dialogRef = this.dialog.open(VerifyMailDialogComponent, {
      data: {email: this.form.getRawValue().email},
    });
    dialogRef.afterClosed().subscribe(result => {
      if (result === true) {
        this.emailIsValid.set(true);
      }
    });
  }

  public goToPage(pageIndex: number): void {
    if (pageIndex >= 0 && pageIndex < this.totalPages.length) {
      this.currentPageIndex = pageIndex;
    }
  }

  public previousPage() {
    this.goToPage(this.currentPageIndex - 1);
  }

  public nextPage() {
    if (this.currentPageIndex === this.totalPages.length - 1) {
      this.totalPages.push(this.currentPageIndex + 1);
    }
    this.goToPage(this.currentPageIndex + 1);
  }

  public isFirstPage(): boolean {
    return this.currentPageIndex === 0;
  }

  public isLastPage(): boolean {
    return this.currentPageIndex === this.totalPages.length - 1;
  }

  protected punishmentLoading: boolean = false;

  protected checkPunishment() {
    if (this.punishmentLoading) {
      return;
    }
    if (window.location.hostname === 'localhost') {
      this.bannedUser = {
        isBanned: false,
        bannedUser: {
          userId: '212303885988134914',
          reason: "This is a test punishment",
          name: "stijn",
          avatarUrl: "https://cdn.discordapp.com/avatars/212303885988134914/3a264be54ca7208d638a22143fc8fdb8.webp?size=160"
        }
      }
      this.nextPage();
      return
    }
    this.appealService.getBannedUser(this.discordId)
      .pipe(
        finalize(() => this.punishmentLoading = false)
      )
      .subscribe(user => {
        this.bannedUser = user
        this.nextPage();
      });
  }

  protected onSubmit() {
    if (this.form === undefined) {
      console.error('Form is undefined');
      return
    }
    if (this.form.valid) {
      this.sendForm()
    } else {
      Object.keys(this.form.controls).forEach(field => {
        const control = this.form!.get(field);
        if (!(control instanceof FormGroup)) {
          console.error('Control [' + control + '] is not a FormGroup');
          return;
        }
        control.markAsTouched({onlySelf: true});
      });
    }
  }

  protected formSubmitting: boolean = false;

  private sendForm() {
    if (this.formSubmitting) {
      return;
    }
    this.formSubmitting = true;
    const rawValue = this.form.getRawValue();
    const uuid = this.authService.getUuid();
    if (uuid === null) {
      throw new Error('JWT subject is null, are you logged in?');
    }
    const appeal: DiscordAppeal = {
      discordId: this.discordId,
      appeal: rawValue.appeal,
      email: rawValue.email,
    }
    this.appealService.submitDiscordAppeal(appeal)
      .pipe(
        finalize(() => this.formSubmitting = false)
      )
      .subscribe((result) => {
        if (!result.verified_mail) {
          throw new Error('Mail not verified');
        }
        this.router.navigate(['/forms/sent'], {
          state: {message: result.message}
        }).then();
      })
  }
}

interface WebDiscordAppeal {
  email: FormControl<string>;
  appeal: FormControl<string>;
}
