// Update member's contribution tier
import {
  getHelcimPlanId,
  requiresPayment,
} from "../../config/contributions.js";
import { connectDB } from "../../utils/mongoose.js";
import Member from "../../models/member.js";
import {
  getHelcimCustomer,
  listHelcimCustomerCards,
  createHelcimSubscription,
  updateHelcimSubscription,
  cancelHelcimSubscription,
  generateIdempotencyKey,
  listHelcimCustomerTransactions,
} from "../../utils/helcim.js";
import { upsertPaymentFromHelcim } from "../../utils/payments.js";

export default defineEventHandler(async (event) => {
  try {
    const member = await requireAuth(event);
    await connectDB();
    const body = await validateBody(event, updateContributionSchema);

    const oldAmount = member.contributionAmount;
    const newAmount = body.contributionAmount;

    // If same amount, nothing to do
    if (oldAmount === newAmount) {
      return {
        success: true,
        message: "Already contributing this amount",
      };
    }

    // Log contribution change (fire-and-forget, at the top so it logs regardless of which case path executes)
    const logContributionChange = () => {
      logActivity(member._id, 'contribution_changed', { from: oldAmount, to: newAmount })
    }

    const oldRequiresPayment = requiresPayment(oldAmount);
    const newRequiresPayment = requiresPayment(newAmount);

    // Case 1: Moving from free to paid tier
    if (!oldRequiresPayment && newRequiresPayment) {
      // Check if member has Helcim customer ID with saved payment method
      if (!member.helcimCustomerId) {
        throw createError({
          statusCode: 400,
          statusMessage:
            "Please use the subscription creation flow to upgrade to a paid tier",
          data: { requiresPaymentSetup: true },
        });
      }

      // Resolve plan id before entering the try/catch (so missing plan → 500, not swallowed 400)
      const cadence = body.cadence; // defaulted to 'monthly' by Zod
      const paymentPlanId = getHelcimPlanId(cadence);
      if (!paymentPlanId) {
        throw createError({
          statusCode: 500,
          statusMessage: cadence === 'annual'
            ? 'Annual plan id not configured'
            : 'Monthly plan id not configured',
        });
      }

      try {
        const customerData = await getHelcimCustomer(member.helcimCustomerId);
        const customerCode = customerData.customerCode;

        if (!customerCode) {
          throw new Error("No customer code found");
        }

        // Check for saved cards
        const cards = await listHelcimCustomerCards(member.helcimCustomerId);
        const hasCards = Array.isArray(cards) && cards.length > 0;

        if (!hasCards) {
          throw new Error("No saved payment methods");
        }

        const idempotencyKey = generateIdempotencyKey();

        const subscriptionData = await createHelcimSubscription(
          {
            dateActivated: new Date().toISOString().split("T")[0],
            paymentPlanId: parseInt(paymentPlanId),
            customerCode,
            recurringAmount: cadence === 'annual' ? newAmount * 12 : newAmount,
            paymentMethod: "card",
          },
          idempotencyKey,
        );

        const subscription = subscriptionData.data?.[0];

        if (!subscription) {
          throw new Error("No subscription returned in response");
        }

        const nextBillingDate = subscription.nextBillingDate
          ? new Date(subscription.nextBillingDate)
          : null;

        // Update member record
        await Member.findByIdAndUpdate(
          member._id,
          { $set: {
              contributionAmount: newAmount,
              helcimSubscriptionId: subscription.id,
              paymentMethod: "card",
              status: "active",
              billingCadence: cadence,
              ...(nextBillingDate && !Number.isNaN(nextBillingDate.getTime())
                ? { nextBillingDate }
                : {}),
            } },
          { runValidators: false }
        );

        try {
          const txs = await listHelcimCustomerTransactions(customerCode);
          const latestPaid = txs.find((t) => t.status === 'paid');
          if (latestPaid) {
            await upsertPaymentFromHelcim(
              {
                _id: member._id,
                email: member.email,
                name: member.name,
                helcimCustomerId: member.helcimCustomerId,
                helcimSubscriptionId: subscription.id,
                billingCadence: cadence,
              },
              latestPaid,
              { paymentType: cadence, sendConfirmation: true }
            );
          }
        } catch (err) {
          console.error('[payments] free→paid charge log failed, will be picked up by reconciliation:', err?.message || err);
        }

        logContributionChange();

        return {
          success: true,
          message: "Successfully upgraded to paid tier",
          subscription: {
            subscriptionId: subscription.id,
            status: subscription.status,
            nextBillingDate: subscription.nextBillingDate,
          },
        };
      } catch (error) {
        console.error("Error creating subscription with saved payment:", error);
        // If we can't use saved payment, require new payment setup
        throw createError({
          statusCode: 400,
          statusMessage:
            "Payment information required. You'll be redirected to complete payment setup.",
          data: { requiresPaymentSetup: true },
        });
      }
    }

    // Case 2: Moving from paid to free tier (cancel subscription)
    if (oldRequiresPayment && !newRequiresPayment) {
      if (member.helcimSubscriptionId) {
        try {
          await cancelHelcimSubscription(member.helcimSubscriptionId);
        } catch (cancelError) {
          console.error("Error canceling Helcim subscription:", cancelError);
          // Continue anyway - we'll update the member record
        }
      }

      // Update member to free tier
      await Member.findByIdAndUpdate(
        member._id,
        {
          $set: { contributionAmount: newAmount, helcimSubscriptionId: null, paymentMethod: "none", billingCadence: "monthly" },
          $unset: { nextBillingDate: 1 },
        },
        { runValidators: false }
      );

      logContributionChange()

      return {
        success: true,
        message: "Successfully downgraded to free tier",
      };
    }

    // Case 3: Moving between paid tiers
    if (oldRequiresPayment && newRequiresPayment) {
      if (!member.helcimSubscriptionId) {
        throw createError({
          statusCode: 400,
          statusMessage: "Payment information required. You'll be redirected to complete payment setup.",
          data: { requiresPaymentSetup: true },
        });
      }

      const memberCadence = member.billingCadence || 'monthly';
      if (body.cadence && body.cadence !== memberCadence) {
        throw createError({
          statusCode: 400,
          statusMessage: 'Cadence switch not supported on existing subscription',
        });
      }

      try {
        const subscriptionData = await updateHelcimSubscription(
          member.helcimSubscriptionId,
          { recurringAmount: memberCadence === 'annual' ? newAmount * 12 : newAmount }
        );

        await Member.findByIdAndUpdate(
          member._id,
          { $set: { contributionAmount: newAmount } },
          { runValidators: false }
        );

        logContributionChange();

        return {
          success: true,
          message: 'Successfully updated contribution level',
          subscription: subscriptionData,
        };
      } catch (updateError) {
        console.error('Error updating Helcim subscription:', updateError);
        throw createError({ statusCode: 500, statusMessage: 'Subscription update failed' });
      }
    }

    // Case 4: Moving between free tiers (shouldn't happen but handle it)
    await Member.findByIdAndUpdate(
      member._id,
      { $set: { contributionAmount: newAmount } },
      { runValidators: false }
    );

    logContributionChange()

    return {
      success: true,
      message: "Successfully updated contribution level",
    };
  } catch (error) {
    if (error.statusCode) throw error;
    console.error("Error updating contribution tier:", error);
    throw createError({
      statusCode: 500,
      statusMessage: "An unexpected error occurred",
    });
  }
});
