/**
 * Voice Agent Configuration API
 *
 * GET /api/voice-agent/config - Get current configuration
 * PUT /api/voice-agent/config - Update configuration
 * DELETE /api/voice-agent/config - Delete agent
 */

import { NextRequest, NextResponse } from "next/server";
import { auth } from "@/lib/auth";
import { logger } from "@/lib/logger";
import { elevenLabsService } from "@/lib/services/elevenlabs.service";
import { prisma } from "@/lib/db";
import { updateAgentConfigSchema } from "@/lib/validators/voice-agent.validator";
import { VoiceAgentConfig } from "@/lib/types/voice-agent.types";
import { z } from "zod";
import { getErrorMessage } from "@/lib/errors";
import { withSecureRoute } from "@/lib/api-security";
import {
  applyRateLimit,
  getClientIdentifier,
  rateLimiters,
} from "@/lib/rate-limiter";
import { createHash } from "crypto";
/**
 * GET /api/voice-agent/config
 * Get current voice agent configuration
 */
export const GET = withSecureRoute(
  async (request: NextRequest) => {
    try {
      const session = await auth();
      if (!session?.user?.email) {
        return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
      }

      const user = await prisma.users.findUnique({
        where: { email: session.user.email },
        select: {
          id: true,
          voiceAgentId: true,
          voiceAgentConfig: true,
        },
      });

      if (!user) {
        return NextResponse.json({ error: "User not found" }, { status: 404 });
      }

      const rateLimitId = user.id
        ? `user:${user.id}`
        : getClientIdentifier(request);
      const rateLimited = await applyRateLimit(
        request,
        rateLimiters.voiceRead,
        rateLimitId,
      );
      if (rateLimited) {
        return rateLimited;
      }

      // Return configuration
      const config = user.voiceAgentConfig || {};
      return NextResponse.json({
        success: true,
        config: {
          agentId: user.voiceAgentId,
          ...(config as Record<string, unknown>),
        },
      });
    } catch (error) {
      logger.error("Error fetching voice agent config", error);
      return NextResponse.json(
        {
          error: "Internal server error",
          message: "Failed to fetch configuration",
        },
        { status: 500 },
      );
    }
  },
  { parseJson: false },
);

/**
 * PUT /api/voice-agent/config
 * Update voice agent configuration
 */
export const PUT = withSecureRoute(
  async (request: NextRequest, _context, body: unknown) => {
    try {
      if (!body) {
        return NextResponse.json(
          { error: "Request body is required" },
          { status: 400 },
        );
      }

      const session = await auth();
      if (!session?.user?.email) {
        return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
      }

      const user = await prisma.users.findUnique({
        where: { email: session.user.email },
        select: {
          id: true,
          voiceAgentId: true,
          voiceAgentConfig: true,
        },
      });

      if (!user) {
        return NextResponse.json({ error: "User not found" }, { status: 404 });
      }

      if (!user.voiceAgentId) {
        return NextResponse.json(
          {
            error: "No agent configured",
            message:
              "You do not have a voice agent. Please provision one first.",
          },
          { status: 404 },
        );
      }

      const rateLimitId = user.id
        ? `user:${user.id}`
        : getClientIdentifier(request);
      const rateLimited = await applyRateLimit(
        request,
        rateLimiters.voiceConfig,
        rateLimitId,
      );
      if (rateLimited) {
        return rateLimited;
      }

      const updates = updateAgentConfigSchema.parse(body);

      logger.info("Updating voice agent configuration", {
        userId: user.id,
        agentId: user.voiceAgentId,
        updates,
      });

      const currentConfig =
        (user.voiceAgentConfig as unknown as VoiceAgentConfig) || {};
      const newConfig: VoiceAgentConfig = {
        ...currentConfig,
        ...updates,
        greetingMessage: {
          ...currentConfig.greetingMessage,
          ...updates.greetingMessage,
        },
        businessHours: updates.businessHours || currentConfig.businessHours,
      };

      const idempotencyKey =
        request.headers.get("idempotency-key") ||
        `voice-config-${createHash("sha256")
          .update(`${user.id}:${user.voiceAgentId}:${JSON.stringify(updates)}`)
          .digest("hex")}`;

      await elevenLabsService.updateAgentConfig(user.voiceAgentId, newConfig, {
        idempotencyKey,
      });

      await prisma.users.update({
        where: { id: user.id },
        data: {
          voiceAgentConfig: newConfig as unknown,
          updatedAt: new Date(),
        },
      });

      logger.info("Successfully updated voice agent configuration", {
        userId: user.id,
        agentId: user.voiceAgentId,
      });

      return NextResponse.json(
        {
          success: true,
          message: "Configuration updated successfully",
          data: {
            agentId: user.voiceAgentId,
            config: newConfig,
          },
        },
        { status: 200 },
      );
    } catch (error) {
      if (error instanceof z.ZodError) {
        return NextResponse.json(
          {
            error: "Validation error",
            message: "Invalid configuration provided",
            details: error.errors,
          },
          { status: 400 },
        );
      }

      if (error instanceof Error && error.name === "ElevenLabsServiceError") {
        logger.error("ElevenLabs service error during config update", error);
        return NextResponse.json(
          {
            error: "Service error",
            message: getErrorMessage(error),
          },
          { status: 500 },
        );
      }

      logger.error("Error updating voice agent config", error);
      return NextResponse.json(
        {
          error: "Internal server error",
          message: "Failed to update configuration",
        },
        { status: 500 },
      );
    }
  },
);

/**
 * DELETE /api/voice-agent/config
 * Delete voice agent (deprovisioning)
 */
export const DELETE = withSecureRoute(async (request: NextRequest) => {
  try {
    const session = await auth();
    if (!session?.user?.email) {
      return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
    }

    const user = await prisma.users.findUnique({
      where: { email: session.user.email },
      select: {
        id: true,
        voiceAgentId: true,
      },
    });

    if (!user) {
      return NextResponse.json({ error: "User not found" }, { status: 404 });
    }

    const rateLimitId = user.id
      ? `user:${user.id}`
      : getClientIdentifier(request);
    const rateLimited = await applyRateLimit(
      request,
      rateLimiters.voiceConfig,
      rateLimitId,
    );
    if (rateLimited) {
      return rateLimited;
    }

    if (!user.voiceAgentId) {
      return NextResponse.json(
        {
          error: "No agent configured",
          message: "You do not have a voice agent to delete.",
        },
        { status: 404 },
      );
    }

    logger.info("Deleting voice agent", {
      userId: user.id,
      agentId: user.voiceAgentId,
    });

    const idempotencyKey =
      request.headers.get("idempotency-key") ||
      `voice-delete-${createHash("sha256")
        .update(`${user.id}:${user.voiceAgentId}`)
        .digest("hex")}`;

    await elevenLabsService.deleteAgent(user.voiceAgentId, { idempotencyKey });

    await prisma.users.update({
      where: { id: user.id },
      data: {
        voiceAgentId: null,
        voiceAgentConfig: undefined,
        updatedAt: new Date(),
      },
    });

    logger.info("Successfully deleted voice agent", {
      userId: user.id,
      agentId: user.voiceAgentId,
    });

    return NextResponse.json(
      {
        success: true,
        message: "Voice agent deleted successfully",
      },
      { status: 200 },
    );
  } catch (error) {
    if (error instanceof Error && error.name === "ElevenLabsServiceError") {
      logger.error("ElevenLabs service error during agent deletion", error);
      return NextResponse.json(
        {
          error: "Service error",
          message: getErrorMessage(error),
        },
        { status: 500 },
      );
    }

    logger.error("Error deleting voice agent", error);
    return NextResponse.json(
      {
        error: "Internal server error",
        message: "Failed to delete voice agent",
      },
      { status: 500 },
    );
  }
});
