import { Component, ChangeDetectionStrategy, signal, inject, OnInit, input, computed } from '@angular/core';
import { RouterLink } from '@angular/router';
import { MatIconModule } from '@angular/material/icon';
import { MatButtonModule } from '@angular/material/button';
import { MatTooltipModule } from '@angular/material/tooltip';
import { EnrollmentService, NotificationService, ErrorHandlerService } from '@core/services';
import { Student, AvailableSubject, Enrollment } from '@core/models';
import { LoadingSpinnerComponent, EmptyStateComponent } from '@shared/index';

@Component({
  selector: 'app-enrollment-page',
  standalone: true,
  imports: [
    RouterLink, MatIconModule, MatButtonModule, MatTooltipModule,
    LoadingSpinnerComponent, EmptyStateComponent
  ],
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    <div class="page">
      <a routerLink="/students" class="back-link">
        <mat-icon>arrow_back</mat-icon>
        Volver a estudiantes
      </a>

      @if (loading()) {
        <app-loading-spinner message="Cargando inscripciones..." />
      } @else if (!student()) {
        <app-empty-state
          icon="error"
          title="Estudiante no encontrado"
          description="El estudiante solicitado no existe"
        >
          <a routerLink="/students" class="btn btn-primary">Volver</a>
        </app-empty-state>
      } @else {
        <header class="page-header">
          <div>
            <h1>Inscripción: {{ student()?.name }}</h1>
            <p class="page-subtitle">{{ student()?.email }}</p>
          </div>
          <a [routerLink]="['/classmates', studentId()]" class="btn btn-secondary"
             [class.disabled]="enrollments().length === 0">
            <mat-icon>group</mat-icon>
            Ver Compañeros
          </a>
        </header>

        <!-- Progress Section -->
        <div class="stats-row">
          <div class="stat-card">
            <div class="stat-header">
              <mat-icon>school</mat-icon>
              <span>Créditos</span>
            </div>
            <div class="stat-value">
              <span class="stat-current">{{ student()?.totalCredits || 0 }}</span>
              <span class="stat-max">/9</span>
            </div>
            <div class="progress-bar">
              <div class="progress-bar-fill" [style.width.%]="creditsProgress()"></div>
            </div>
          </div>
          <div class="stat-card">
            <div class="stat-header">
              <mat-icon>book</mat-icon>
              <span>Materias</span>
            </div>
            <div class="stat-value">
              <span class="stat-current">{{ enrollments().length }}</span>
              <span class="stat-max">/3</span>
            </div>
            <div class="progress-bar">
              <div class="progress-bar-fill" [style.width.%]="subjectsProgress()"></div>
            </div>
          </div>
        </div>

        <!-- Enrolled Subjects -->
        @if (enrollments().length > 0) {
          <section class="section">
            <h2 class="section-title">
              <mat-icon>check_circle</mat-icon>
              Materias Inscritas
            </h2>
            <div class="subjects-grid">
              @for (enrollment of enrollments(); track enrollment.id) {
                <div class="subject-card enrolled">
                  <div class="subject-card-info">
                    <div class="subject-card-name" data-testid="enrolled-subject-name">{{ enrollment.subjectName }}</div>
                    <div class="subject-card-professor">
                      <mat-icon>person</mat-icon>
                      {{ enrollment.professorName }}
                    </div>
                    <div class="subject-card-credits">{{ enrollment.credits }} créditos</div>
                  </div>
                  <button
                    class="btn btn-sm btn-danger"
                    (click)="unenroll(enrollment)"
                    [disabled]="processingId() === enrollment.id"
                    matTooltip="Cancelar inscripción"
                    data-testid="btn-unenroll-subject"
                  >
                    @if (processingId() === enrollment.id) {
                      <span class="btn-loading"></span>
                    } @else {
                      <mat-icon>close</mat-icon>
                      Cancelar
                    }
                  </button>
                </div>
              }
            </div>
          </section>
        }

        <!-- Available Subjects -->
        <section class="section">
          <h2 class="section-title">
            <mat-icon>add_circle</mat-icon>
            Materias Disponibles
          </h2>

          @if (loadingAvailable()) {
            <app-loading-spinner [size]="32" />
          } @else if (availableSubjects().length === 0) {
            <app-empty-state
              icon="check_circle"
              title="Inscripción completa"
              description="Ya has seleccionado el máximo de materias permitidas"
            />
          } @else {
            <div class="subjects-grid">
              @for (item of availableSubjects(); track item.id) {
                <div class="subject-card" [class.unavailable]="!item.isAvailable">
                  <div class="subject-card-info">
                    <div class="subject-card-name">{{ item.name }}</div>
                    <div class="subject-card-professor">
                      <mat-icon>person</mat-icon>
                      {{ item.professorName }}
                    </div>
                    <div class="subject-card-credits">{{ item.credits }} créditos</div>
                    @if (!item.isAvailable && item.unavailableReason) {
                      <div class="subject-card-warning">
                        <mat-icon>warning</mat-icon>
                        {{ translateReason(item.unavailableReason) }}
                      </div>
                    }
                  </div>
                  <button
                    class="btn btn-sm btn-primary"
                    (click)="enroll(item)"
                    [disabled]="!item.isAvailable || processingId() === item.id || enrollments().length >= 3"
                    [matTooltip]="!item.isAvailable ? translateReason(item.unavailableReason || '') : 'Inscribir'"
                    data-testid="btn-enroll-subject"
                  >
                    @if (processingId() === item.id) {
                      <span class="btn-loading"></span>
                    } @else {
                      <mat-icon>add</mat-icon>
                      Inscribir
                    }
                  </button>
                </div>
              }
            </div>
          }
        </section>
      }
    </div>
  `,
  styles: [`
    .page {
      animation: fadeIn 0.3s ease;
    }

    @keyframes fadeIn {
      from { opacity: 0; transform: translateY(8px); }
      to { opacity: 1; transform: translateY(0); }
    }

    .stats-row {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
      gap: 1rem;
      margin-bottom: 2rem;
    }

    .stat-card {
      background: var(--bg-secondary);
      border: 1px solid var(--border-light);
      border-radius: var(--radius-lg);
      padding: 1.25rem;
    }

    .stat-header {
      display: flex;
      align-items: center;
      gap: 0.5rem;
      color: var(--text-secondary);
      font-size: 0.875rem;
      margin-bottom: 0.5rem;

      mat-icon {
        font-size: 1.125rem;
        width: 1.125rem;
        height: 1.125rem;
      }
    }

    .stat-value {
      font-size: 2rem;
      font-weight: 600;
      margin-bottom: 0.75rem;
    }

    .stat-current {
      color: var(--text-primary);
    }

    .stat-max {
      color: var(--text-tertiary);
    }

    .section {
      margin-bottom: 2rem;
    }

    .section-title {
      display: flex;
      align-items: center;
      gap: 0.75rem;
      font-size: 1.125rem;
      font-weight: 600;
      margin-bottom: 1rem;
      color: var(--text-primary);

      mat-icon {
        color: var(--accent);
      }
    }

    .subjects-grid {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
      gap: 1rem;
    }

    .subject-card {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 1rem;
      padding: 1.25rem;
      background: var(--bg-secondary);
      border: 1px solid var(--border-light);
      border-radius: var(--radius-md);
      transition: all var(--transition);

      &:hover {
        border-color: var(--border-medium);
        box-shadow: var(--shadow-sm);
      }

      &.enrolled {
        border-color: var(--success);
        background: rgba(52, 199, 89, 0.04);
      }

      &.unavailable {
        opacity: 0.7;
        background: var(--bg-tertiary);
      }
    }

    .subject-card-info {
      flex: 1;
      min-width: 0;
    }

    .subject-card-name {
      font-weight: 600;
      margin-bottom: 0.375rem;
      color: var(--text-primary);
    }

    .subject-card-professor {
      display: flex;
      align-items: center;
      gap: 0.375rem;
      font-size: 0.875rem;
      color: var(--text-secondary);
      margin-bottom: 0.25rem;

      mat-icon {
        font-size: 1rem;
        width: 1rem;
        height: 1rem;
      }
    }

    .subject-card-credits {
      font-size: 0.8125rem;
      color: var(--text-tertiary);
    }

    .subject-card-warning {
      display: flex;
      align-items: center;
      gap: 0.375rem;
      font-size: 0.8125rem;
      color: var(--warning);
      margin-top: 0.5rem;

      mat-icon {
        font-size: 0.875rem;
        width: 0.875rem;
        height: 0.875rem;
      }
    }

    .btn-loading {
      width: 14px;
      height: 14px;
      border: 2px solid rgba(255, 255, 255, 0.3);
      border-top-color: white;
      border-radius: 50%;
      animation: spin 0.8s linear infinite;
    }

    @keyframes spin {
      to { transform: rotate(360deg); }
    }

    .disabled {
      pointer-events: none;
      opacity: 0.5;
    }
  `],
})
export class EnrollmentPageComponent implements OnInit {
  studentId = input.required<string>();

  private enrollmentService = inject(EnrollmentService);
  private notification = inject(NotificationService);
  private errorHandler = inject(ErrorHandlerService);

  student = signal<Student | null>(null);
  availableSubjects = signal<AvailableSubject[]>([]);
  loading = signal(true);
  loadingAvailable = signal(true);
  processingId = signal<number | null>(null);

  enrollments = computed(() => this.student()?.enrollments ?? []);
  creditsProgress = computed(() => ((this.student()?.totalCredits ?? 0) / 9) * 100);
  subjectsProgress = computed(() => (this.enrollments().length / 3) * 100);

  ngOnInit(): void {
    this.loadData();
  }

  private loadData(): void {
    const id = parseInt(this.studentId(), 10);

    this.enrollmentService.getStudentWithEnrollments(id).subscribe({
      next: ({ data, loading }) => {
        this.student.set(data);
        this.loading.set(loading);
      },
      error: (error) => {
        this.loading.set(false);
        this.errorHandler.handle(error, 'Enrollment.cargarEstudiante');
      },
    });

    this.enrollmentService.getAvailableSubjects(id).subscribe({
      next: ({ data, loading }) => {
        this.availableSubjects.set(data);
        this.loadingAvailable.set(loading);
      },
      error: (error) => {
        this.loadingAvailable.set(false);
        this.errorHandler.handle(error, 'Enrollment.cargarMaterias');
      },
    });
  }

  enroll(item: AvailableSubject): void {
    if (!item.isAvailable) return;

    const studentId = parseInt(this.studentId(), 10);
    this.processingId.set(item.id);

    this.enrollmentService.enrollStudent({
      studentId,
      subjectId: item.id,
    }).subscribe({
      next: (result) => {
        this.processingId.set(null);
        if (result.enrollment) {
          this.notification.success(`Inscrito en ${item.name}`);
        } else if (result.errors?.length) {
          this.notification.error(result.errors.join('. '));
        }
      },
      error: (error) => {
        this.processingId.set(null);
        this.errorHandler.handle(error, `Enrollment.inscribir(${item.name})`);
      },
    });
  }

  unenroll(enrollment: Enrollment): void {
    const studentId = parseInt(this.studentId(), 10);
    this.processingId.set(enrollment.id);

    this.enrollmentService.unenrollStudent(enrollment.id, studentId).subscribe({
      next: (result) => {
        this.processingId.set(null);
        if (result.success) {
          this.notification.success(`Inscripción cancelada: ${enrollment.subjectName}`);
        } else if (result.errors?.length) {
          this.notification.error(result.errors.join('. '));
        }
      },
      error: (error) => {
        this.processingId.set(null);
        this.errorHandler.handle(error, `Enrollment.cancelar(${enrollment.subjectName})`);
      },
    });
  }

  private readonly reasonTranslations: Record<string, string> = {
    'Already enrolled': 'Ya inscrito',
    'Already have a subject with this professor': 'Ya tienes una materia con este profesor',
    'Maximum 3 subjects reached': 'Máximo 3 materias alcanzado',
  };

  translateReason(reason: string): string {
    return this.reasonTranslations[reason] ?? reason;
  }
}
