import { Component, inject, signal, OnInit, OnDestroy } from '@angular/core';
import { Router } from '@angular/router';
import { FormsModule } from '@angular/forms';
import { NzIconModule } from 'ng-zorro-antd/icon';
import { NzMessageService } from 'ng-zorro-antd/message';
import { Subject, debounceTime, distinctUntilChanged, takeUntil, forkJoin, of } from 'rxjs';
import { catchError, switchMap } from 'rxjs/operators';
import { CourseService } from '../../services/course.service';
import { EnrollmentService } from '../../services/enrollment.service';
import { AuthService } from '../../services/auth.service';
import { Course, CourseProgress } from '../../models/types';
import { CourseCard } from '../../components/course-card/course-card';
import { BottomNav } from '../../components/bottom-nav/bottom-nav';

@Component({
  selector: 'app-catalog',
  imports: [FormsModule, NzIconModule, CourseCard, BottomNav],
  providers: [NzMessageService],
  templateUrl: './catalog.html',
  styleUrl: './catalog.css'
})
export class CatalogPage implements OnInit, OnDestroy {
  private readonly courseService = inject(CourseService);
  private readonly enrollmentService = inject(EnrollmentService);
  private readonly authService = inject(AuthService);
  private readonly router = inject(Router);
  private readonly message = inject(NzMessageService);
  private readonly destroy$ = new Subject<void>();
  private readonly search$ = new Subject<string>();

  courses = signal<Course[]>([]);
  progressMap = signal<Record<string, CourseProgress>>({});
  loading = signal(false);
  searchQuery = signal('');
  isDark = signal(true);

  get currentUser() {
    return this.authService.currentUser();
  }

  ngOnInit(): void {
    this.search$.pipe(
      debounceTime(400),
      distinctUntilChanged(),
      takeUntil(this.destroy$)
    ).subscribe(query => {
      this.loadCourses(query);
    });

    this.loadCourses('');
  }

  ngOnDestroy(): void {
    this.destroy$.next();
    this.destroy$.complete();
  }

  onSearchChange(value: string): void {
    this.searchQuery.set(value);
    this.search$.next(value);
  }

  loadCourses(search: string): void {
    const user = this.currentUser;
    this.loading.set(true);

    const courses$ = this.courseService.getCourses(search);
    const enrollments$ = user
      ? this.enrollmentService.getEnrollments(user.userId).pipe(catchError(() => of([])))
      : of([]);

    forkJoin([courses$, enrollments$]).subscribe({
      next: ([courses, enrollments]) => {
        this.courses.set(courses);

        if (!user || enrollments.length === 0) {
          this.loading.set(false);
          return;
        }

        const progressRequests = enrollments.map((e: any) =>
          this.enrollmentService.getCourseProgress(e.courseId, user.userId).pipe(
            catchError(() => of(null))
          )
        );

        forkJoin(progressRequests).subscribe({
          next: (progressList) => {
            const map: Record<string, CourseProgress> = {};
            enrollments.forEach((e: any, i: number) => {
              if (progressList[i]) map[e.courseId] = progressList[i]!;
            });
            this.progressMap.set(map);
            this.loading.set(false);
          },
          error: () => this.loading.set(false)
        });
      },
      error: () => {
        this.loading.set(false);
        this.message.error('Impossible de charger les cours');
      }
    });
  }

  getProgress(courseId: string): CourseProgress | null {
    return this.progressMap()[courseId] ?? null;
  }

  onCourseClicked(course: Course): void {
    this.router.navigate(['/courses', course.id]);
  }

  toggleTheme(): void {
    const html = document.documentElement;
    if (html.classList.contains('dark')) {
      html.classList.remove('dark');
      this.isDark.set(false);
    } else {
      html.classList.add('dark');
      this.isDark.set(true);
    }
  }

  logout(): void {
    this.authService.logout();
    this.router.navigate(['/auth']);
  }
}
