/**
 * WhatsApp Automation Service
 * Service for managing automation rules
 *
 * @module WhatsApp
 */

import { Repository, FindOptionsWhere } from 'typeorm';
import { AppDataSource } from '../../../shared/database/typeorm.config';
import { WhatsAppAutomation, AutomationTriggerType, AutomationActionType } from '../entities';
import { ServiceContext } from './account.service';

export interface CreateAutomationDto {
  accountId: string;
  name: string;
  description?: string;
  triggerType: AutomationTriggerType;
  triggerConfig: Record<string, any>;
  actionType: AutomationActionType;
  actionConfig: Record<string, any>;
  conditions?: Record<string, any>[];
  priority?: number;
}

export interface UpdateAutomationDto {
  name?: string;
  description?: string;
  triggerType?: AutomationTriggerType;
  triggerConfig?: Record<string, any>;
  actionType?: AutomationActionType;
  actionConfig?: Record<string, any>;
  conditions?: Record<string, any>[];
  isActive?: boolean;
  priority?: number;
}

export interface AutomationFilters {
  accountId?: string;
  triggerType?: AutomationTriggerType;
  actionType?: AutomationActionType;
  isActive?: boolean;
}

export interface AutomationContext {
  accountId: string;
  contactId: string;
  conversationId?: string;
  message?: {
    content?: string;
    messageType: string;
  };
  isFirstMessage?: boolean;
  isAfterHours?: boolean;
}

export class WhatsAppAutomationService {
  private repository: Repository<WhatsAppAutomation>;

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

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

    if (filters?.accountId) {
      where.accountId = filters.accountId;
    }
    if (filters?.triggerType) {
      where.triggerType = filters.triggerType;
    }
    if (filters?.actionType) {
      where.actionType = filters.actionType;
    }
    if (filters?.isActive !== undefined) {
      where.isActive = filters.isActive;
    }

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

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

  async findActive(ctx: ServiceContext, accountId?: string): Promise<WhatsAppAutomation[]> {
    const where: FindOptionsWhere<WhatsAppAutomation> = {
      tenantId: ctx.tenantId,
      isActive: true,
    };

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

    return this.repository.find({
      where,
      order: { priority: 'DESC' },
    });
  }

  async findByTriggerType(
    ctx: ServiceContext,
    triggerType: AutomationTriggerType,
    accountId?: string
  ): Promise<WhatsAppAutomation[]> {
    const where: FindOptionsWhere<WhatsAppAutomation> = {
      tenantId: ctx.tenantId,
      triggerType,
      isActive: true,
    };

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

    return this.repository.find({
      where,
      order: { priority: 'DESC' },
    });
  }

  async create(ctx: ServiceContext, data: CreateAutomationDto): Promise<WhatsAppAutomation> {
    const automation = this.repository.create({
      ...data,
      tenantId: ctx.tenantId,
      createdBy: ctx.userId,
      isActive: true,
      priority: data.priority ?? 0,
    });

    return this.repository.save(automation);
  }

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

    Object.assign(automation, data);
    return this.repository.save(automation);
  }

  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 activate(ctx: ServiceContext, id: string): Promise<WhatsAppAutomation | null> {
    return this.update(ctx, id, { isActive: true });
  }

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

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

  async findMatchingAutomations(
    ctx: ServiceContext,
    context: AutomationContext
  ): Promise<WhatsAppAutomation[]> {
    const automations = await this.findActive(ctx, context.accountId);
    const matching: WhatsAppAutomation[] = [];

    for (const automation of automations) {
      if (this.matchesTrigger(automation, context) && this.matchesConditions(automation, context)) {
        matching.push(automation);
      }
    }

    return matching.sort((a, b) => b.priority - a.priority);
  }

  private matchesTrigger(automation: WhatsAppAutomation, context: AutomationContext): boolean {
    switch (automation.triggerType) {
      case 'keyword':
        const keywords = automation.triggerConfig.keywords as string[] || [];
        const content = context.message?.content?.toLowerCase() || '';
        return keywords.some(kw => content.includes(kw.toLowerCase()));

      case 'first_message':
        return context.isFirstMessage === true;

      case 'after_hours':
        return context.isAfterHours === true;

      case 'no_response':
        // Would require external timer/scheduler to track no response
        return false;

      case 'webhook':
        return false;

      default:
        return false;
    }
  }

  private matchesConditions(automation: WhatsAppAutomation, context: AutomationContext): boolean {
    if (!automation.conditions || automation.conditions.length === 0) {
      return true;
    }

    return automation.conditions.every(condition => {
      const field = condition.field as string;
      const operator = condition.operator as string;
      const value = condition.value;

      let actualValue: any;
      switch (field) {
        case 'messageType':
          actualValue = context.message?.messageType;
          break;
        case 'content':
          actualValue = context.message?.content;
          break;
        default:
          return true;
      }

      switch (operator) {
        case 'equals':
          return actualValue === value;
        case 'contains':
          return typeof actualValue === 'string' && actualValue.includes(value);
        case 'startsWith':
          return typeof actualValue === 'string' && actualValue.startsWith(value);
        case 'endsWith':
          return typeof actualValue === 'string' && actualValue.endsWith(value);
        case 'regex':
          return typeof actualValue === 'string' && new RegExp(value).test(actualValue);
        default:
          return true;
      }
    });
  }

  async getAction(automation: WhatsAppAutomation): Promise<{
    type: AutomationActionType;
    config: Record<string, any>;
  }> {
    return {
      type: automation.actionType,
      config: automation.actionConfig,
    };
  }

  async getStatistics(ctx: ServiceContext, accountId?: string): Promise<{
    total: number;
    active: number;
    inactive: number;
    byTriggerType: Record<AutomationTriggerType, number>;
    byActionType: Record<AutomationActionType, number>;
    totalTriggers: number;
  }> {
    const where: FindOptionsWhere<WhatsAppAutomation> = { tenantId: ctx.tenantId };
    if (accountId) {
      where.accountId = accountId;
    }

    const automations = await this.repository.find({ where });

    const byTriggerType: Record<string, number> = {};
    const byActionType: Record<string, number> = {};
    let totalTriggers = 0;

    automations.forEach(a => {
      byTriggerType[a.triggerType] = (byTriggerType[a.triggerType] || 0) + 1;
      byActionType[a.actionType] = (byActionType[a.actionType] || 0) + 1;
      totalTriggers += a.triggerCount;
    });

    return {
      total: automations.length,
      active: automations.filter(a => a.isActive).length,
      inactive: automations.filter(a => !a.isActive).length,
      byTriggerType: byTriggerType as Record<AutomationTriggerType, number>,
      byActionType: byActionType as Record<AutomationActionType, number>,
      totalTriggers,
    };
  }

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

    const newAutomation = this.repository.create({
      tenantId: ctx.tenantId,
      accountId: automation.accountId,
      name: newName,
      description: automation.description,
      triggerType: automation.triggerType,
      triggerConfig: automation.triggerConfig,
      actionType: automation.actionType,
      actionConfig: automation.actionConfig,
      conditions: automation.conditions,
      priority: automation.priority,
      isActive: false,
      createdBy: ctx.userId,
    });

    return this.repository.save(newAutomation);
  }

  async reorder(ctx: ServiceContext, automationIds: string[]): Promise<void> {
    for (let i = 0; i < automationIds.length; i++) {
      await this.repository.update(
        { id: automationIds[i], tenantId: ctx.tenantId },
        { priority: automationIds.length - i }
      );
    }
  }
}
