import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository, InjectDataSource } from '@nestjs/typeorm';
import { Repository, DataSource } from 'typeorm';
import {
  Template,
  AuditStageName,
  TemplateType,
} from './entities/template.entity';
import { CreateTemplateDto } from './dto/create-template.dto';
import { UpdateTemplateDto } from './dto/update-template.dto';

@Injectable()
export class TemplateService {
  [x: string]: any;
  constructor(
    @InjectRepository(Template, 'certification_db')
    private readonly templateRepository: Repository<Template>,

    @InjectDataSource('certification_db')
    private readonly dataSource: DataSource,
  ) {}

  async create(dto: CreateTemplateDto) {
    return await this.dataSource.transaction(async (manager) => {
      const existingTemplates = await manager.find(Template, {
        where: { name: dto.name, stageName: dto.stageName },
        order: { version: 'DESC' },
      });

      let nextVersion = 'v1.0';
      if (existingTemplates.length > 0) {
        const latestVersion = existingTemplates[0].version;
        const parts = latestVersion.replace('v', '').split('.');
        const major = parseInt(parts[0]);
        const minor = parseInt(parts[1]);
        nextVersion = `v${major}.${minor + 1}`;
      }

      const version = dto.version || nextVersion;

      const template = manager.create(Template, {
        name: dto.name,
        stageName: dto.stageName,
        filePath: dto.filePath,
        version,
        createdBy: dto.createdBy ?? undefined,
        templateType: dto.templateType || TemplateType.DOCUMENT, // Add this line
      });

      return await manager.save(template);
    });
  }
  async findByFilePath(filePath: string): Promise<Template | null> {
    return this.templateRepository.findOne({
      where: { filePath, isActive: true },
    });
  }
  // async findAll(stageName?: AuditStageName, companyId?: number) {
  //   const query = this.templateRepository.createQueryBuilder('template');
  //   if (stageName) {
  //     query.where('template.stage_name = :stageName', { stageName });
  //   }
  //   const templates = await query
  //     .orderBy('template.created_at', 'DESC')
  //     .getMany();

  //   // Map each template to include the dynamic PDF URL
  //   // Frontend (TemplateService)
  //   return templates.map((t) => ({
  //     ...t,
  //     url: `/api/pdf/${t.stageName.toLowerCase().replace(' ', '')}/${t.filePath}?companyId=${companyId ?? ''}&templateId=${t.id}`,
  //   }));
  // }
  async findAll(
    stageName?: AuditStageName,
    companyId?: number,
    templateType?: TemplateType, // ✅ new parameter
  ) {
    const query = this.templateRepository.createQueryBuilder('template');

    if (stageName) {
      query.where('template.stage_name = :stageName', { stageName });
    }

    if (templateType) {
      query.andWhere('template.template_type = :templateType', {
        templateType,
      }); // ✅ filter by type
    }

    const templates = await query
      .orderBy('template.created_at', 'DESC')
      .getMany();

    return templates.map((t) => ({
      ...t,
      url: `/api/pdf/${t.stageName.toLowerCase().replace(' ', '')}/${t.filePath}?companyId=${companyId ?? ''}&templateId=${t.id}`,
    }));
  }

  async findOne(id: number, throwIfNotFound = true): Promise<Template | null> {
    const template = await this.templateRepository.findOne({ where: { id } });

    if (!template && throwIfNotFound) {
      throw new NotFoundException('Template not found');
    }

    // Optional: include templateType explicitly in the returned object
    if (template) {
      return {
        ...template,
        templateType: template.templateType, // this ensures templateType is available
        // You can also add URL here if needed like in findAll
      };
    }

    return null;
  }

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

      Object.assign(template, {
        ...dto,
        templateType: dto.templateType ?? template.templateType,
      });

      return await manager.save(template);
    });
  }

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

  async findByNameAndStage(
    name: string,
    stageName: AuditStageName,
    version?: string,
    templateType?: TemplateType, // ✅ new optional param
  ) {
    const query = this.templateRepository
      .createQueryBuilder('template')
      .where('template.name = :name', { name })
      .andWhere('template.stage_name = :stageName', { stageName });

    if (templateType) {
      query.andWhere('template.template_type = :templateType', {
        templateType,
      }); // ✅ filter by type
    }

    if (version) query.andWhere('template.version = :version', { version });
    else query.orderBy('template.created_at', 'DESC').limit(1);

    return query.getOne();
  }
}
