import { type LoaderFunctionArgs } from "@remix-run/node";
import { getIntegrationDefinitionWithId } from "~/services/integrationDefinition.server";
import { runIntegrationTrigger } from "~/services/integration.server";
import { IntegrationEventType } from "@core/types";
import { createMCPAuthClient } from "@core/mcp-proxy";
import { logger } from "~/services/logger.service";
import { env } from "~/env.server";
import { getIntegrationDefinitionForState } from "~/services/oauth/oauth.server";

const MCP_CALLBACK_URL = `${process.env.OAUTH_CALLBACK_URL ?? ""}/mcp`;

export async function loader({ request }: LoaderFunctionArgs) {
  const url = new URL(request.url);
  const authorizationCode = url.searchParams.get("code");
  const state = url.searchParams.get("state");

  if (!authorizationCode || !state) {
    return new Response(null, {
      status: 302,
      headers: {
        Location: `${env.APP_ORIGIN}/integrations?success=false&error=${encodeURIComponent(
          "Missing authorization code or state",
        )}`,
      },
    });
  }

  const { integrationDefinitionId, redirectURL } =
    await getIntegrationDefinitionForState(state);

  try {
    // For now, we'll assume Linear integration - in the future this should be derived from state
    const integrationDefinition = await getIntegrationDefinitionWithId(
      integrationDefinitionId,
    );

    if (!integrationDefinition) {
      throw new Error("Integration definition not found");
    }

    const spec = integrationDefinition.spec as any;

    if (!spec.mcpAuth) {
      throw new Error("MCP auth configuration not found for this integration");
    }

    const { transportStrategy, serverUrl } = spec.mcpAuth;

    const authClient = createMCPAuthClient({
      serverUrl,
      transportStrategy: transportStrategy || "sse-first",
      redirectUrl: MCP_CALLBACK_URL,
    });

    const result = await authClient.completeOAuthFlow({
      authorizationCode,
      state,
      scope: "read write",
    });

    // Run integration trigger with MCP OAuth response
    await runIntegrationTrigger(
      integrationDefinition,
      {
        event: IntegrationEventType.SETUP,
        eventBody: {
          oauthResponse: result,
          oauthParams: {
            code: authorizationCode,
            state,
            redirect_uri: MCP_CALLBACK_URL,
          },
          integrationDefinition,
        },
      },
      // We need to get userId from somewhere - for now using undefined
      undefined,
    );

    return new Response(null, {
      status: 302,
      headers: {
        Location: `${redirectURL}/integrations?success=true&integrationName=${encodeURIComponent(
          integrationDefinition.name,
        )}`,
      },
    });
  } catch (error: any) {
    logger.error("MCP OAuth callback error:", error);

    return new Response(null, {
      status: 302,
      headers: {
        Location: `${redirectURL}/integrations?success=false&error=${encodeURIComponent(
          error.message || "OAuth callback failed",
        )}`,
      },
    });
  }
}
