import { convexMutation, convexQuery } from "@/lib/convex-client";
import { CONVEX_PATHS } from "@/lib/convex-paths";
import type { RawConvexUser } from "@/lib/convex-auth-state";

export interface ConvexBillingSubscription {
  _id: string;
  prismaId?: string;
  userId: string;
  stripeCustomerId: string;
  stripeSubscriptionId: string;
  stripePriceId: string;
  tierId: string;
  status: string;
  billingPeriod: string;
  currentPeriodEnd: number;
  trialEndsAt?: number;
  cancelAtPeriodEnd: boolean;
  cancelledAt?: number;
  lastPaymentDate?: number;
  lastPaymentAttempt?: number;
  paymentFailureCount: number;
  cardBrand?: string;
  cardLastFour?: string;
  paymentMethodId?: string;
  setupFeeAmount?: number;
  setupFeePaid: boolean;
  setupFeePaidAt?: number;
}

export interface ConvexPaymentRecord {
  _id: string;
  stripePaymentIntentId: string;
  stripeSessionId?: string;
  amount: number;
  currency: string;
  status: string;
  customerId: string;
  customerEmail?: string;
  succeededAt?: number;
  failedAt?: number;
  errorMessage?: string;
  metadata?: Record<string, unknown>;
}

export interface ConvexRefundRecord {
  _id: string;
  stripeRefundId: string;
  stripePaymentIntentId?: string;
  stripeChargeId?: string;
  subscriptionId?: string;
  customerId: string;
  userId?: string;
  amount: number;
  currency: string;
  status: string;
  reason?: string;
  stripeReason?: string;
  failureReason?: string;
  processedAt?: number;
  metadata?: Record<string, unknown>;
}

export async function getActiveConvexSubscription(userId: string) {
  return await convexQuery<ConvexBillingSubscription>(
    "billing/queries:getActiveSubscription",
    { userId },
  );
}

export async function getConvexSubscriptionByAnyId(subscriptionId: string) {
  return await convexQuery<ConvexBillingSubscription>(
    CONVEX_PATHS.getSubscriptionByAnyId,
    { subscriptionId },
  );
}

export async function getConvexSubscriptionByCustomerId(
  stripeCustomerId: string,
) {
  return await convexQuery<ConvexBillingSubscription>(
    CONVEX_PATHS.getSubscriptionByCustomerId,
    { stripeCustomerId },
  );
}

export async function upsertConvexSubscriptionByStripeId(args: {
  userId?: string;
  prismaId?: string;
  stripeCustomerId: string;
  stripeSubscriptionId: string;
  stripePriceId?: string;
  tierId?: string;
  status: string;
  billingPeriod?: string;
  currentPeriodEnd?: number;
  trialEndsAt?: number;
  cancelAtPeriodEnd?: boolean;
  cancelledAt?: number;
  lastPaymentDate?: number;
  lastPaymentAttempt?: number;
  paymentFailureCount?: number;
  cardBrand?: string;
  cardLastFour?: string;
  paymentMethodId?: string;
  setupFeeAmount?: number;
  setupFeePaid?: boolean;
  setupFeePaidAt?: number;
}) {
  return await convexMutation<string>(
    CONVEX_PATHS.upsertSubscriptionByStripeId,
    args,
  );
}

export async function updateConvexSubscription(args: {
  id: string;
  status?: string;
  stripeCustomerId?: string;
  stripePriceId?: string;
  tierId?: string;
  billingPeriod?: string;
  currentPeriodEnd?: number;
  trialEndsAt?: number;
  cancelAtPeriodEnd?: boolean;
  cancelledAt?: number;
  lastPaymentDate?: number;
  lastPaymentAttempt?: number;
  paymentFailureCount?: number;
  cardBrand?: string;
  cardLastFour?: string;
  paymentMethodId?: string;
  setupFeeAmount?: number;
  setupFeePaid?: boolean;
  setupFeePaidAt?: number;
}) {
  return await convexMutation<string>(
    "billing/mutations:updateSubscription",
    args,
  );
}

export async function recordConvexBillingEvent(args: {
  customerId: string;
  subscriptionId?: string;
  invoiceId?: string;
  paymentIntentId?: string;
  dedupeKey: string;
  event: string;
  amount: number;
  currency: string;
  metadata?: Record<string, unknown>;
}) {
  return await convexMutation<string>(
    CONVEX_PATHS.recordBillingEventIfMissing,
    args,
  );
}

export async function getConvexPaymentByStripePaymentIntentId(
  stripePaymentIntentId: string,
) {
  return await convexQuery<ConvexPaymentRecord>(
    CONVEX_PATHS.getPaymentByStripePaymentIntentId,
    { stripePaymentIntentId },
  );
}

export async function upsertConvexPayment(args: {
  stripePaymentIntentId: string;
  stripeSessionId?: string;
  amount: number;
  currency: string;
  status: string;
  customerId: string;
  customerEmail?: string;
  succeededAt?: number;
  failedAt?: number;
  errorMessage?: string;
  metadata?: Record<string, unknown>;
}) {
  return await convexMutation<string>(CONVEX_PATHS.upsertPayment, args);
}

export async function getConvexRefundById(refundId: string) {
  return await convexQuery<ConvexRefundRecord>(CONVEX_PATHS.getRefundById, {
    refundId,
  });
}

export async function upsertConvexRefund(args: {
  prismaId?: string;
  stripeRefundId: string;
  stripePaymentIntentId?: string;
  stripeChargeId?: string;
  subscriptionId?: string;
  customerId: string;
  userId?: string;
  amount: number;
  currency: string;
  status: string;
  reason?: string;
  stripeReason?: string;
  failureReason?: string;
  processedAt?: number;
  metadata?: Record<string, unknown>;
}) {
  return await convexMutation<string>(CONVEX_PATHS.upsertRefund, args);
}

export async function getConvexUserByStripeCustomerId(
  stripeCustomerId: string,
) {
  return await convexQuery<RawConvexUser>(
    CONVEX_PATHS.getUserByStripeCustomerId,
    { stripeCustomerId },
  );
}

export async function getConvexOrganizationByConnectAccountId(
  stripeConnectAccountId: string,
) {
  return await convexQuery<Record<string, unknown>>(
    CONVEX_PATHS.getOrganizationByConnectAccountId,
    { stripeConnectAccountId },
  );
}
