import { Component, inject, signal, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { FormsModule } from '@angular/forms';
import { NzIconModule } from 'ng-zorro-antd/icon';
import { NzMessageService } from 'ng-zorro-antd/message';
import { CourseService } from '../../services/course.service';
import { TopicService } from '../../services/topic.service';
import { ResourceService } from '../../services/resource.service';
import { AuthService } from '../../services/auth.service';
import { CourseDetails, Topic, Resource, ResourceType } from '../../models/types';
import { getErrorMessage } from '../../utils/error.utils';
import { forkJoin } from 'rxjs';

type EditorMode = 'course' | 'topic' | 'resource' | 'link-resource';

@Component({
  selector: 'app-course-editor',
  imports: [FormsModule, NzIconModule],
  providers: [NzMessageService],
  templateUrl: './course-editor.html',
  styleUrl: './course-editor.css'
})
export class CourseEditorPage implements OnInit {
  private readonly route = inject(ActivatedRoute);
  private readonly router = inject(Router);
  private readonly courseService = inject(CourseService);
  private readonly topicService = inject(TopicService);
  private readonly resourceService = inject(ResourceService);
  private readonly authService = inject(AuthService);
  private readonly message = inject(NzMessageService);

  // State
  isEditMode = signal(false);
  loading = signal(true);
  saving = signal(false);
  publishing = signal(false);
  mode = signal<EditorMode>('course');

  course = signal<CourseDetails | null>(null);
  allResources = signal<Resource[]>([]);
  selectedTopic = signal<Topic | null>(null);

  // Course form
  courseTitle = signal('');
  courseDescription = signal('');

  // Topic form
  topicTitle = signal('');
  topicDescription = signal('');
  editingTopicId = signal<string | null>(null);

  // Resource form
  resourceType = signal<ResourceType>('Url');
  resourceTitle = signal('');
  resourceContent = signal('');
  editingResourceId = signal<string | null>(null);

  resourceTypes: ResourceType[] = ['Url', 'Video', 'Text', 'File'];

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

  ngOnInit(): void {
    const id = this.route.snapshot.paramMap.get('id');
    if (id) {
      this.isEditMode.set(true);
      this.loadCourse(id);
    } else {
      this.loading.set(false);
    }
  }

  loadCourse(id: string): void {
    this.loading.set(true);
    forkJoin([
      this.courseService.getCourseById(id),
      this.resourceService.getResources()
    ]).subscribe({
      next: ([course, resources]) => {
        this.course.set(course);
        this.courseTitle.set(course.title);
        this.courseDescription.set(course.description);
        this.allResources.set(resources);
        this.loading.set(false);
      },
      error: () => {
        this.loading.set(false);
        this.message.error('Cours introuvable');
        this.router.navigate(['/catalog']);
      }
    });
  }

  // -- Course actions --

  saveCourse(): void {
    if (!this.courseTitle().trim()) {
      this.message.warning('Le titre est requis');
      return;
    }
    this.saving.set(true);
    const user = this.currentUser;

    if (this.isEditMode()) {
      const id = this.course()!.id;
      this.courseService.updateCourse(id, this.courseTitle(), this.courseDescription()).subscribe({
        next: (updated) => {
          this.course.update(c => c ? { ...c, title: updated.title, description: updated.description } : c);
          this.saving.set(false);
          this.message.success('Cours mis à jour');
        },
        error: () => {
          this.saving.set(false);
          this.message.error('Erreur lors de la mise à jour');
        }
      });
    } else {
      if (!user) return;
      this.courseService.createCourse(this.courseTitle(), this.courseDescription(), user.userId).subscribe({
        next: (created) => {
          this.saving.set(false);
          this.message.success('Cours créé !');
          this.router.navigate(['/courses', created.id, 'edit']);
        },
        error: (err) => {
          this.saving.set(false);
          this.message.error(getErrorMessage(err, 'Erreur lors de la création'));
        }
      });
    }
  }

  publishCourse(): void {
    const course = this.course();
    if (!course) return;
    this.publishing.set(true);
    this.courseService.publishCourse(course.id).subscribe({
      next: (updated) => {
        this.course.update(c => c ? { ...c, status: updated.status } : c);
        this.publishing.set(false);
        this.message.success('Cours publié !');
      },
      error: (err) => {
        this.publishing.set(false);
        this.message.error(getErrorMessage(err, 'Impossible de publier le cours'));
      }
    });
  }

  deleteCourse(): void {
    const course = this.course();
    if (!course) return;
    this.courseService.deleteCourse(course.id).subscribe({
      next: () => {
        this.message.success('Cours supprimé');
        this.router.navigate(['/catalog']);
      },
      error: (err) => {
        this.message.error(getErrorMessage(err, 'Impossible de supprimer le cours'));
      }
    });
  }

  // -- Topic actions --

  openAddTopic(): void {
    this.topicTitle.set('');
    this.topicDescription.set('');
    this.editingTopicId.set(null);
    this.mode.set('topic');
  }

  openEditTopic(topic: Topic, event: Event): void {
    event.stopPropagation();
    this.topicTitle.set(topic.title);
    this.topicDescription.set(topic.description ?? '');
    this.editingTopicId.set(topic.id);
    this.mode.set('topic');
  }

  saveTopic(): void {
    if (!this.topicTitle().trim()) {
      this.message.warning('Le titre du sujet est requis');
      return;
    }
    const course = this.course();
    if (!course) return;
    this.saving.set(true);

    const editId = this.editingTopicId();
    if (editId) {
      const existing = course.topics.find(t => t.id === editId)!;
      this.topicService.updateTopic(editId, this.topicTitle(), this.topicDescription(), existing.position).subscribe({
        next: (updated) => {
          this.course.update(c => c ? {
            ...c,
            topics: c.topics.map(t => t.id === editId ? { ...t, ...updated } : t)
          } : c);
          this.saving.set(false);
          this.mode.set('course');
          this.message.success('Sujet mis à jour');
        },
        error: () => {
          this.saving.set(false);
          this.message.error('Erreur lors de la mise à jour');
        }
      });
    } else {
      const position = course.topics.length + 1;
      const desc = this.topicDescription().trim() || null;
      this.topicService.createTopic(course.id, this.topicTitle(), desc, position).subscribe({
        next: (created) => {
          this.course.update(c => c ? {
            ...c,
            topics: [...c.topics, { ...created, resources: [] }],
            topicCount: c.topicCount + 1
          } : c);
          this.saving.set(false);
          this.mode.set('course');
          this.message.success('Sujet ajouté');
        },
        error: (err) => {
          this.saving.set(false);
          this.message.error(getErrorMessage(err, 'Erreur lors de la création du sujet'));
        }
      });
    }
  }

  deleteTopic(topic: Topic, event: Event): void {
    event.stopPropagation();
    this.topicService.deleteTopic(topic.id).subscribe({
      next: () => {
        this.course.update(c => c ? {
          ...c,
          topics: c.topics.filter(t => t.id !== topic.id),
          topicCount: c.topicCount - 1
        } : c);
        this.message.success('Sujet supprimé');
      },
      error: () => this.message.error('Impossible de supprimer ce sujet')
    });
  }

  // -- Resource actions --

  openAddResource(): void {
    this.resourceType.set('Url');
    this.resourceTitle.set('');
    this.resourceContent.set('');
    this.editingResourceId.set(null);
    this.mode.set('resource');
  }

  openLinkResource(topic: Topic, event: Event): void {
    event.stopPropagation();
    this.selectedTopic.set(topic);
    this.resourceService.getResources().subscribe({
      next: (resources) => {
        this.allResources.set(resources);
        this.mode.set('link-resource');
      },
      error: () => this.message.error('Impossible de charger les ressources')
    });
  }

  saveResource(): void {
    if (!this.resourceTitle().trim() || !this.resourceContent().trim()) {
      this.message.warning('Titre et contenu sont requis');
      return;
    }
    this.saving.set(true);
    this.resourceService.createResource(this.resourceType(), this.resourceTitle(), this.resourceContent()).subscribe({
      next: (created) => {
        this.allResources.update(list => [...list, created]);
        this.saving.set(false);
        this.mode.set('course');
        this.message.success('Ressource créée');
      },
      error: (err) => {
        this.saving.set(false);
        this.message.error(getErrorMessage(err, 'Erreur lors de la création de la ressource'));
      }
    });
  }

  linkResource(resource: Resource): void {
    const topic = this.selectedTopic();
    if (!topic) return;

    const position = topic.resources.length + 1;
    this.topicService.linkResource(topic.id, resource.id, position).subscribe({
      next: () => {
        this.course.update(c => c ? {
          ...c,
          topics: c.topics.map(t => t.id === topic.id
            ? { ...t, resources: [...t.resources, resource] }
            : t
          )
        } : c);
        this.selectedTopic.update(t => t ? { ...t, resources: [...t.resources, resource] } : t);
        this.message.success('Ressource liée');
      },
      error: () => this.message.error('Erreur lors de la liaison')
    });
  }

  unlinkResource(topic: Topic, resource: Resource, event: Event): void {
    event.stopPropagation();
    this.topicService.unlinkResource(topic.id, resource.id).subscribe({
      next: () => {
        this.course.update(c => c ? {
          ...c,
          topics: c.topics.map(t => t.id === topic.id
            ? { ...t, resources: t.resources.filter(r => r.id !== resource.id) }
            : t
          )
        } : c);
        this.message.success('Ressource retirée');
      },
      error: () => this.message.error('Erreur lors du retrait')
    });
  }

  isResourceLinked(resource: Resource): boolean {
    return this.selectedTopic()?.resources.some(r => r.id === resource.id) ?? false;
  }

  getResourceIcon(type: string): string {
    switch (type) {
      case 'Video': return 'video-camera';
      case 'Text': return 'file-text';
      case 'File': return 'file';
      default: return 'link';
    }
  }

  cancelMode(): void {
    this.mode.set('course');
  }

  goBack(): void {
    this.router.navigate(['/catalog']);
  }
}
