import { ResourceScheduleService } from '../../storage/schedules/ResourceScheduleService';
import { DateService } from '../../core/DateService';
import { IGridConfig } from '../../core/IGridConfig';
import { ITimeSlot } from '../../types/ScheduleTypes';

/**
 * ScheduleRenderer - Renders unavailable time zones in day columns
 *
 * Creates visual indicators for times outside the resource's working hours:
 * - Before work start (e.g., 06:00 - 09:00)
 * - After work end (e.g., 17:00 - 18:00)
 * - Full day if resource is off (schedule = null)
 */
export class ScheduleRenderer {
  constructor(
    private scheduleService: ResourceScheduleService,
    private dateService: DateService,
    private gridConfig: IGridConfig
  ) {}

  /**
   * Render unavailable zones for visible columns
   * @param container - Calendar container element
   * @param filter - Filter with 'date' and 'resource' arrays
   */
  async render(container: HTMLElement, filter: Record<string, string[]>): Promise<void> {
    const dates = filter['date'] || [];
    const resourceIds = filter['resource'] || [];

    if (dates.length === 0) return;

    // Find day columns
    const dayColumns = container.querySelector('swp-day-columns');
    if (!dayColumns) return;

    const columns = dayColumns.querySelectorAll('swp-day-column');

    for (const column of columns) {
      const date = (column as HTMLElement).dataset.date;
      const resourceId = (column as HTMLElement).dataset.resourceId;

      if (!date || !resourceId) continue;

      // Get or create unavailable layer
      let unavailableLayer = column.querySelector('swp-unavailable-layer');
      if (!unavailableLayer) {
        unavailableLayer = document.createElement('swp-unavailable-layer');
        column.insertBefore(unavailableLayer, column.firstChild);
      }

      // Clear existing
      unavailableLayer.innerHTML = '';

      // Get schedule for this resource/date
      const schedule = await this.scheduleService.getScheduleForDate(resourceId, date);

      // Render unavailable zones
      this.renderUnavailableZones(unavailableLayer as HTMLElement, schedule);
    }
  }

  /**
   * Render unavailable time zones based on schedule
   */
  private renderUnavailableZones(layer: HTMLElement, schedule: ITimeSlot | null): void {
    const dayStartMinutes = this.gridConfig.dayStartHour * 60;
    const dayEndMinutes = this.gridConfig.dayEndHour * 60;
    const minuteHeight = this.gridConfig.hourHeight / 60;

    if (schedule === null) {
      // Full day unavailable
      const zone = this.createUnavailableZone(0, (dayEndMinutes - dayStartMinutes) * minuteHeight);
      layer.appendChild(zone);
      return;
    }

    const workStartMinutes = this.dateService.timeToMinutes(schedule.start);
    const workEndMinutes = this.dateService.timeToMinutes(schedule.end);

    // Before work start
    if (workStartMinutes > dayStartMinutes) {
      const top = 0;
      const height = (workStartMinutes - dayStartMinutes) * minuteHeight;
      const zone = this.createUnavailableZone(top, height);
      layer.appendChild(zone);
    }

    // After work end
    if (workEndMinutes < dayEndMinutes) {
      const top = (workEndMinutes - dayStartMinutes) * minuteHeight;
      const height = (dayEndMinutes - workEndMinutes) * minuteHeight;
      const zone = this.createUnavailableZone(top, height);
      layer.appendChild(zone);
    }
  }

  /**
   * Create an unavailable zone element
   */
  private createUnavailableZone(top: number, height: number): HTMLElement {
    const zone = document.createElement('swp-unavailable-zone');
    zone.style.top = `${top}px`;
    zone.style.height = `${height}px`;
    return zone;
  }
}
