import { NextRequest, NextResponse } from "next/server";
import { auth } from "@/lib/auth";
import { logger } from "@/lib/logger";
import { getErrorMessage } from "@/lib/errors";
import { getAuthenticatedConvexUser } from "@/lib/convex-auth-state";
import { convexMutation, convexQuery } from "@/lib/convex-client";
import {
  createAccountLink,
  createConnectedAccount,
  createDashboardLink,
  getAccountStatus,
} from "@/lib/stripe/connect";

type OrganizationState = {
  organization: Record<string, unknown>;
  userRole: string;
};

async function getAuthorizedOrganization(userId: string) {
  const orgState = await convexQuery<OrganizationState>(
    "organizations/queries:getOrganizationStateByUserId",
    { userId },
  );

  if (!orgState) {
    return null;
  }

  if (!["OWNER", "ADMIN"].includes(orgState.userRole)) {
    return null;
  }

  return orgState.organization;
}

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

    const organization = await getAuthorizedOrganization(user.id);
    if (!organization) {
      return NextResponse.json(
        { error: "Organization not found or insufficient permissions" },
        { status: 403 },
      );
    }

    const organizationId =
      (organization.prismaId as string | undefined) ||
      (organization._id as string);
    const stripeConnectAccountId =
      (organization.stripeConnectAccountId as string | undefined) ?? null;

    if (stripeConnectAccountId) {
      const status = await getAccountStatus(stripeConnectAccountId);
      if (status.status === "pending" || status.status === "restricted") {
        const onboardingUrl = await createAccountLink(stripeConnectAccountId);
        return NextResponse.json({
          accountId: stripeConnectAccountId,
          onboardingUrl,
          status: status.status,
        });
      }

      return NextResponse.json({
        accountId: stripeConnectAccountId,
        status: status.status,
      });
    }

    const body = await req.json();
    const { businessName, country } = body;

    if (!businessName || !country) {
      return NextResponse.json(
        { error: "Business name and country are required" },
        { status: 400 },
      );
    }

    const result = await createConnectedAccount(organizationId, {
      businessName,
      email: user.email,
      country,
    });

    return NextResponse.json(result, { status: 201 });
  } catch (error) {
    logger.error("Stripe Connect onboarding error", {
      error: getErrorMessage(error),
    });
    return NextResponse.json(
      { error: "Failed to start onboarding" },
      { status: 500 },
    );
  }
}

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

    const orgState = await convexQuery<OrganizationState>(
      "organizations/queries:getOrganizationStateByUserId",
      { userId: user.id },
    );

    const organization = orgState?.organization;
    const accountId =
      (organization?.stripeConnectAccountId as string | undefined) ?? null;

    if (!accountId) {
      return NextResponse.json({ status: "not_connected", accountId: null });
    }

    const status = await getAccountStatus(accountId);
    const currentDbStatus =
      (organization?.stripeConnectStatus as string | undefined) ?? null;

    if (currentDbStatus !== status.status) {
      await convexMutation("organizations/mutations:updateOrganizationNoAuth", {
        organizationId:
          (organization?.prismaId as string | undefined) ||
          (organization?._id as string),
        stripeConnectStatus: status.status,
      });
    }

    let dashboardUrl: string | null = null;
    if (status.chargesEnabled) {
      try {
        dashboardUrl = await createDashboardLink(accountId);
      } catch {
        // Ignore dashboard link failures.
      }
    }

    return NextResponse.json({ ...status, accountId, dashboardUrl });
  } catch (error) {
    logger.error("Stripe Connect status check error", {
      error: getErrorMessage(error),
    });
    return NextResponse.json(
      { error: "Failed to check status" },
      { status: 500 },
    );
  }
}
