/**
 * Dashboard Access Control
 *
 * Determines if a user can access the dashboard based on:
 * - Authentication status
 * - Onboarding completion (optional)
 * - Subscription status (optional)
 *
 * All data access goes through Convex. No Prisma fallback.
 */

import { convexQuery, convexMutation } from "@/lib/convex-client";
import { logger } from "./logger";
import {
  isStaffMember,
  getStaffSubscriptionForResponse,
} from "./utils/permissions";

export interface DashboardAccessResult {
  hasAccess: boolean;
  reason?: string;
  onboardingComplete?: boolean;
  subscription?: {
    status: string;
    tierId: string;
    billingPeriod: string;
    currentPeriodEnd: string;
  };
  redirectUrl?: string;
  /**
   * Organization information when user has access via org membership
   */
  organization?: {
    id: string;
    name: string;
    role: string;
  };
}

interface ConvexUser {
  _id: string;
  prismaId?: string;
  appUserId?: string;
  email: string;
  name?: string;
  role?: string;
  onboardingComplete?: boolean;
  selectedPackage?: string;
  selectedBillingPeriod?: string;
  preferredCurrency?: string;
}

interface ConvexSubscription {
  _id: string;
  tierId?: string;
  status: string;
  billingPeriod?: string;
  currentPeriodEnd?: number;
  trialEndsAt?: number;
  cancelAtPeriodEnd?: boolean;
  setupFeePaid?: boolean;
}

const ACTIVE_SUBSCRIPTION_STATUSES = new Set([
  "active",
  "trialing",
  "pending_verification", // Legacy: created before webhook promoted to active
]);

/**
 * Check if user has access to the dashboard.
 * Accepts optional email for fallback lookup when userId is a non-Prisma ID.
 */
export async function checkDashboardAccess(
  userId: string,
  email?: string,
): Promise<DashboardAccessResult> {
  try {
    logger.debug("checkDashboardAccess called", { userId, email });

    // Try finding user by email first (most reliable cross-DB key)
    let user: ConvexUser | null = null;

    if (email) {
      user = await convexQuery<ConvexUser>("auth/queries:getUserByEmail", {
        email,
      });
    }

    // If not found by email, try by clerkId
    if (!user) {
      user = await convexQuery<ConvexUser>("auth/queries:getUserByClerkId", {
        clerkId: userId,
      });
    }

    if (!user) {
      return {
        hasAccess: false,
        reason: "User not found",
        redirectUrl: "/en/onboarding",
      };
    }

    const effectiveUserId = user.prismaId || user.appUserId || user._id;

    logger.debug("checkDashboardAccess user found", {
      userId: effectiveUserId,
      email: user.email,
    });

    // Staff members (STAFF, ADMIN, SUPER_ADMIN) always have full access
    if (isStaffMember({ role: user.role || null })) {
      const staffSub = getStaffSubscriptionForResponse();
      return {
        hasAccess: true,
        onboardingComplete: true,
        subscription: {
          status: staffSub.status,
          tierId: staffSub.tierId,
          billingPeriod: staffSub.billingPeriod,
          currentPeriodEnd: staffSub.currentPeriodEnd,
        },
      };
    }

    // Check for a valid subscription via Convex
    // Try all userId formats to handle the write/read mismatch
    const sub = await convexQuery<ConvexSubscription>(
      "billing/queries:getSubscriptionByAnyUserId",
      {
        prismaId: user.prismaId || undefined,
        appUserId: user.appUserId || undefined,
        convexId: user._id,
      },
    );

    logger.info("checkDashboardAccess subscription check", {
      prismaId: user.prismaId,
      appUserId: user.appUserId,
      convexId: user._id,
      subFound: !!sub,
      subStatus: sub?.status,
      subCurrentPeriodEnd: sub?.currentPeriodEnd,
      isValid: sub ? isValidSubscription(sub) : false,
    });

    if (sub && isValidSubscription(sub)) {
      // Backfill onboardingComplete if user has a valid subscription but flag is false
      if (!user.onboardingComplete) {
        convexMutation("auth/mutations:updateUserNoAuth", {
          email: user.email,
          onboardingComplete: true,
        }).catch((err) => {
          logger.warn("Failed to backfill onboardingComplete", {
            userId: effectiveUserId,
            error: err instanceof Error ? err.message : String(err),
          });
        });
      }
      return {
        hasAccess: true,
        onboardingComplete: true,
        subscription: {
          status: sub.status,
          tierId: sub.tierId || "",
          billingPeriod: sub.billingPeriod || "monthly",
          currentPeriodEnd: sub.currentPeriodEnd
            ? new Date(sub.currentPeriodEnd).toISOString()
            : "",
        },
      };
    }

    // No direct subscription — check if user is member of an organization with active subscription
    const orgState = await convexQuery<Record<string, unknown>>(
      "organizations/queries:getOrganizationStateByUserId",
      { userId: effectiveUserId },
    ).catch(() => null);

    if (orgState) {
      const userRole = orgState.userRole as string | undefined;
      const organization = orgState.organization as
        | Record<string, unknown>
        | undefined;

      if (organization && userRole && userRole !== "OWNER") {
        const ownerId = organization.ownerId as string | undefined;
        if (ownerId) {
          const ownerSub = await convexQuery<ConvexSubscription>(
            "billing/queries:getActiveSubscription",
            { userId: ownerId },
          ).catch(() => null);

          if (ownerSub && isValidSubscription(ownerSub)) {
            const orgId =
              (organization._id as string) || (organization.id as string);
            const orgName = (organization.name as string) || "";
            return {
              hasAccess: true,
              onboardingComplete: user.onboardingComplete,
              subscription: {
                status: ownerSub.status,
                tierId: ownerSub.tierId || "",
                billingPeriod: ownerSub.billingPeriod || "monthly",
                currentPeriodEnd: ownerSub.currentPeriodEnd
                  ? new Date(ownerSub.currentPeriodEnd).toISOString()
                  : "",
              },
              organization: {
                id: orgId,
                name: orgName,
                role: userRole,
              },
            };
          }
        }
      }
    }

    // No valid subscription — check if onboarding is incomplete
    if (!user.onboardingComplete) {
      return {
        hasAccess: false,
        reason: "Onboarding not completed",
        redirectUrl: "/en/onboarding",
      };
    }

    // User completed onboarding but has no active subscription
    // If they previously selected a package, send them to reactivate (not generic pricing)
    if (user.selectedPackage) {
      const params = new URLSearchParams({
        tier: user.selectedPackage,
        ...(user.selectedBillingPeriod && {
          period: user.selectedBillingPeriod,
        }),
        ...(user.preferredCurrency && {
          currency: user.preferredCurrency,
        }),
      });
      return {
        hasAccess: false,
        reason: "No active subscription",
        redirectUrl: `/en/reactivate?${params.toString()}`,
      };
    }

    return {
      hasAccess: false,
      reason: "No active subscription",
      redirectUrl: "/en/pricing",
    };
  } catch (error) {
    logger.error("Dashboard access check error", error);
    return {
      hasAccess: false,
      reason: "System error",
      redirectUrl: "/en/onboarding",
    };
  }
}

/**
 * Check if a subscription is valid (active or trialing, not expired)
 */
function isValidSubscription(sub: ConvexSubscription): boolean {
  if (!ACTIVE_SUBSCRIPTION_STATUSES.has(sub.status)) return false;

  const now = Date.now();
  if (sub.status === "trialing") {
    const trialEnd = sub.trialEndsAt || sub.currentPeriodEnd;
    // If trialEnd is in the past but currentPeriodEnd is in the future,
    // the subscription has transitioned — treat as active
    if (trialEnd && trialEnd <= now && sub.currentPeriodEnd && sub.currentPeriodEnd > now) {
      return true;
    }
    return trialEnd ? trialEnd > now : false;
  }
  if (sub.status === "active") {
    return sub.currentPeriodEnd ? sub.currentPeriodEnd > now : true;
  }
  // pending_verification: user has paid but webhook status hasn't synced yet
  // Grant access with a 24-hour grace window
  if (sub.status === "pending_verification") {
    const createdWindow = sub.currentPeriodEnd
      ? sub.currentPeriodEnd > now
      : true;
    return createdWindow;
  }
  return false;
}
