import { Component, OnInit, signal, computed, inject } from '@angular/core';
import { CommonModule } from '@angular/common';
import { Router, RouterModule } from '@angular/router';
import { ReservasService } from '../services/reservas.service';

export interface Resource {
  id: string;
  name: string;
  type: 'Sala Reuniones' | 'Oficina Flexible' | 'Zona Relax' | 'Evento';
  icon: string;
  desc: string;
  capacity: number;
}

@Component({
  selector: 'app-calendar-booking',
  standalone: true,
  imports: [CommonModule, RouterModule],
  templateUrl: './calendar-booking.component.html',
  styleUrls: ['./calendar-booking.component.css']
})
export class CalendarBookingComponent implements OnInit {
  private router = inject(Router);
  reservasService = inject(ReservasService);

  // Horarios laborales (en hora exacta para coincidir con el backend)
  timeSlots = ['09:00', '10:00', '11:00', '12:00', '14:00', '15:00', '16:00', '17:00'];

  // Recursos disponibles — alineados con el seed
  resources = signal<Resource[]>([
    { id: 'aton1', name: 'Sala Aton 1', type: 'Sala Reuniones', icon: '🌙', desc: 'Sala equipada para reuniones ejecutivas', capacity: 40 },
    { id: 'aton2', name: 'Sala Aton 2', type: 'Sala Reuniones', icon: '☀️', desc: 'Sala estándar para equipos de trabajo', capacity: 50 },
    { id: 'aton3', name: 'Sala Aton 3', type: 'Oficina Flexible', icon: '🏢', desc: 'Puesto de trabajo con vista panorámica', capacity: 30 },
    { id: 'cowork-1', name: 'Espacio Coworking 1', type: 'Oficina Flexible', icon: '🏢', desc: 'Puesto de trabajo abierto y colaborativo', capacity: 50 },
    { id: 'auditorio', name: 'Auditorio Principal', type: 'Evento', icon: '🎤', desc: 'Auditorio para presentaciones corporativas', capacity: 100 },
  ]);

  // ── Estado de la fecha activa ──
  activeDate = signal<Date>(this.getNextWeekday(new Date()));

  // ── Filtros ──
  selectedCategories = signal<string[]>(['Sala Reuniones', 'Oficina Flexible', 'Zona Relax', 'Evento']);
  searchQuery = signal<string>('');

  // ── UI ──
  selectedSlot = signal<{ resource: Resource; time: string } | null>(null);
  confirmLoading = signal<boolean>(false);
  confirmError = signal<string | null>(null);
  confirmSuccess = signal<boolean>(false);

  // ── Computed ──
  filteredResources = computed(() => {
    const cats = this.selectedCategories();
    const q = this.searchQuery().toLowerCase().trim();
    return this.resources().filter(
      (r) =>
        cats.includes(r.type) &&
        (!q || r.name.toLowerCase().includes(q) || r.desc.toLowerCase().includes(q))
    );
  });

  activeDateStr = computed(() => this.toDateStr(this.activeDate()));

  activeDateLabel = computed(() => {
    const d = this.activeDate();
    return d.toLocaleDateString('es-ES', { weekday: 'long', day: 'numeric', month: 'long', year: 'numeric' });
  });

  monthLabel = computed(() => {
    const d = this.activeDate();
    return d.toLocaleDateString('es-ES', { month: 'long', year: 'numeric' });
  });

  // Mini calendar — genera los días del mes de la fecha activa
  miniCalendarDays = computed(() => {
    const d = this.activeDate();
    const year = d.getFullYear();
    const month = d.getMonth();
    const firstDay = new Date(year, month, 1).getDay();
    const daysInMonth = new Date(year, month + 1, 0).getDate();
    const prevDays = new Date(year, month, 0).getDate();
    const days: { day: number; currentMonth: boolean; active?: boolean; date: Date }[] = [];

    // días del mes anterior para completar la primera semana
    for (let i = firstDay - 1; i >= 0; i--) {
      const day = prevDays - i;
      days.push({ day, currentMonth: false, date: new Date(year, month - 1, day) });
    }
    // días del mes actual
    for (let i = 1; i <= daysInMonth; i++) {
      const date = new Date(year, month, i);
      days.push({ day: i, currentMonth: true, active: this.toDateStr(date) === this.activeDateStr(), date });
    }
    // completar hasta 42 celdas
    const remaining = 42 - days.length;
    for (let i = 1; i <= remaining; i++) {
      days.push({ day: i, currentMonth: false, date: new Date(year, month + 1, i) });
    }
    return days;
  });

  // ── Lifecycle ──
  ngOnInit(): void {
    this.loadForDate(this.activeDate());
  }

  // ── Navegación de fechas ──
  prevDay(): void {
    const d = new Date(this.activeDate());
    d.setDate(d.getDate() - 1);
    this.activeDate.set(d);
    this.selectedSlot.set(null);
    this.loadForDate(d);
  }

  nextDay(): void {
    const d = new Date(this.activeDate());
    d.setDate(d.getDate() + 1);
    this.activeDate.set(d);
    this.selectedSlot.set(null);
    this.loadForDate(d);
  }

  goToToday(): void {
    const today = this.getNextWeekday(new Date());
    this.activeDate.set(today);
    this.selectedSlot.set(null);
    this.loadForDate(today);
  }

  selectMiniCalendarDay(date: Date): void {
    this.activeDate.set(date);
    this.selectedSlot.set(null);
    this.loadForDate(date);
  }

  private loadForDate(date: Date): void {
    this.reservasService.loadReservas(this.toDateStr(date)).subscribe();
  }

  // ── Filtros ──
  toggleCategory(cat: string): void {
    this.selectedCategories.update((prev) =>
      prev.includes(cat) ? prev.filter((c) => c !== cat) : [...prev, cat]
    );
    this.selectedSlot.set(null);
  }

  isCategorySelected(cat: string): boolean {
    return this.selectedCategories().includes(cat);
  }

  onSearch(event: Event): void {
    this.searchQuery.set((event.target as HTMLInputElement).value);
  }

  // ── Slots ──
  isSlotOccupied(resourceName: string, time: string): boolean {
    return this.reservasService.isOccupied(resourceName, this.activeDateStr(), time);
  }

  getReservaForSlot(resourceName: string, time: string) {
    return this.reservasService.reservas().find(
      (r) => r.resourceName === resourceName && r.date === this.activeDateStr() && r.startTime === time
    );
  }

  onSlotClick(resource: Resource, time: string): void {
    if (this.isSlotOccupied(resource.name, time)) return;
    const today = new Date();
    today.setHours(0, 0, 0, 0);
    const selected = new Date(this.activeDate());
    selected.setHours(0, 0, 0, 0);
    if (selected < today) return; // no permitir reservar en el pasado
    this.confirmError.set(null);
    this.confirmSuccess.set(false);
    this.selectedSlot.set({ resource, time });
  }

  // ── Guardar reserva en Supabase ──
  confirmReserva(): void {
    const slot = this.selectedSlot();
    if (!slot) return;

    this.confirmLoading.set(true);
    this.confirmError.set(null);
    this.confirmSuccess.set(false);

    const endTime = this.getEndTime(slot.time);

    this.reservasService.create({
      resourceId: slot.resource.id,
      resourceName: slot.resource.name,
      date: this.activeDateStr(),
      startTime: slot.time,
      endTime,
      author: 'Jessica Orozco',
    }).subscribe({
      next: () => {
        this.confirmLoading.set(false);
        this.confirmSuccess.set(true);
        setTimeout(() => {
          this.selectedSlot.set(null);
          this.confirmSuccess.set(false);
        }, 1200);
      },
      error: (err) => {
        this.confirmLoading.set(false);
        if (err.status === 409) {
          this.confirmError.set('Este espacio ya está reservado para ese horario.');
        } else {
          this.confirmError.set('Error al conectar con el servidor.');
        }
      }
    });
  }

  closePopup(): void {
    this.selectedSlot.set(null);
    this.confirmError.set(null);
    this.confirmSuccess.set(false);
  }

  // ── Utilidades ──
  getEndTime(startTime: string): string {
    const [h, m] = startTime.split(':').map(Number);
    const end = new Date(0, 0, 0, h + 1, m);
    return `${String(end.getHours()).padStart(2, '0')}:${String(end.getMinutes()).padStart(2, '0')}`;
  }

  private toDateStr(date: Date): string {
    return date.toISOString().split('T')[0];
  }

  /** Devuelve el día dado, o el próximo lunes si es fin de semana */
  private getNextWeekday(date: Date): Date {
    const d = new Date(date);
    const day = d.getDay();
    if (day === 0) d.setDate(d.getDate() + 1); // domingo → lunes
    if (day === 6) d.setDate(d.getDate() + 2); // sábado → lunes
    return d;
  }

  navigateToNuevo(): void {
    const slot = this.selectedSlot();
    this.router.navigate(['/reservas/nuevo'], {
      queryParams: {
        fecha: this.activeDateStr(),
        tipo: slot ? (slot.resource.type === 'Sala Reuniones' ? 'room' : 'desk') : 'room',
        hora: slot ? slot.time : '10:00'
      }
    });
  }
}
