import { Injectable, NotFoundException, OnModuleInit } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { EmailTemplate } from './email_templates.entity';
import * as path from 'path';
import * as fs from 'fs';

@Injectable()
export class EmailTemplatesService implements OnModuleInit {
  private cache = new Map<string, EmailTemplate>();

  constructor(
    @InjectRepository(EmailTemplate)
    private emailTemplateRepository: Repository<EmailTemplate>,
  ) {}

  async onModuleInit() {
    await this.seedDefaultTemplates();
  }

  private async seedDefaultTemplates() {
    try {
      const jsonPath = path.join(process.cwd(), 'email_templates.json');
      if (fs.existsSync(jsonPath)) {
        const rawData = fs.readFileSync(jsonPath, 'utf8');
        const parsed = JSON.parse(rawData);
        const tableExport = parsed.find(
          (item: any) => item.type === 'table' && item.name === 'email_templates',
        );
        if (tableExport && Array.isArray(tableExport.data)) {
          for (const item of tableExport.data) {
            let variablesArr: string[] = [];
            if (item.variables) {
              if (typeof item.variables === 'string') {
                try {
                  variablesArr = JSON.parse(item.variables);
                } catch {
                  variablesArr = item.variables.split(',').map((v: string) => v.trim()).filter(Boolean);
                }
              } else if (Array.isArray(item.variables)) {
                variablesArr = item.variables;
              }
            }

            const is_active_bool =
              item.is_active === '1' ||
              item.is_active === 1 ||
              item.is_active === true ||
              item.is_active === 'true';

            const templateData = {
              template_name: item.template_name,
              subject: item.subject,
              body_html: item.body_html,
              variables: variablesArr,
              description: item.description || null,
              language_code: item.language_code || 'en',
              category: item.category || 'transactional',
              recipient: item.recipient || null,
              is_active: is_active_bool,
            };

            const exists = await this.emailTemplateRepository.findOne({
              where: { template_name: templateData.template_name },
            });

            if (!exists) {
              const newTemplate = this.emailTemplateRepository.create(templateData);
              await this.emailTemplateRepository.save(newTemplate);
            } else {
              exists.subject = templateData.subject;
              exists.body_html = templateData.body_html;
              exists.variables = templateData.variables;
              exists.description = templateData.description;
              exists.language_code = templateData.language_code;
              exists.category = templateData.category;
              exists.recipient = templateData.recipient;
              exists.is_active = templateData.is_active;
              await this.emailTemplateRepository.save(exists);
            }
          }
        }
      }
    } catch (err) {
      console.error('Failed to seed templates from email_templates.json:', err);
    }

  }


  async findAllPaginated(page: number, limit: number): Promise<{ data: EmailTemplate[], total: number, page: number, limit: number }> {
    const [data, total] = await this.emailTemplateRepository.findAndCount({
      skip: (page - 1) * limit,
      take: limit,
      order: { created_at: 'DESC' },
    });
    return { data, total, page, limit };
  }

  async findOne(id: string): Promise<EmailTemplate> {
    const template = await this.emailTemplateRepository.findOne({
      where: { id },
    });
    if (!template) {
      throw new NotFoundException(`Email template with ID ${id} not found`);
    }
    return template;
  }

  async findByName(template_name: string): Promise<EmailTemplate | null> {
    if (this.cache.has(template_name)) {
      return this.cache.get(template_name) || null;
    }
    const template = await this.emailTemplateRepository.findOne({
      where: { template_name },
    });
    if (template) {
      this.cache.set(template_name, template);
    }
    return template;
  }

  async create(data: Partial<EmailTemplate>): Promise<EmailTemplate> {
    const newTemplate = this.emailTemplateRepository.create(data);
    const saved = await this.emailTemplateRepository.save(newTemplate);
    this.cache.set(saved.template_name, saved);
    return saved;
  }

  async update(
    id: string,
    data: Partial<EmailTemplate>,
  ): Promise<EmailTemplate> {
    const template = await this.findOne(id);
    Object.assign(template, data);
    const saved = await this.emailTemplateRepository.save(template);
    this.cache.set(saved.template_name, saved);
    return saved;
  }
}
