import { Injectable } from '@nestjs/common';
import { Prisma } from '@prisma/client';
import { AuthenticatedUser } from '../auth/auth.types';
import { getAppConfig } from '../config/env';
import { JobsService } from '../jobs/jobs.service';
import { PrismaService } from '../prisma/prisma.service';
import { TestWhatsappConfigDto } from './dto/test-whatsapp-config.dto';
import { UpdateWhatsappConfigDto } from './dto/update-whatsapp-config.dto';
import {
  defaultWhatsappSubscriptions,
  whatsappSubscriptionOptions,
} from './whatsapp-subscriptions';

@Injectable()
export class IntegrationsService {
  constructor(
    private readonly prisma: PrismaService,
    private readonly jobsService: JobsService,
  ) {}

  getWhatsappSettings() {
    const config = getAppConfig();
    return this.prisma.integrationConfig
      .findUnique({
        where: { configKey: 'whatsapp' },
      })
      .then((storedConfig) => {
        const configJson = (storedConfig?.configJson as Record<string, unknown> | null) ?? {};

        return {
          provider: String(configJson.provider || storedConfig?.provider || 'meta'),
          webhookUrl: `${config.publicApiUrl.replace(/\/$/, '')}/api/webhooks/whatsapp`,
          verifyToken: String(configJson.webhookVerifyToken || config.webhookVerifyToken),
          status: storedConfig ? (storedConfig.isEnabled ? 'configured' : 'disabled') : 'not-configured',
          hasSharedSecret: Boolean(configJson.sharedSecret || config.webhookSharedSecret),
          hasAppSecret: Boolean(configJson.appSecret || config.metaWebhookAppSecret),
          hasAccessToken: Boolean(configJson.accessToken),
          phoneNumberId: typeof configJson.phoneNumberId === 'string' ? configJson.phoneNumberId : '',
          isEnabled: storedConfig?.isEnabled ?? true,
          subscriptions: Array.isArray(configJson.subscriptions)
            ? configJson.subscriptions
            : defaultWhatsappSubscriptions,
          availableSubscriptions: whatsappSubscriptionOptions,
        };
      });
  }

  async updateWhatsappSettings(
    dto: UpdateWhatsappConfigDto,
    user: AuthenticatedUser,
    ipAddress?: string,
  ) {
    const actor = await this.prisma.user.findUnique({
      where: { id: user.sub },
      select: { id: true, name: true, email: true },
    });
    const existing = await this.prisma.integrationConfig.findUnique({
      where: { configKey: 'whatsapp' },
    });
    const previous = (existing?.configJson as Record<string, unknown> | null) ?? {};
    const nextConfig = {
      ...previous,
      ...(dto.provider ? { provider: dto.provider } : {}),
      ...(dto.webhookVerifyToken ? { webhookVerifyToken: dto.webhookVerifyToken } : {}),
      ...(dto.sharedSecret ? { sharedSecret: dto.sharedSecret } : {}),
      ...(dto.appSecret !== undefined ? { appSecret: dto.appSecret } : {}),
      ...(dto.accessToken ? { accessToken: dto.accessToken } : {}),
      ...(dto.phoneNumberId ? { phoneNumberId: dto.phoneNumberId } : {}),
      ...(dto.subscriptions ? { subscriptions: dto.subscriptions } : {}),
    };

    const result = await this.prisma.integrationConfig.upsert({
      where: { configKey: 'whatsapp' },
      update: {
        provider: dto.provider || existing?.provider || 'meta',
        isEnabled: dto.isEnabled ?? existing?.isEnabled ?? true,
        configJson: nextConfig as Prisma.InputJsonValue,
      },
      create: {
        configKey: 'whatsapp',
        provider: dto.provider || 'meta',
        isEnabled: dto.isEnabled ?? true,
        configJson: nextConfig as Prisma.InputJsonValue,
      },
    });

    await this.prisma.auditLog.create({
      data: {
        actorUserId: actor?.id || user.sub,
        actorName: actor?.name || user.email,
        actorEmail: actor?.email || user.email,
        actionType: 'WhatsApp Settings Updated',
        module: 'Integrations',
        ipAddress: ipAddress || null,
        severity: 'default',
        details: `Updated WhatsApp settings for provider ${result.provider}.`,
        metadataJson: nextConfig as Prisma.InputJsonValue,
      },
    });

    return result;
  }

  async testWhatsappSettings(
    dto: TestWhatsappConfigDto,
    user: AuthenticatedUser,
    ipAddress?: string,
  ) {
    const actor = await this.prisma.user.findUnique({
      where: { id: user.sub },
      select: { id: true, name: true, email: true },
    });
    const provider = dto.provider || 'meta';
    const senderPhone = dto.senderPhone || '6281999000111';
    const eventId = `evt_test_${Date.now()}`;

    await this.prisma.webhookEvent.create({
      data: {
        provider,
        eventId,
        eventType: 'message.inbound',
        senderPhone,
        recipientPhone: 'test-webhook-destination',
        externalMessageId: eventId,
        eventTimestamp: new Date(),
        payloadJson: {
          source: 'integration-test',
          eventId,
          provider,
          senderPhone,
        } as Prisma.InputJsonValue,
        verified: true,
        processingStatus: 'queued',
        processingNotes: 'Queued from integration test endpoint',
      },
    });

    const job = await this.jobsService.enqueue({
      queueName: 'webhooks',
      jobType: 'webhook.process',
      payload: { eventId },
      maxAttempts: 1,
    });

    await this.prisma.auditLog.create({
      data: {
        actorUserId: actor?.id || user.sub,
        actorName: actor?.name || user.email,
        actorEmail: actor?.email || user.email,
        actionType: 'Webhook Test Queued',
        module: 'Integrations',
        ipAddress: ipAddress || null,
        severity: 'default',
        details: `Queued webhook test ${eventId} for provider ${provider}.`,
        metadataJson: {
          provider,
          eventId,
          senderPhone,
          jobId: job.id,
        } as Prisma.InputJsonValue,
      },
    });

    return {
      provider,
      eventId,
      jobId: job.id,
      status: 'queued',
    };
  }
}
