import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository, InjectDataSource } from '@nestjs/typeorm';
import { Repository, DataSource } from 'typeorm';
import { TemplateContent } from './entities/template_content.entity';
import { CreateTemplateContentDto } from './dto/create-template_content.dto';
import { UpdateTemplateContentDto } from './dto/update-template_content.dto';

@Injectable()
export class TemplateContentService {
  constructor(
    @InjectRepository(TemplateContent, 'certification_db')
    private readonly templateContentRepository: Repository<TemplateContent>,
    @InjectDataSource('certification_db')
    private readonly dataSource: DataSource,
  ) {}

  async create(dto: CreateTemplateContentDto) {
    return await this.dataSource.transaction(async (manager) => {
      const content = manager.create(TemplateContent, {
        template_id: dto.template_id,
        title: dto.title,
        content: dto.content,
        // audit_time: dto.audit_time,
        startTime: dto.startTime,
        endTime: dto.endTime,
        functional_area: dto.functional_area,
        created_by: dto.created_by ?? undefined,
      });
      return await manager.save(content);
    });
  }

  async createMany(dtoArray: CreateTemplateContentDto[]) {
    if (!dtoArray || dtoArray.length === 0)
      throw new NotFoundException('No contents provided');

    return await this.dataSource.transaction(async (manager) => {
      const contents = dtoArray.map((dto) =>
        manager.create(TemplateContent, {
          template_id: dto.template_id,
          title: dto.title,
          content: dto.content,
          // audit_time: dto.audit_time,
          startTime: dto.startTime, // new field
          endTime: dto.endTime, // new field
          functional_area: dto.functional_area,
          created_by: dto.created_by ?? undefined,
        }),
      );
      return await manager.save(contents);
    });
  }

  async findAll(templateId?: number) {
    const query = this.templateContentRepository
      .createQueryBuilder('content')
      .leftJoinAndSelect('content.template', 'template');

    if (templateId) {
      query.where('content.template_id = :templateId', { templateId });
    }

    query.orderBy('content.startTime', 'ASC');

    const contents = await query.getMany();
    if (!contents.length) return [];

    const grouped = contents.reduce(
      (acc, item) => {
        const tId = item.template_id;

        if (!acc[tId]) {
          acc[tId] = {
            template_id: tId,
            template_name: item.template?.name || 'Unknown Template',
            schedule: {},
          };
        }

        const schedule = acc[tId].schedule;
        const timeSlot = `${item.startTime || ''} - ${item.endTime || ''}`;

        if (!schedule[timeSlot]) {
          schedule[timeSlot] = [];
        }

        schedule[timeSlot].push({
          id: item.id,
          title: item.title,
          content: item.content,
          startTime: item.startTime, // include startTime
          endTime: item.endTime, // include endTime
          functional_area: item.functional_area,
          created_by: item.created_by,
          created_at: item.created_at,
          updated_at: item.updated_at,
        });

        return acc;
      },
      {} as Record<number, any>,
    );

    return Object.values(grouped).filter(
      (item) => item && Object.keys(item).length > 0,
    );
  }

  async findOne(id: number) {
    const content = await this.templateContentRepository.findOne({
      where: { id },
    });
    if (!content) throw new NotFoundException('Template content not found');
    return content;
  }

  async update(id: number, dto: UpdateTemplateContentDto) {
    return await this.dataSource.transaction(async (manager) => {
      const content = await manager.findOne(TemplateContent, { where: { id } });
      if (!content) throw new NotFoundException('Template content not found');
      Object.assign(content, dto);
      return await manager.save(content);
    });
  }

  async remove(id: number) {
    const result = await this.templateContentRepository.delete(id);
    if (result.affected === 0)
      throw new NotFoundException('Template content not found');
    return { message: 'Template content deleted successfully' };
  }

  async findByTemplate(templateId: number, title?: string) {
    const query = this.templateContentRepository
      .createQueryBuilder('content')
      .where('content.template_id = :templateId', { templateId });
    if (title) query.andWhere('content.title = :title', { title });
    return query.orderBy('content.created_at', 'DESC').getMany();
  }

  async getTemplateSchedule(templateId: number) {
    const contents = await this.findByTemplate(templateId);
    console.log('📌 Fetched template contents:', contents); // Check raw DB data

    if (contents.length === 0) {
      console.log('⚠️ No content found for this template');
      throw new NotFoundException('No content found for this template');
    }

    const templateTitle = contents[0].title;
    console.log('📌 Template Title:', templateTitle);

    const scheduleArray = contents.reduce(
      (acc, item) => {
        const timeSlot = `${item.startTime || ''} - ${item.endTime || ''}`;
        console.log('📌 Processing timeslot:', timeSlot, 'Item:', item);

        acc.push({
          timeSlot,
          items: [
            {
              id: item.id,
              title: item.title,
              content: item.content,
              startTime: item.startTime,
              endTime: item.endTime,
              functional_area: item.functional_area,
              created_by: item.created_by,
              created_at: item.created_at,
              updated_at: item.updated_at,
            },
          ],
        });

        return acc;
      },
      [] as Array<{ timeSlot: string; items: any[] }>,
    );

    console.log('📌 Schedule Array for Handlebars:', scheduleArray);

    return {
      template_id: templateId,
      template_title: templateTitle,
      templateContent: scheduleArray,
    };
  }
  async getTemplateScheduleByTime(
    templateId: number,
    startTime: string,
    endTime: string,
  ) {
    const contents = await this.templateContentRepository.find({
      where: {
        template_id: templateId,
        startTime,
        endTime,
      },
      order: { created_at: 'ASC' },
    });

    if (!contents.length) {
      throw new NotFoundException('No content found for this time slot');
    }

    return {
      template_id: templateId,
      template_name: contents[0]?.template?.name ?? '',
      schedule: {
        [`${startTime} - ${endTime}`]: contents.map((item) => ({
          id: item.id,
          title: item.title,
          content: item.content,
          startTime: item.startTime,
          endTime: item.endTime,
          functional_area: item.functional_area,
        })),
      },
    };
  }
}
