import { Injectable, BadRequestException, Logger } from '@nestjs/common';
import { EventEmitter2 } from '@nestjs/event-emitter';
import { PrismaService } from '../../prisma/prisma.service';
import {
  AVAILABLE_THEMES,
  DEFAULT_THEME_ID,
  isValidThemeId,
  type ThemeDefinition,
} from './theme-definitions';

export interface ThemeHistoryEntry {
  id: string;
  themeId: string;
  setById: string | null;
  createdAt: Date;
}

@Injectable()
export class ThemesService {
  private readonly logger = new Logger(ThemesService.name);

  constructor(
    private readonly prisma: PrismaService,
    private readonly eventEmitter: EventEmitter2,
  ) {}

  /** Get all available theme definitions */
  getAvailableThemes(): ThemeDefinition[] {
    return AVAILABLE_THEMES;
  }

  /** Get the current active theme ID (falls back to default) */
  async getCurrentThemeId(): Promise<string> {
    await this.prisma.resetTenantId();

    const active = await this.prisma.platformTheme.findFirst({
      orderBy: { createdAt: 'desc' },
    });

    return active?.themeId ?? DEFAULT_THEME_ID;
  }

  /** Get the full current theme response. `isExplicit` = true when set via API. */
  async getCurrent(): Promise<{ themeId: string; theme: ThemeDefinition; isExplicit: boolean }> {
    await this.prisma.resetTenantId();

    const active = await this.prisma.platformTheme.findFirst({
      orderBy: { createdAt: 'desc' },
    });

    const isExplicit = !!active;
    const themeId = active?.themeId ?? DEFAULT_THEME_ID;
    const theme = AVAILABLE_THEMES.find((t) => t.id === themeId) ?? AVAILABLE_THEMES[0]!;

    return { themeId, theme, isExplicit };
  }

  /** Set the active platform theme (superadmin only) */
  async setActive(themeId: string, setById: string): Promise<{ themeId: string; theme: ThemeDefinition }> {
    if (!isValidThemeId(themeId)) {
      throw new BadRequestException(
        `Invalid theme ID "${themeId}". Valid themes: ${AVAILABLE_THEMES.map((t) => t.id).join(', ')}`,
      );
    }

    await this.prisma.resetTenantId();

    // Upsert: we keep a history of theme changes
    await this.prisma.platformTheme.create({
      data: { themeId, setById },
    });

    this.logger.log(`Platform theme changed to "${themeId}" by user ${setById}`);

    // Emit webhook event for cross-service sync
    this.eventEmitter.emit('theme.changed', {
      themeId,
      setById,
      timestamp: new Date().toISOString(),
    });

    const theme = AVAILABLE_THEMES.find((t) => t.id === themeId)!;
    return { themeId, theme };
  }

  /** Get theme change history (audit trail) */
  async getHistory(limit = 20): Promise<ThemeHistoryEntry[]> {
    await this.prisma.resetTenantId();

    return this.prisma.platformTheme.findMany({
      orderBy: { createdAt: 'desc' },
      take: limit,
    });
  }
}
