import { NextRequest, NextResponse } from "next/server";
import { stripe } from "@/lib/stripe";
import { prisma } from "@/lib/db";
import { logger } from "@/lib/logger";
import { createId } from "@paralleldrive/cuid2";
import {
  sendOnboardingCongratulationsEmail,
  sendInvoiceEmail,
} from "@/lib/email-onboarding";
import { getSectorForIndustry } from "@/lib/config/industry-sector-map";
import { seedIndustryDefaults } from "@/lib/services/appointment-type-seeder";

/**
 * GET /api/signup/success?session_id=cs_...
 *
 * Verifies Stripe checkout session completion and finalizes clinic subscription
 * - Retrieves session from Stripe
 * - Verifies payment was successful
 * - Creates Subscription record in database (via Convex-backed adapter)
 * - Marks user onboarding as complete
 * - Returns actual session data for display (not hardcoded prices!)
 *
 * Response:
 * {
 *   success: true,
 *   subscriptionId: string,
 *   redirectUrl: string,
 *   sessionData: {
 *     tierId: string,
 *     billingPeriod: string,
 *     currency: string,
 *     recurringAmount: number,
 *     setupFeeAmount: number,
 *     trialDays: number,
 *     paymentStatus: string
 *   }
 * }
 */

export async function GET(request: NextRequest) {
  try {
    const { searchParams } = new URL(request.url);
    const sessionId = searchParams.get("session_id");

    if (!sessionId) {
      logger.warn("Missing session_id in success request");
      return NextResponse.json(
        { error: "Missing session_id parameter" },
        { status: 400 },
      );
    }

    logger.info("Processing signup success", { sessionId });

    // Retrieve checkout session from Stripe with timeout handling
    let session;
    try {
      session = await stripe.checkout.sessions.retrieve(sessionId, {
        expand: [
          "subscription",
          "subscription.default_payment_method",
          "payment_intent",
          "line_items",
        ],
      });

      logger.info("Stripe session retrieved", {
        sessionId,
        paymentStatus: session.payment_status,
        hasSubscription: !!session.subscription,
        customer: session.customer,
        amountTotal: session.amount_total,
        currency: session.currency,
      });
    } catch (stripeError) {
      const errorMessage =
        stripeError instanceof Error
          ? stripeError.message
          : String(stripeError);
      const errorCode = (stripeError as any)?.code || "unknown";

      logger.error("Failed to retrieve Stripe session", {
        sessionId,
        error: errorMessage,
        errorCode,
        errorType: (stripeError as any)?.type,
      });

      // Return detailed error for debugging
      return NextResponse.json(
        {
          error: "Failed to verify payment session",
          details: errorMessage,
          code: errorCode,
          sessionId,
        },
        { status: 400 },
      );
    }

    // Validate session status
    if (session.payment_status !== "paid") {
      logger.warn("Session payment not completed", {
        sessionId,
        paymentStatus: session.payment_status,
      });
      return NextResponse.json(
        {
          error: "Payment not completed",
          paymentStatus: session.payment_status,
        },
        { status: 400 },
      );
    }

    // Extract metadata
    const userIdFromMetadata = session.metadata?.user_id;
    const tierId = session.metadata?.tier_id;
    const billingPeriod = session.metadata?.billing_period || "monthly";
    const goalsJson = session.metadata?.goals;
    const setupFeeAmountStr = session.metadata?.setup_fee_amount;
    const setupFeeAmount = setupFeeAmountStr ? parseInt(setupFeeAmountStr) : 0;

    if (!tierId) {
      logger.error("Missing tier_id in session metadata", { sessionId });
      return NextResponse.json(
        { error: "Invalid session metadata - missing tier_id" },
        { status: 400 },
      );
    }

    // Get user by email from Stripe session (more reliable than metadata userId)
    const customerEmail =
      session.customer_details?.email || (session as any).customer_email;

    logger.info("Looking up user", {
      customerEmail,
      userIdFromMetadata,
      hasCustomerDetails: !!session.customer_details,
      customerDetailsEmail: session.customer_details?.email,
    });

    if (!customerEmail && !userIdFromMetadata) {
      logger.error("No customer email or user_id in session", { sessionId });
      return NextResponse.json(
        { error: "Cannot identify user from session" },
        { status: 400 },
      );
    }

    // Find user by email (primary method) or fallback to userId from metadata
    let user = null;
    if (customerEmail) {
      logger.info("Searching for user by email", { email: customerEmail });
      user = await prisma.users.findUnique({
        where: { email: customerEmail },
      });
      logger.info("Email lookup result", {
        found: !!user,
        userId: user?.id,
        email: customerEmail,
      });
    }

    // Fallback to userId from metadata if email lookup fails
    if (!user && userIdFromMetadata) {
      logger.info("Searching for user by ID", { userId: userIdFromMetadata });
      user = await prisma.users.findUnique({
        where: { id: userIdFromMetadata },
      });
      logger.info("ID lookup result", { found: !!user, userId: user?.id });
    }

    if (!user) {
      logger.error("User not found for session", {
        sessionId,
        customerEmail,
        userIdFromMetadata,
      });
      return NextResponse.json(
        {
          error: "User account not found. Please complete signup first.",
          details:
            "The user associated with this payment session was not found in the database.",
        },
        { status: 404 },
      );
    }

    const userId = user.id;

    // Verify subscription was created
    if (!session.subscription) {
      logger.error("No subscription found in session", { sessionId });
      return NextResponse.json(
        { error: "Subscription not created" },
        { status: 400 },
      );
    }

    const stripeSubscription =
      typeof session.subscription === "string"
        ? await stripe.subscriptions.retrieve(session.subscription, {
            expand: ["default_payment_method"],
          })
        : session.subscription;

    const customerId = session.customer as string;
    const stripePriceId = stripeSubscription.items?.data?.[0]?.price?.id;

    if (!stripePriceId) {
      logger.error("No price found in subscription", { sessionId });
      return NextResponse.json(
        { error: "Invalid subscription items" },
        { status: 400 },
      );
    }

    // Extract payment method details
    let paymentMethodId: string | null = null;
    let cardBrand: string | null = null;
    let cardLastFour: string | null = null;

    if (stripeSubscription.default_payment_method) {
      const pm = stripeSubscription.default_payment_method as any;
      paymentMethodId = pm.id;
      if (pm.card) {
        cardBrand = pm.card.brand;
        cardLastFour = pm.card.last4;
      }
    }

    // Check if subscription already exists (idempotency)
    logger.info("Checking for existing subscription", {
      stripeSubscriptionId: stripeSubscription.id,
    });

    const existingPrismaSub = await prisma.subscriptions.findFirst({
      where: { stripeSubscriptionId: stripeSubscription.id },
    });

    let subscription;

    if (!existingPrismaSub) {
      logger.info("Creating new subscription record", {
        userId,
        tierId,
        stripeSubscriptionId: stripeSubscription.id,
      });

      // Safely handle current_period_end which might be undefined
      const currentPeriodEnd = stripeSubscription.current_period_end
        ? new Date(stripeSubscription.current_period_end * 1000)
        : new Date(Date.now() + 14 * 24 * 60 * 60 * 1000); // 14 days from now as fallback

      // Create subscription record in database
      subscription = await prisma.subscriptions.create({
        data: {
          id: createId(), // Generate unique ID
          userId: userId,
          stripeCustomerId: customerId,
          stripeSubscriptionId: stripeSubscription.id,
          stripePriceId: stripePriceId,
          tierId: tierId,
          status: "trialing", // 14-day trial
          billingPeriod: billingPeriod as "monthly" | "yearly",
          currentPeriodEnd: currentPeriodEnd,
          trialEndsAt: stripeSubscription.trial_end
            ? new Date(stripeSubscription.trial_end * 1000)
            : currentPeriodEnd,
          paymentMethodId: paymentMethodId,
          cardBrand: cardBrand,
          cardLastFour: cardLastFour,
          setupFeePaid: session.metadata?.has_setup_fee === "true",
          setupFeePaidAt:
            session.metadata?.has_setup_fee === "true" ? new Date() : null,
          setupFeeAmount: setupFeeAmount,
          updatedAt: new Date(), // Required field for subscriptions model
        },
      });

      logger.info("Subscription record created (success endpoint)", {
        subscriptionId: subscription.id,
        userId,
        stripeSubscriptionId: stripeSubscription.id,
      });
    } else {
      logger.info(
        "Subscription already exists (idempotent - success endpoint)",
        {
          subscriptionId: existingPrismaSub.id,
          stripeSubscriptionId: stripeSubscription.id,
          userId,
        },
      );
      subscription = existingPrismaSub;
    }

    // Mark onboarding as complete and save goals
    logger.info("Updating user onboarding status", { userId });

    const goals = goalsJson ? JSON.parse(goalsJson) : [];
    await prisma.users.update({
      where: { id: userId },
      data: {
        goals: goals.length > 0 ? goals : null,
        onboardingComplete: true,
        selectedPackage: tierId,
        stripeCustomerId: customerId,
      },
    });

    logger.info("User onboarding marked complete", { userId });

    // 🏢 AUTO-PROVISION ORGANIZATION
    // Create organization for ALL subscription tiers (not just tier3+)
    // so the WhatsApp pipeline, KB, and appointment types are ready immediately.
    try {
      const existingOrg = await prisma.organizations.findFirst({
        where: { ownerId: userId },
        select: { id: true },
      });

      if (existingOrg) {
        logger.info("Organization already exists for user, skipping creation", {
          userId,
          organizationId: existingOrg.id,
        });
      } else {
        const industry = user.industry || null;
        const sector = getSectorForIndustry(industry);
        const orgName = user.companyName
          || (user.name ? `${user.name}'s Business` : "My Business");

        const newOrg = await prisma.organizations.create({
          data: {
            id: createId(),
            name: orgName,
            ownerId: userId,
            subscriptionTier: tierId,
            industry: industry || undefined,
            sector: sector,
          },
        });

        logger.info("Organization auto-provisioned", {
          userId,
          organizationId: newOrg.id,
          industry,
          sector,
          tier: tierId,
        });

        // Seed industry-specific appointment types
        try {
          await seedIndustryDefaults(userId, newOrg.id, industry);
          logger.info("Appointment types seeded for new organization", {
            organizationId: newOrg.id,
            industry,
          });
        } catch (seedError) {
          logger.error("Failed to seed appointment types (non-fatal)", {
            organizationId: newOrg.id,
            industry,
            error: seedError instanceof Error ? seedError.message : String(seedError),
          });
        }
      }
    } catch (orgError) {
      // Non-fatal: log but don't break the signup flow
      logger.error("Failed to auto-provision organization (non-fatal)", {
        userId,
        error: orgError instanceof Error ? orgError.message : String(orgError),
      });
    }

    // 🎉 SEND CONGRATULATIONS AND INVOICE EMAILS
    // After onboarding is complete, send welcome and invoice emails
    try {
      const lang = session.metadata?.language || "en";
      const userLanguage = lang === "ar" || lang === "en" ? lang : "en";

      // Get package name from tier ID
      const packageNames: Record<string, { en: string; ar: string }> = {
        tier1: { en: "Starter", ar: "المبتدئ" },
        tier2: { en: "Professional", ar: "المحترف" },
        tier3: { en: "Business", ar: "الأعمال" },
        tier4: { en: "Enterprise", ar: "المؤسسات" },
        tier5: { en: "Ultimate", ar: "المتكاملة" },
      };

      const packageName = packageNames[tierId]?.[userLanguage] || tierId;
      const trialDays = 14; // Default trial period

      // 1. Send Congratulations Email
      logger.info("Sending congratulations email", {
        email: customerEmail,
        userId,
      });
      const congratsSent = await sendOnboardingCongratulationsEmail(
        customerEmail!,
        user.name || "User",
        user.companyName || "Your Company",
        packageName,
        trialDays,
        userLanguage,
      );

      if (congratsSent) {
        logger.info("✅ Congratulations email sent", { email: customerEmail });
      } else {
        logger.warn("❌ Failed to send congratulations email", {
          email: customerEmail,
        });
      }

      // 2. Send Invoice Email (ALWAYS send, setup fee might be 0)
      logger.info("Preparing to send invoice email", {
        email: customerEmail,
        setupFeeAmount,
        setupFeeAmountInDollars: setupFeeAmount / 100,
        willSendInvoice: true,
      });

      if (true) {
        // Always send invoice
        logger.info("Sending invoice email", {
          email: customerEmail,
          setupFee: setupFeeAmount,
        });

        const trialEndDate =
          subscription.trialEndsAt ||
          new Date(Date.now() + 14 * 24 * 60 * 60 * 1000);
        const nextBillingDate = subscription.currentPeriodEnd;

        const invoiceSent = await sendInvoiceEmail(
          customerEmail!,
          user.name || "User",
          user.companyName || "Your Company",
          {
            invoiceNumber: subscription.id.slice(-8).toUpperCase(),
            packageName,
            currency: (session.currency || "qar").toUpperCase(),
            setupFee: setupFeeAmount / 100, // Convert from cents
            recurringAmount: 0, // Will be set accurately in the section below
            trialEndsDate: trialEndDate.toLocaleDateString(
              userLanguage === "ar" ? "ar-SA" : "en-US",
            ),
            nextBillingDate: nextBillingDate.toLocaleDateString(
              userLanguage === "ar" ? "ar-SA" : "en-US",
            ),
          },
          userLanguage,
        );

        if (invoiceSent) {
          logger.info("✅ Invoice email sent", { email: customerEmail });
        } else {
          logger.warn("❌ Failed to send invoice email", {
            email: customerEmail,
          });
        }
      }
    } catch (emailError) {
      // Don't fail the request if emails fail - log and continue
      logger.error("Failed to send onboarding emails", {
        error:
          emailError instanceof Error ? emailError.message : String(emailError),
        userId,
        email: customerEmail,
      });
    }

    // Log successful completion in audit log
    await prisma.audit_logs.create({
      data: {
        id: createId(), // Generate unique ID for audit log
        userId: userId,
        type: "subscription_created",
        action: "Subscription created after payment",
        success: true,
        ip:
          request.headers.get("x-forwarded-for") ||
          request.headers.get("x-real-ip") ||
          "127.0.0.1",
        userAgent: request.headers.get("user-agent") || undefined,
        metadata: {
          tier_id: tierId,
          subscription_id: subscription.id,
          stripe_subscription_id: stripeSubscription.id,
          billing_period: billingPeriod,
          setup_fee_paid: true,
        },
      },
    });

    logger.info("Signup completed successfully", {
      userId,
      subscriptionId: subscription.id,
      tierId,
      sessionId,
    });

    // Default to Arabic (language field not in User schema)
    // TODO: Add language field to User model if needed
    const lang = session.metadata?.language || "ar";

    // Get the ACTUAL subscription price from Stripe for display (not hardcoded!)
    let recurringPrice = 0;
    let priceCurrency = session.currency || "qar";
    let trialDays = 14; // Default

    if (stripeSubscription.items?.data?.length > 0) {
      // Find the recurring price item (not the setup fee)
      const recurringItem = stripeSubscription.items.data.find(
        (item) =>
          item.price.recurring !== null && item.price.recurring !== undefined,
      );

      if (recurringItem?.price.unit_amount) {
        recurringPrice = recurringItem.price.unit_amount / 100; // Convert from cents to currency units
        priceCurrency = recurringItem.price.currency;
      }

      // Calculate actual trial days remaining
      if (
        stripeSubscription.trial_end &&
        typeof stripeSubscription.trial_end === "number"
      ) {
        const trialEndDate = stripeSubscription.trial_end * 1000;
        const daysRemaining = Math.ceil(
          (trialEndDate - Date.now()) / (1000 * 60 * 60 * 24),
        );
        trialDays = Math.max(0, daysRemaining); // Ensure non-negative
      }
    }

    // 🔐 FIXED: Redirect to login page instead of dashboard
    // This ensures proper NextAuth session creation with all user data
    // User will login with OTP and get full authenticated access
    return NextResponse.json({
      success: true,
      subscriptionId: subscription.id,
      redirectUrl: `/${lang}/login?signup_complete=true`,
      sessionData: {
        tierId: tierId,
        billingPeriod: billingPeriod,
        currency: priceCurrency.toUpperCase(),
        recurringAmount: recurringPrice, // ACTUAL recurring price from Stripe
        setupFeeAmount: setupFeeAmount / 100, // Convert from cents
        trialDays: trialDays,
        paymentStatus: session.payment_status,
      },
    });
  } catch (error) {
    logger.error("Success route error", {
      error: error instanceof Error ? error.message : "Unknown error",
      stack: error instanceof Error ? error.stack : undefined,
    });

    return NextResponse.json(
      { error: "Failed to process signup completion" },
      { status: 500 },
    );
  }
}
