import { Injectable, OnModuleInit } from '@nestjs/common';
import * as fs from 'fs';
import * as path from 'path';
import Handlebars from 'handlebars';

import { ContractViewModel } from './contract-view-model.builder';

@Injectable()
export class ContractRendererService implements OnModuleInit {
  private readonly templatesDir = path.join(__dirname, 'templates');
  private readonly compiled = new Map<string, Handlebars.TemplateDelegate>();

  onModuleInit(): void {
    Handlebars.registerHelper('eq', (a: unknown, b: unknown) => a === b);

    const partialsDir = path.join(this.templatesDir, '_partials');
    if (fs.existsSync(partialsDir)) {
      for (const file of fs.readdirSync(partialsDir)) {
        if (!file.endsWith('.hbs')) continue;
        const name = file.replace(/\.hbs$/, '');
        const content = fs.readFileSync(path.join(partialsDir, file), 'utf-8');
        Handlebars.registerPartial(name, content);
      }
    }
  }

  render(view: ContractViewModel): string {
    const fileName =
      view.template.templateFile ?? 'generic.hbs';
    const template = this.getCompiled(fileName);
    return template({
      ...view,
      paymentArticle: view.pricing.currency === 'ETB' ? 'ETB' : 'USD',
    });
  }

  private getCompiled(fileName: string): Handlebars.TemplateDelegate {
    const cached = this.compiled.get(fileName);
    if (cached) return cached;

    const filePath = path.join(this.templatesDir, fileName);
    const fallbackPath = path.join(this.templatesDir, 'generic.hbs');
    const source = fs.existsSync(filePath)
      ? fs.readFileSync(filePath, 'utf-8')
      : fs.readFileSync(fallbackPath, 'utf-8');

    const compiled = Handlebars.compile(source);
    this.compiled.set(fileName, compiled);
    return compiled;
  }
}
