import { NextRequest, NextResponse } from "next/server";
import { auth } from "@/lib/auth";
import { PRICING_TIERS } from "@/lib/config/pricing-tiers";
import { getAuthenticatedConvexUser } from "@/lib/convex-auth-state";
import { getActiveConvexSubscription } from "@/lib/convex-billing-state";
import { convexQuery } from "@/lib/convex-client";

interface PlanDetails {
  type: string;
  name: string;
  nameAr: string;
  monthlyPrice: number;
  features: string[];
  featuresAr: string[];
}

interface CurrentSubscription {
  id: string;
  userId: string;
  stripeSubscriptionId: string;
  stripeCustomerId: string;
  stripePriceId: string;
  planType: string;
  status: string;
  currentPeriodStart: string;
  currentPeriodEnd: string;
  cancelAtPeriodEnd: boolean;
  amount: number;
  currency: string;
  daysRemaining: number;
  daysInPeriod: number;
  daysUsed: number;
}

function planDetailsForTier(tierId: string): PlanDetails {
  const tier = PRICING_TIERS.find((item) => item.id === tierId);
  if (!tier) {
    throw new Error(`Unknown tier: ${tierId}`);
  }

  return {
    type: tier.id,
    name: tier.nameEn,
    nameAr: tier.nameAr,
    monthlyPrice: tier.priceGBP,
    features: tier.featuresEn,
    featuresAr: tier.featuresAr,
  };
}

function buildCurrentSubscription(
  subscription: Awaited<ReturnType<typeof getActiveConvexSubscription>>,
) {
  if (!subscription) return null;

  const daysInPeriod = subscription.billingPeriod === "yearly" ? 365 : 30;
  const currentPeriodEnd = new Date(subscription.currentPeriodEnd);
  const currentPeriodStart = new Date(
    subscription.currentPeriodEnd - daysInPeriod * 24 * 60 * 60 * 1000,
  );
  const now = Date.now();
  const daysRemaining = Math.max(
    0,
    Math.ceil((subscription.currentPeriodEnd - now) / (24 * 60 * 60 * 1000)),
  );
  const daysUsed = Math.max(0, daysInPeriod - daysRemaining);
  const tier = PRICING_TIERS.find((item) => item.id === subscription.tierId);

  const currentSubscription: CurrentSubscription = {
    id: subscription._id,
    userId: subscription.userId,
    stripeSubscriptionId: subscription.stripeSubscriptionId,
    stripeCustomerId: subscription.stripeCustomerId,
    stripePriceId: subscription.stripePriceId,
    planType: subscription.tierId,
    status: subscription.status,
    currentPeriodStart: currentPeriodStart.toISOString(),
    currentPeriodEnd: currentPeriodEnd.toISOString(),
    cancelAtPeriodEnd: subscription.cancelAtPeriodEnd,
    amount: tier?.priceGBP ?? 0,
    currency: "gbp",
    daysRemaining,
    daysInPeriod,
    daysUsed,
  };

  return currentSubscription;
}

function calculateProration(
  currentSubscription: CurrentSubscription,
  newPlan: PlanDetails,
) {
  const dailyRateCurrentPlan =
    currentSubscription.amount / currentSubscription.daysInPeriod;
  const dailyRateNewPlan =
    newPlan.monthlyPrice / currentSubscription.daysInPeriod;
  const creditFromCurrentPlan =
    dailyRateCurrentPlan * currentSubscription.daysRemaining;
  const chargeForNewPlan = dailyRateNewPlan * currentSubscription.daysRemaining;
  const immediateCharge = chargeForNewPlan - creditFromCurrentPlan;

  return {
    currentPlan: planDetailsForTier(currentSubscription.planType),
    newPlan,
    daysRemaining: currentSubscription.daysRemaining,
    daysInPeriod: currentSubscription.daysInPeriod,
    creditFromCurrentPlan: Math.round(creditFromCurrentPlan * 100) / 100,
    chargeForNewPlan: Math.round(chargeForNewPlan * 100) / 100,
    immediateCharge: Math.round(immediateCharge * 100) / 100,
    nextBillingAmount: newPlan.monthlyPrice,
    isUpgrade: newPlan.monthlyPrice > currentSubscription.amount,
  };
}

async function resolveBillableSubscription(userId: string) {
  const directSubscription = await getActiveConvexSubscription(userId);
  if (directSubscription) {
    return directSubscription;
  }

  const orgState = await convexQuery<{
    organization: { ownerId: string };
  }>("organizations/queries:getOrganizationStateByUserId", {
    userId,
  });

  if (
    orgState?.organization?.ownerId &&
    orgState.organization.ownerId !== userId
  ) {
    return await getActiveConvexSubscription(orgState.organization.ownerId);
  }

  return null;
}

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

    const subscription = await resolveBillableSubscription(user.id);
    const currentSubscription = buildCurrentSubscription(subscription);

    if (!currentSubscription) {
      return NextResponse.json(
        { error: "No active subscription" },
        { status: 404 },
      );
    }

    const currentPlan = planDetailsForTier(currentSubscription.planType);
    const currentIndex = PRICING_TIERS.findIndex(
      (tier) => tier.id === currentSubscription.planType,
    );

    const upgrades = PRICING_TIERS.slice(currentIndex + 1).map((tier) => {
      const plan = planDetailsForTier(tier.id);
      return {
        ...plan,
        proration: calculateProration(currentSubscription, plan),
      };
    });

    const downgrades = PRICING_TIERS.slice(0, currentIndex).map((tier) => {
      const plan = planDetailsForTier(tier.id);
      return {
        ...plan,
        proration: calculateProration(currentSubscription, plan),
      };
    });

    return NextResponse.json({
      current: currentPlan,
      upgrades,
      downgrades,
      currentSubscription,
    });
  } catch (error) {
    return NextResponse.json(
      {
        error: "Internal server error",
        message: error instanceof Error ? error.message : "Unknown error",
      },
      { status: 500 },
    );
  }
}
