/**
 * WhatsApp Template Service
 * Service for managing WhatsApp message templates
 *
 * @module WhatsApp
 */

import { Repository, FindOptionsWhere } from 'typeorm';
import { AppDataSource } from '../../../shared/database/typeorm.config';
import { WhatsAppTemplate, TemplateCategory, TemplateStatus, HeaderType } from '../entities';
import { ServiceContext } from './account.service';

export interface CreateTemplateDto {
  accountId: string;
  name: string;
  displayName: string;
  description?: string;
  category: TemplateCategory;
  language?: string;
  headerType?: HeaderType;
  headerText?: string;
  headerMediaUrl?: string;
  bodyText: string;
  bodyVariables?: string[];
  footerText?: string;
  buttons?: Record<string, any>[];
}

export interface UpdateTemplateDto {
  displayName?: string;
  description?: string;
  category?: TemplateCategory;
  headerType?: HeaderType;
  headerText?: string;
  headerMediaUrl?: string;
  bodyText?: string;
  bodyVariables?: string[];
  footerText?: string;
  buttons?: Record<string, any>[];
  isActive?: boolean;
}

export interface TemplateFilters {
  accountId?: string;
  category?: TemplateCategory;
  metaStatus?: TemplateStatus;
  isActive?: boolean;
  language?: string;
}

export class WhatsAppTemplateService {
  private repository: Repository<WhatsAppTemplate>;

  constructor() {
    this.repository = AppDataSource.getRepository(WhatsAppTemplate);
  }

  async findAll(ctx: ServiceContext, filters?: TemplateFilters): Promise<WhatsAppTemplate[]> {
    const where: FindOptionsWhere<WhatsAppTemplate> = {
      tenantId: ctx.tenantId,
    };

    if (filters?.accountId) {
      where.accountId = filters.accountId;
    }
    if (filters?.category) {
      where.category = filters.category;
    }
    if (filters?.metaStatus) {
      where.metaStatus = filters.metaStatus;
    }
    if (filters?.isActive !== undefined) {
      where.isActive = filters.isActive;
    }
    if (filters?.language) {
      where.language = filters.language;
    }

    return this.repository.find({
      where,
      relations: ['account'],
      order: { displayName: 'ASC' },
    });
  }

  async findById(ctx: ServiceContext, id: string): Promise<WhatsAppTemplate | null> {
    return this.repository.findOne({
      where: { id, tenantId: ctx.tenantId },
      relations: ['account'],
    });
  }

  async findByName(
    ctx: ServiceContext,
    accountId: string,
    name: string,
    language?: string
  ): Promise<WhatsAppTemplate | null> {
    const where: FindOptionsWhere<WhatsAppTemplate> = {
      tenantId: ctx.tenantId,
      accountId,
      name,
    };

    if (language) {
      where.language = language;
    }

    return this.repository.findOne({ where });
  }

  async findApproved(ctx: ServiceContext, accountId?: string): Promise<WhatsAppTemplate[]> {
    const where: FindOptionsWhere<WhatsAppTemplate> = {
      tenantId: ctx.tenantId,
      metaStatus: 'APPROVED',
      isActive: true,
    };

    if (accountId) {
      where.accountId = accountId;
    }

    return this.repository.find({
      where,
      order: { displayName: 'ASC' },
    });
  }

  async findByCategory(ctx: ServiceContext, category: TemplateCategory): Promise<WhatsAppTemplate[]> {
    return this.repository.find({
      where: {
        tenantId: ctx.tenantId,
        category,
        isActive: true,
      },
      order: { displayName: 'ASC' },
    });
  }

  async create(ctx: ServiceContext, data: CreateTemplateDto): Promise<WhatsAppTemplate> {
    const template = this.repository.create({
      ...data,
      tenantId: ctx.tenantId,
      language: data.language || 'es_MX',
      metaStatus: 'PENDING',
      isActive: true,
    });

    return this.repository.save(template);
  }

  async update(ctx: ServiceContext, id: string, data: UpdateTemplateDto): Promise<WhatsAppTemplate | null> {
    const template = await this.findById(ctx, id);
    if (!template) {
      return null;
    }

    Object.assign(template, data);
    template.version += 1;

    return this.repository.save(template);
  }

  async delete(ctx: ServiceContext, id: string): Promise<boolean> {
    const result = await this.repository.delete({ id, tenantId: ctx.tenantId });
    return result.affected ? result.affected > 0 : false;
  }

  async submit(ctx: ServiceContext, id: string, metaTemplateId: string): Promise<WhatsAppTemplate | null> {
    const template = await this.findById(ctx, id);
    if (!template) {
      return null;
    }

    template.metaTemplateId = metaTemplateId;
    template.metaStatus = 'PENDING';
    template.submittedAt = new Date();

    return this.repository.save(template);
  }

  async updateMetaStatus(
    ctx: ServiceContext,
    id: string,
    status: TemplateStatus,
    rejectionReason?: string
  ): Promise<WhatsAppTemplate | null> {
    const template = await this.findById(ctx, id);
    if (!template) {
      return null;
    }

    template.metaStatus = status;

    if (status === 'APPROVED') {
      template.approvedAt = new Date();
    }

    if (status === 'REJECTED' && rejectionReason) {
      template.rejectionReason = rejectionReason;
    }

    return this.repository.save(template);
  }

  async activate(ctx: ServiceContext, id: string): Promise<WhatsAppTemplate | null> {
    return this.update(ctx, id, { isActive: true });
  }

  async deactivate(ctx: ServiceContext, id: string): Promise<WhatsAppTemplate | null> {
    return this.update(ctx, id, { isActive: false });
  }

  async incrementUsage(ctx: ServiceContext, id: string): Promise<void> {
    await this.repository.increment(
      { id, tenantId: ctx.tenantId },
      'usageCount',
      1
    );
    await this.repository.update(
      { id, tenantId: ctx.tenantId },
      { lastUsedAt: new Date() }
    );
  }

  async renderTemplate(
    ctx: ServiceContext,
    id: string,
    variables: string[]
  ): Promise<{ header?: string; body: string; footer?: string } | null> {
    const template = await this.findById(ctx, id);
    if (!template) {
      return null;
    }

    let body = template.bodyText;
    variables.forEach((value, index) => {
      body = body.replace(`{{${index + 1}}}`, value);
    });

    let header: string | undefined;
    if (template.headerType === 'TEXT' && template.headerText) {
      header = template.headerText;
    }

    return {
      header,
      body,
      footer: template.footerText || undefined,
    };
  }

  async getStatistics(ctx: ServiceContext, accountId?: string): Promise<{
    total: number;
    approved: number;
    pending: number;
    rejected: number;
    byCategory: Record<TemplateCategory, number>;
    mostUsed: Array<{ id: string; name: string; usageCount: number }>;
  }> {
    const where: FindOptionsWhere<WhatsAppTemplate> = { tenantId: ctx.tenantId };
    if (accountId) {
      where.accountId = accountId;
    }

    const templates = await this.repository.find({
      where,
      order: { usageCount: 'DESC' },
    });

    const byCategory: Record<string, number> = {};
    templates.forEach(t => {
      byCategory[t.category] = (byCategory[t.category] || 0) + 1;
    });

    const mostUsed = templates
      .filter(t => t.usageCount > 0)
      .slice(0, 10)
      .map(t => ({
        id: t.id,
        name: t.displayName,
        usageCount: t.usageCount,
      }));

    return {
      total: templates.length,
      approved: templates.filter(t => t.metaStatus === 'APPROVED').length,
      pending: templates.filter(t => t.metaStatus === 'PENDING').length,
      rejected: templates.filter(t => t.metaStatus === 'REJECTED').length,
      byCategory: byCategory as Record<TemplateCategory, number>,
      mostUsed,
    };
  }

  async duplicate(
    ctx: ServiceContext,
    id: string,
    newName: string,
    newDisplayName: string
  ): Promise<WhatsAppTemplate | null> {
    const template = await this.findById(ctx, id);
    if (!template) {
      return null;
    }

    const newTemplate = this.repository.create({
      tenantId: ctx.tenantId,
      accountId: template.accountId,
      name: newName,
      displayName: newDisplayName,
      description: template.description,
      category: template.category,
      language: template.language,
      headerType: template.headerType,
      headerText: template.headerText,
      headerMediaUrl: template.headerMediaUrl,
      bodyText: template.bodyText,
      bodyVariables: template.bodyVariables,
      footerText: template.footerText,
      buttons: template.buttons,
      metaStatus: 'PENDING',
      isActive: false,
    });

    return this.repository.save(newTemplate);
  }
}
