// components/subscription/PlanComparison.tsx
'use client';

import { useState } from 'react';
import {
  PLAN_FEATURES,
  PLAN_DISPLAY_NAMES,
  PLAN_PRICES,
  TIER_ORDER,
  HIGHEST_TIER,
  LOWEST_TIER,
  TierName,
  BillingInterval,
  getTierRank,
  getAvailableIntervals,
} from '@/lib/plan-features';
import { DowngradeModal } from './DowngradeModal';
import styles from './PlanComparison.module.css';

/**
 * Maps backend error messages to user-friendly display messages.
 * Prevents exposing internal state or technical details to users.
 */
function getUserFriendlyError(
  backendError: string,
  action: 'upgrade' | 'downgrade' = 'upgrade'
): string {
  // Map specific backend errors to user-friendly messages
  const errorMap: Record<string, string> = {
    // Auth errors
    Unauthorized: `Please sign in to ${action} your subscription.`,
    // Account state errors
    'Dealer account not found': 'Your account could not be found. Please contact support.',
    'No active subscription found': `You need an active subscription to ${action}. Please contact support.`,
    'Account must be active to upgrade':
      'Your account must be active to upgrade. Please contact support if you believe this is an error.',
    'Account must be active to change subscription':
      'Your account must be active to change your subscription. Please contact support if you believe this is an error.',
    // Validation errors
    'Can only upgrade to a higher tier':
      'You can only upgrade to a higher tier than your current plan.',
    'Can only downgrade to a lower tier. Use the upgrade API for higher tiers.':
      'You can only downgrade to a lower tier than your current plan.',
    'Cannot downgrade from starter tier - it is the lowest tier':
      'You are already on the Starter plan, which is the lowest tier available.',
    'Invalid target tier. Must be: growth, enhanced, or professional':
      'Please select a valid plan to upgrade to.',
    'Invalid target tier. Must be: starter, growth, or enhanced':
      'Please select a valid plan to downgrade to.',
    'Invalid billing interval. Must be: monthly or annual':
      'Please select monthly or annual billing.',
    'You must acknowledge that you will lose features by downgrading':
      'Please confirm that you understand you will lose access to certain features.',
    // Server/config errors
    'Invalid subscription state':
      'There was an issue with your subscription. Please refresh the page and try again.',
    'Plan configuration error':
      'This plan is temporarily unavailable. Please try again later or contact support.',
    'Subscription configuration error':
      'There was an issue with your subscription configuration. Please contact support.',
    // Stripe errors
    'Unable to access subscription. Please try again.':
      "We couldn't connect to our payment system. Please try again in a few moments.",
    'Failed to process upgrade. If you were charged, please contact support.':
      'The upgrade could not be completed. If you see a charge on your account, please contact support for assistance.',
    'Failed to process downgrade. Please try again.':
      'The downgrade could not be completed. Please try again or contact support.',
    // Race condition
    'Subscription was already updated. Please refresh the page.':
      'Your subscription was already updated. Please refresh the page to see your new plan.',
    // Rate limiting
    'Rate limit exceeded': 'Too many requests. Please wait a moment and try again.',
  };

  // Check for exact match first
  if (errorMap[backendError]) {
    return errorMap[backendError];
  }

  // Check for partial matches (for errors that might have dynamic content)
  if (backendError.includes('billing is not available for')) {
    return 'The selected billing option is not available for this plan. Please choose a different option.';
  }

  if (backendError.includes('rate limit') || backendError.includes('Rate limit')) {
    return 'Too many requests. Please wait a moment and try again.';
  }

  // Default fallback - don't expose the raw backend error
  return `Something went wrong while processing your ${action}. Please try again or contact support if the problem persists.`;
}

interface PlanComparisonProps {
  currentTier: TierName;
  currentBillingInterval: BillingInterval | null;
}

export function PlanComparison({ currentTier, currentBillingInterval }: PlanComparisonProps) {
  const [loadingTier, setLoadingTier] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [confirmingTier, setConfirmingTier] = useState<TierName | null>(null);
  const [selectedInterval, setSelectedInterval] = useState<BillingInterval>('monthly');
  // Downgrade state
  const [downgradingTier, setDowngradingTier] = useState<TierName | null>(null);
  const [downgradeError, setDowngradeError] = useState<string | null>(null);
  const [isDowngrading, setIsDowngrading] = useState(false);

  const currentRank = getTierRank(currentTier);
  const isHighestTier = currentTier === HIGHEST_TIER;
  const isLowestTier = currentTier === LOWEST_TIER;

  const handleUpgradeClick = (targetTier: TierName) => {
    // Default to monthly if available, otherwise annual
    const availableIntervals = getAvailableIntervals(targetTier);
    setSelectedInterval(availableIntervals.includes('monthly') ? 'monthly' : 'annual');
    setConfirmingTier(targetTier);
    setError(null);
  };

  const [isSubmitting, setIsSubmitting] = useState(false);

  const handleConfirmUpgrade = async () => {
    if (!confirmingTier || isSubmitting) return;

    setIsSubmitting(true);
    setLoadingTier(confirmingTier);

    try {
      const response = await fetch('/api/checkout/upgrade', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          targetTier: confirmingTier,
          billingInterval: selectedInterval,
        }),
      });

      const data = await response.json();

      if (!response.ok) {
        throw new Error(data.error || 'Failed to upgrade subscription');
      }

      // Upgrade successful - reload page to reflect new tier
      // Include partialSuccess flag if tier handlers failed (user may need to refresh for full feature access)
      const redirectUrl = data.partialSuccess
        ? '/dashboard/subscription?upgraded=true&partialSuccess=true'
        : '/dashboard/subscription?upgraded=true';
      window.location.href = redirectUrl;
    } catch (err) {
      // Map backend errors to user-friendly messages
      const rawError = err instanceof Error ? err.message : 'Unknown error';
      setError(getUserFriendlyError(rawError));
      setLoadingTier(null);
      setIsSubmitting(false);
      // Keep modal open so user can retry
    }
  };

  const handleCancelUpgrade = () => {
    setConfirmingTier(null);
  };

  // Downgrade handlers
  const handleDowngradeClick = (targetTier: TierName) => {
    setDowngradingTier(targetTier);
    setDowngradeError(null);
  };

  const handleConfirmDowngrade = async (
    billingInterval: BillingInterval,
    acknowledgeFeatureLoss: boolean
  ) => {
    if (!downgradingTier || isDowngrading) return;

    setIsDowngrading(true);
    setDowngradeError(null);

    try {
      const response = await fetch('/api/subscription/downgrade', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          targetTier: downgradingTier,
          billingInterval,
          acknowledgeFeatureLoss,
        }),
      });

      const data = await response.json();

      if (!response.ok) {
        throw new Error(data.error || 'Failed to downgrade subscription');
      }

      // Downgrade successful - reload page to reflect new tier
      // Include partialSuccess flag if tier handlers failed (user may need to refresh for full feature update)
      const redirectUrl = data.partialSuccess
        ? '/dashboard/subscription?downgraded=true&partialSuccess=true'
        : '/dashboard/subscription?downgraded=true';
      window.location.href = redirectUrl;
    } catch (err) {
      const rawError = err instanceof Error ? err.message : 'Unknown error';
      setDowngradeError(getUserFriendlyError(rawError, 'downgrade'));
      setIsDowngrading(false);
    }
  };

  const handleCancelDowngrade = () => {
    setDowngradingTier(null);
    setDowngradeError(null);
  };

  // Helper to format price display
  const formatPrice = (tier: TierName, interval: BillingInterval): string => {
    const pricing = PLAN_PRICES[tier];
    if (interval === 'monthly') {
      return pricing.monthly ? `$${pricing.monthly}/mo` : `$${pricing.annualMonthly}/mo`;
    }
    return `$${pricing.annual}/yr`;
  };

  // Get display price for current tier
  const getCurrentTierDisplay = (): string => {
    const pricing = PLAN_PRICES[currentTier];
    // Show annual if starter, otherwise monthly equivalent
    if (currentTier === 'starter') {
      return `$${pricing.annual}/yr`;
    }
    return pricing.monthly ? `$${pricing.monthly}/mo` : `$${pricing.annualMonthly}/mo`;
  };

  // Get context-aware proration notice based on billing interval transition
  const getProrationNotice = (
    currentInterval: BillingInterval | null,
    targetInterval: BillingInterval
  ): string => {
    // If we don't know the current interval, show a generic but accurate message
    if (!currentInterval) {
      return targetInterval === 'monthly'
        ? 'Stripe will calculate any prorated charges based on your current billing cycle.'
        : 'You will be charged the annual amount. Stripe will apply any credits from your current plan.';
    }

    // Same interval: standard proration
    if (currentInterval === targetInterval) {
      return targetInterval === 'monthly'
        ? 'You will be charged a prorated amount for the price difference immediately.'
        : 'You will be charged the prorated annual difference. Your subscription renews in one year.';
    }

    // Cross-interval transitions
    if (currentInterval === 'annual' && targetInterval === 'monthly') {
      return 'You will receive credit for your unused annual time. Monthly billing starts immediately.';
    }

    // monthly → annual
    return 'You will be charged the full annual amount, minus credit for your current monthly period.';
  };

  // Determine the title based on current tier
  const getTitle = () => {
    if (isHighestTier) return 'Plan Comparison';
    if (isLowestTier) return 'Upgrade Your Plan';
    return 'Change Your Plan';
  };

  return (
    <div className={styles.container}>
      <div className={styles.header}>
        <h2 className={styles.title}>{getTitle()}</h2>
        {isHighestTier && (
          <p className={styles.headerSubtitle}>
            You&apos;re on the Professional plan — our highest tier with all features included.
          </p>
        )}
      </div>

      {error && <div className={styles.errorMessage}>{error}</div>}

      <div className={styles.tableWrapper}>
        <table className={styles.table}>
          <thead>
            <tr>
              <th>Features</th>
              {TIER_ORDER.map((tier) => {
                const isCurrent = tier === currentTier;
                return (
                  <th key={tier} className={isCurrent ? styles.currentTier : undefined}>
                    {PLAN_DISPLAY_NAMES[tier]}
                    {isCurrent && <span className={styles.currentBadge}>Current</span>}
                  </th>
                );
              })}
            </tr>
          </thead>
          <tbody>
            {PLAN_FEATURES.map((feature) => (
              <tr key={feature.name}>
                <td className={styles.featureName}>{feature.name}</td>
                {TIER_ORDER.map((tier) => {
                  const hasFeature = feature[tier];
                  const isCurrent = tier === currentTier;
                  const isLowerTier = getTierRank(tier) < currentRank;

                  return (
                    <td
                      key={tier}
                      className={`${isCurrent ? styles.currentTier : ''} ${isLowerTier ? styles.grayed : ''}`}
                    >
                      {hasFeature ? (
                        <span className={styles.check}>✓</span>
                      ) : (
                        <span className={styles.dash}>—</span>
                      )}
                    </td>
                  );
                })}
              </tr>
            ))}
            <tr className={styles.upgradeRow}>
              <td></td>
              {TIER_ORDER.map((tier) => {
                const isCurrent = tier === currentTier;
                const tierRank = getTierRank(tier);
                const isLowerTier = tierRank < currentRank;
                const canUpgrade = tierRank > currentRank;
                const canDowngradeToTier = isLowerTier && !isLowestTier;
                const isLoading = loadingTier === tier;

                return (
                  <td key={tier} className={isCurrent ? styles.currentTier : undefined}>
                    {canUpgrade ? (
                      <button
                        className={styles.upgradeButton}
                        onClick={() => handleUpgradeClick(tier)}
                        disabled={isLoading || loadingTier !== null || isDowngrading}
                      >
                        {isLoading ? (
                          <span className={styles.loading}>
                            <span className={styles.spinner} />
                            Loading...
                          </span>
                        ) : (
                          `Upgrade to ${PLAN_DISPLAY_NAMES[tier]}`
                        )}
                      </button>
                    ) : isCurrent ? (
                      <span className={styles.currentPlanText}>Current Plan</span>
                    ) : canDowngradeToTier ? (
                      <button
                        className={styles.downgradeButton}
                        onClick={() => handleDowngradeClick(tier)}
                        disabled={isDowngrading || loadingTier !== null}
                      >
                        Downgrade to {PLAN_DISPLAY_NAMES[tier]}
                      </button>
                    ) : isLowerTier ? (
                      <span className={styles.grayed}>—</span>
                    ) : null}
                  </td>
                );
              })}
            </tr>
          </tbody>
        </table>
      </div>

      {/* Confirmation Modal */}
      {confirmingTier && (
        <div className={styles.modalOverlay} onClick={handleCancelUpgrade}>
          <div className={styles.modal} onClick={(e) => e.stopPropagation()}>
            <h3 className={styles.modalTitle}>Confirm Upgrade</h3>
            <p className={styles.modalText}>
              You are upgrading from <strong>{PLAN_DISPLAY_NAMES[currentTier]}</strong> to{' '}
              <strong>{PLAN_DISPLAY_NAMES[confirmingTier]}</strong>.
            </p>

            {/* Billing Interval Toggle */}
            {getAvailableIntervals(confirmingTier).length > 1 && (
              <div className={styles.intervalToggle}>
                <span className={styles.intervalLabel}>Billing:</span>
                <div className={styles.intervalButtons}>
                  <button
                    type="button"
                    className={`${styles.intervalButton} ${selectedInterval === 'monthly' ? styles.intervalButtonActive : ''}`}
                    onClick={() => setSelectedInterval('monthly')}
                  >
                    Monthly
                  </button>
                  <button
                    type="button"
                    className={`${styles.intervalButton} ${selectedInterval === 'annual' ? styles.intervalButtonActive : ''}`}
                    onClick={() => setSelectedInterval('annual')}
                  >
                    Annual
                  </button>
                </div>
              </div>
            )}

            <div className={styles.priceComparison}>
              <div className={styles.priceItem}>
                <span className={styles.priceLabel}>Current</span>
                <span className={styles.priceValue}>{getCurrentTierDisplay()}</span>
              </div>
              <div className={styles.priceArrow}>→</div>
              <div className={styles.priceItem}>
                <span className={styles.priceLabel}>New</span>
                <span className={styles.priceValue}>
                  {formatPrice(confirmingTier, selectedInterval)}
                </span>
              </div>
            </div>

            <p className={styles.prorationNotice}>
              {getProrationNotice(currentBillingInterval, selectedInterval)}
            </p>

            {error && <div className={styles.modalError}>{error}</div>}

            <div className={styles.modalActions}>
              <button
                className={styles.cancelButton}
                onClick={handleCancelUpgrade}
                disabled={isSubmitting}
              >
                Cancel
              </button>
              <button
                className={styles.confirmButton}
                onClick={handleConfirmUpgrade}
                disabled={isSubmitting}
              >
                {isSubmitting ? (
                  <span className={styles.loading}>
                    <span className={styles.spinner} />
                    Processing...
                  </span>
                ) : (
                  'Confirm Upgrade'
                )}
              </button>
            </div>
          </div>
        </div>
      )}

      {/* Downgrade Confirmation Modal */}
      {downgradingTier && (
        <DowngradeModal
          isOpen={true}
          currentTier={currentTier}
          currentBillingInterval={currentBillingInterval}
          targetTier={downgradingTier}
          onConfirm={handleConfirmDowngrade}
          onCancel={handleCancelDowngrade}
          isSubmitting={isDowngrading}
          error={downgradeError}
        />
      )}
    </div>
  );
}

export default PlanComparison;
