import { IRenderer, IRenderContext } from './IGroupingRenderer';

/**
 * Entity must have id
 */
export interface IGroupingEntity {
  id: string;
}

/**
 * Configuration for a grouping renderer
 */
export interface IGroupingRendererConfig {
  elementTag: string;      // e.g., 'swp-team-header'
  idAttribute: string;     // e.g., 'teamId' -> data-team-id
  colspanVar: string;      // e.g., '--team-cols'
}

/**
 * Abstract base class for grouping renderers
 *
 * Handles:
 * - Fetching entities by IDs
 * - Calculating colspan from parentChildMap
 * - Creating header elements
 * - Appending to container
 *
 * Subclasses override:
 * - renderHeader() for custom content
 * - getDisplayName() for entity display text
 */
export abstract class BaseGroupingRenderer<T extends IGroupingEntity> implements IRenderer {
  abstract readonly type: string;
  protected abstract readonly config: IGroupingRendererConfig;

  /**
   * Fetch entities from service
   */
  protected abstract getEntities(ids: string[]): Promise<T[]>;

  /**
   * Get display name for entity
   */
  protected abstract getDisplayName(entity: T): string;

  /**
   * Main render method - handles common logic
   */
  async render(context: IRenderContext): Promise<void> {
    const allowedIds = context.filter[this.type] || [];
    if (allowedIds.length === 0) return;

    const entities = await this.getEntities(allowedIds);
    const dateCount = context.filter['date']?.length || 1;
    const childIds = context.childType ? context.filter[context.childType] || [] : [];

    for (const entity of entities) {
      const entityChildIds = context.parentChildMap?.[entity.id] || [];
      const childCount = entityChildIds.filter(id => childIds.includes(id)).length;
      const colspan = childCount * dateCount;

      const header = document.createElement(this.config.elementTag);
      header.dataset[this.config.idAttribute] = entity.id;
      header.style.setProperty(this.config.colspanVar, String(colspan));

      // Allow subclass to customize header content
      this.renderHeader(entity, header, context);

      context.headerContainer.appendChild(header);
    }
  }

  /**
   * Override this method for custom header rendering
   * Default: just sets textContent to display name
   */
  protected renderHeader(entity: T, header: HTMLElement, _context: IRenderContext): void {
    header.textContent = this.getDisplayName(entity);
  }

  /**
   * Helper to render a single entity header.
   * Can be used by subclasses that override render() but want consistent header creation.
   */
  protected createHeader(entity: T, context: IRenderContext): HTMLElement {
    const header = document.createElement(this.config.elementTag);
    header.dataset[this.config.idAttribute] = entity.id;
    this.renderHeader(entity, header, context);
    return header;
  }
}
