import { NextRequest, NextResponse } from "next/server";
import { auth } from "@/lib/auth";
import { db } from "@/lib/db";
import { logger } from "@/lib/logger";
import { dispatchFleetAction } from "@/lib/token/agents/fleet-manager";

/**
 * GET /api/token/actions — List fleet actions (optionally by conversationId).
 * POST /api/token/actions — Create fleet actions from proposals.
 * PATCH /api/token/actions — Approve/reject an action (triggers dispatch on approval).
 */

export async function GET(req: NextRequest) {
  const session = await auth();
  if (!session?.user?.id) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  const conversationId = req.nextUrl.searchParams.get("conversationId");
  const status = req.nextUrl.searchParams.get("status");

  const where: Record<string, unknown> = {
    conversation: { userId: session.user.id },
  };
  if (conversationId) where.conversationId = conversationId;
  if (status) where.status = status;

  try {
    const actions = await db.tokenFleetAction.findMany({
      where,
      orderBy: { createdAt: "desc" },
      take: 50,
    });

    return NextResponse.json({ actions });
  } catch (err) {
    logger.error({ err, action: "token_actions_list_error" }, "Failed to list fleet actions");
    return NextResponse.json({ error: "Failed to list actions" }, { status: 500 });
  }
}

export async function POST(req: NextRequest) {
  const session = await auth();
  if (!session?.user?.id) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  try {
    const body = await req.json();
    const { conversationId, messageId, actions } = body;

    if (!conversationId || !Array.isArray(actions) || actions.length === 0) {
      return NextResponse.json(
        { error: "conversationId and actions array required" },
        { status: 400 },
      );
    }

    // Verify conversation ownership
    const conversation = await db.tokenConversation.findFirst({
      where: { id: conversationId, userId: session.user.id },
    });
    if (!conversation) {
      return NextResponse.json({ error: "Conversation not found" }, { status: 404 });
    }

    // Validate actions (max 5)
    const validTypes = ["pull_model", "remove_model", "restart_engine"];
    const validActions = actions
      .slice(0, 5)
      .filter(
        (a: { type: string; deviceId: string }) =>
          validTypes.includes(a.type) && a.deviceId,
      );

    if (validActions.length === 0) {
      return NextResponse.json({ error: "No valid actions provided" }, { status: 400 });
    }

    // Create all actions
    const created = await Promise.all(
      validActions.map(
        (a: { type: string; deviceId: string; payload?: Record<string, string> }) =>
          db.tokenFleetAction.create({
            data: {
              conversationId,
              messageId: messageId ?? null,
              deviceId: a.deviceId,
              type: a.type,
              payload: JSON.stringify(a.payload ?? {}),
              status: "pending",
            },
          }),
      ),
    );

    logger.info(
      { action: "token_actions_created", count: created.length, conversationId },
      "Fleet actions created",
    );

    return NextResponse.json({ actions: created }, { status: 201 });
  } catch (err) {
    logger.error(
      { err, action: "token_actions_create_error" },
      "Failed to create fleet actions",
    );
    return NextResponse.json({ error: "Failed to create actions" }, { status: 500 });
  }
}

export async function PATCH(req: NextRequest) {
  const session = await auth();
  if (!session?.user?.id) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  try {
    const body = await req.json();
    const { actionId, status: newStatus } = body;

    if (!actionId || !newStatus) {
      return NextResponse.json(
        { error: "actionId and status required" },
        { status: 400 },
      );
    }

    const validStatuses = ["approved", "rejected"];
    if (!validStatuses.includes(newStatus)) {
      return NextResponse.json(
        { error: "status must be 'approved' or 'rejected'" },
        { status: 400 },
      );
    }

    // Find the action and verify ownership
    const fleetAction = await db.tokenFleetAction.findFirst({
      where: {
        id: actionId,
        conversation: { userId: session.user.id },
        status: "pending",
      },
    });

    if (!fleetAction) {
      return NextResponse.json(
        { error: "Action not found or not pending" },
        { status: 404 },
      );
    }

    if (newStatus === "rejected") {
      const updated = await db.tokenFleetAction.update({
        where: { id: actionId },
        data: { status: "rejected" },
      });
      return NextResponse.json({ action: updated });
    }

    // Approved — dispatch to device
    await db.tokenFleetAction.update({
      where: { id: actionId },
      data: { status: "in_progress" },
    });

    // Look up device for tunnel URL
    const device = await db.device.findFirst({
      where: { id: fleetAction.deviceId, userId: session.user.id },
    });

    if (!device) {
      await db.tokenFleetAction.update({
        where: { id: actionId },
        data: {
          status: "failed",
          result: JSON.stringify({ error: "Device not found" }),
        },
      });
      return NextResponse.json({ error: "Device not found" }, { status: 404 });
    }

    if (device.status !== "online") {
      await db.tokenFleetAction.update({
        where: { id: actionId },
        data: {
          status: "failed",
          result: JSON.stringify({ error: "Device is offline" }),
        },
      });
      return NextResponse.json({ error: "Device is offline" }, { status: 409 });
    }

    // Dispatch the action
    const payload = JSON.parse(fleetAction.payload) as Record<string, string>;
    const dispatchResult = await dispatchFleetAction(
      device.tunnelUrl,
      fleetAction.type,
      payload,
    );

    const finalStatus = dispatchResult.success ? "success" : "failed";
    const updated = await db.tokenFleetAction.update({
      where: { id: actionId },
      data: {
        status: finalStatus,
        result: JSON.stringify(dispatchResult),
      },
    });

    logger.info(
      {
        action: "token_fleet_dispatch",
        actionId,
        type: fleetAction.type,
        deviceId: fleetAction.deviceId,
        success: dispatchResult.success,
      },
      "Fleet action dispatched",
    );

    return NextResponse.json({ action: updated });
  } catch (err) {
    logger.error(
      { err, action: "token_actions_patch_error" },
      "Failed to update fleet action",
    );
    return NextResponse.json({ error: "Failed to update action" }, { status: 500 });
  }
}
