/**
 * Billing Plans Hooks
 *
 * Provides access to the billing system's plans, features, and add-ons.
 * Used by platform admin for managing tenant subscriptions.
 */

import { useQuery } from '@tanstack/react-query';
import apiClient from '../api/client';

// Feature from billing system - the SINGLE SOURCE OF TRUTH
export interface BillingFeature {
  id: number;
  code: string;
  name: string;
  description: string;
  feature_type: 'boolean' | 'integer';
  // Dynamic feature management
  category: 'limits' | 'payments' | 'communication' | 'customization' | 'plugins' | 'advanced' | 'scheduling' | 'enterprise';
  tenant_field_name: string;  // Corresponding field on Tenant model
  display_order: number;
  is_overridable: boolean;
  depends_on: number | null;  // ID of parent feature
  depends_on_code: string | null;  // Code of parent feature (for convenience)
}

// Category metadata for display
export const FEATURE_CATEGORY_META: Record<BillingFeature['category'], { label: string; order: number }> = {
  limits: { label: 'Limits', order: 0 },
  payments: { label: 'Payments & Revenue', order: 1 },
  communication: { label: 'Communication', order: 2 },
  customization: { label: 'Customization', order: 3 },
  plugins: { label: 'Plugins & Automation', order: 4 },
  advanced: { label: 'Advanced Features', order: 5 },
  scheduling: { label: 'Scheduling', order: 6 },
  enterprise: { label: 'Enterprise & Security', order: 7 },
};

// Plan feature with value
export interface BillingPlanFeature {
  id: number;
  feature: BillingFeature;
  bool_value: boolean | null;
  int_value: number | null;
  value: boolean | number | null;
}

// Plan (logical grouping)
export interface BillingPlan {
  id: number;
  code: string;
  name: string;
  description: string;
  display_order: number;
  is_active: boolean;
  max_pages: number;
  allow_custom_domains: boolean;
  max_custom_domains: number;
}

// Plan version (specific offer with pricing and features)
export interface BillingPlanVersion {
  id: number;
  plan: BillingPlan;
  version: number;
  name: string;
  is_public: boolean;
  is_legacy: boolean;
  starts_at: string | null;
  ends_at: string | null;
  price_monthly_cents: number;
  price_yearly_cents: number;
  transaction_fee_percent: string;
  transaction_fee_fixed_cents: number;
  trial_days: number;
  sms_price_per_message_cents: number;
  masked_calling_price_per_minute_cents: number;
  proxy_number_monthly_fee_cents: number;
  default_auto_reload_enabled: boolean;
  default_auto_reload_threshold_cents: number;
  default_auto_reload_amount_cents: number;
  is_most_popular: boolean;
  show_price: boolean;
  marketing_features: string[];
  stripe_product_id: string;
  stripe_price_id_monthly: string;
  stripe_price_id_yearly: string;
  is_available: boolean;
  features: BillingPlanFeature[];
  subscriber_count?: number;
  created_at: string;
}

// Plan with all versions
export interface BillingPlanWithVersions {
  id: number;
  code: string;
  name: string;
  description: string;
  display_order: number;
  is_active: boolean;
  max_pages: number;
  allow_custom_domains: boolean;
  max_custom_domains: number;
  versions: BillingPlanVersion[];
  active_version: BillingPlanVersion | null;
  total_subscribers: number;
}

// Add-on product
export interface BillingAddOn {
  id: number;
  code: string;
  name: string;
  description: string;
  price_monthly_cents: number;
  price_one_time_cents: number;
  stripe_product_id: string;
  stripe_price_id: string;
  is_stackable: boolean;
  is_active: boolean;
  features: BillingPlanFeature[];
}

/**
 * Hook to get all billing plans with their versions (admin view)
 */
export const useBillingPlans = () => {
  return useQuery<BillingPlanWithVersions[]>({
    queryKey: ['billingPlans'],
    queryFn: async () => {
      const { data } = await apiClient.get('/billing/admin/plans/');
      return data;
    },
    staleTime: 5 * 60 * 1000, // 5 minutes
  });
};

/**
 * Hook to get the public plan catalog (available versions only)
 */
export const useBillingPlanCatalog = () => {
  return useQuery<BillingPlanVersion[]>({
    queryKey: ['billingPlanCatalog'],
    queryFn: async () => {
      const { data } = await apiClient.get('/billing/plans/');
      return data;
    },
    staleTime: 5 * 60 * 1000,
  });
};

/**
 * Hook to get all features
 */
export const useBillingFeatures = () => {
  return useQuery<BillingFeature[]>({
    queryKey: ['billingFeatures'],
    queryFn: async () => {
      const { data } = await apiClient.get('/billing/admin/features/');
      return data;
    },
    staleTime: 10 * 60 * 1000, // 10 minutes (features rarely change)
  });
};

/**
 * Hook to get available add-ons
 */
export const useBillingAddOns = () => {
  return useQuery<BillingAddOn[]>({
    queryKey: ['billingAddOns'],
    queryFn: async () => {
      const { data } = await apiClient.get('/billing/addons/');
      return data;
    },
    staleTime: 5 * 60 * 1000,
  });
};

// =============================================================================
// Helper Functions
// =============================================================================

/**
 * Get a feature value from a plan version's features array
 */
export function getFeatureValue(
  features: BillingPlanFeature[],
  featureCode: string
): boolean | number | null {
  const feature = features.find(f => f.feature.code === featureCode);
  if (!feature) return null;
  return feature.value;
}

/**
 * Get a boolean feature value (defaults to false if not found)
 */
export function getBooleanFeature(
  features: BillingPlanFeature[],
  featureCode: string
): boolean {
  const value = getFeatureValue(features, featureCode);
  return typeof value === 'boolean' ? value : false;
}

/**
 * Get an integer feature value (defaults to 0 if not found, null means unlimited)
 */
export function getIntegerFeature(
  features: BillingPlanFeature[],
  featureCode: string
): number | null {
  const value = getFeatureValue(features, featureCode);
  if (value === null || value === undefined) return null; // Unlimited
  return typeof value === 'number' ? value : 0;
}

/**
 * Convert a plan version's features to a flat object for form state
 * Maps feature codes to their values
 */
export function planFeaturesToFormState(
  planVersion: BillingPlanVersion | null
): Record<string, boolean | number | null> {
  if (!planVersion) return {};

  const state: Record<string, boolean | number | null> = {};

  for (const pf of planVersion.features) {
    state[pf.feature.code] = pf.value;
  }

  return state;
}

/**
 * Map old tier names to new plan codes
 */
export const TIER_TO_PLAN_CODE: Record<string, string> = {
  FREE: 'free',
  STARTER: 'starter',
  GROWTH: 'growth',
  PROFESSIONAL: 'pro', // Old name -> new code
  PRO: 'pro',
  ENTERPRISE: 'enterprise',
};

/**
 * Map new plan codes to display names
 */
export const PLAN_CODE_TO_NAME: Record<string, string> = {
  free: 'Free',
  starter: 'Starter',
  growth: 'Growth',
  pro: 'Pro',
  enterprise: 'Enterprise',
};

/**
 * Get the active plan version for a given plan code
 */
export function getActivePlanVersion(
  plans: BillingPlanWithVersions[],
  planCode: string
): BillingPlanVersion | null {
  const plan = plans.find(p => p.code === planCode);
  return plan?.active_version || null;
}

/**
 * Feature code mapping from old permission names to new feature codes
 */
export const PERMISSION_TO_FEATURE_CODE: Record<string, string> = {
  // Communication
  can_use_sms_reminders: 'sms_enabled',
  can_use_masked_phone_numbers: 'masked_calling_enabled',

  // Platform
  can_api_access: 'api_access',
  can_use_custom_domain: 'custom_domain',
  can_white_label: 'white_label',

  // Features
  can_accept_payments: 'payment_processing',
  can_use_mobile_app: 'mobile_app_access',
  advanced_reporting: 'advanced_reporting',
  priority_support: 'priority_support',
  dedicated_support: 'dedicated_account_manager',

  // Limits (integer features)
  max_users: 'max_users',
  max_resources: 'max_resources',
  max_locations: 'max_locations',
};

/**
 * Convert plan features to legacy permission format for backward compatibility
 */
export function planFeaturesToLegacyPermissions(
  planVersion: BillingPlanVersion | null
): Record<string, boolean | number> {
  if (!planVersion) return {};

  const permissions: Record<string, boolean | number> = {};

  // Map features to legacy permission names
  for (const pf of planVersion.features) {
    const code = pf.feature.code;
    const value = pf.value;

    // Direct feature code
    permissions[code] = value as boolean | number;

    // Also add with legacy naming for backward compatibility
    switch (code) {
      case 'sms_enabled':
        permissions.can_use_sms_reminders = value as boolean;
        break;
      case 'masked_calling_enabled':
        permissions.can_use_masked_phone_numbers = value as boolean;
        break;
      case 'api_access':
        permissions.can_api_access = value as boolean;
        permissions.can_connect_to_api = value as boolean;
        break;
      case 'custom_domain':
        permissions.can_use_custom_domain = value as boolean;
        break;
      case 'white_label':
        permissions.can_white_label = value as boolean;
        break;
      case 'remove_branding':
        permissions.can_white_label = permissions.can_white_label || (value as boolean);
        break;
      case 'payment_processing':
        permissions.can_accept_payments = value as boolean;
        break;
      case 'mobile_app_access':
        permissions.can_use_mobile_app = value as boolean;
        break;
      case 'advanced_reporting':
        permissions.advanced_reporting = value as boolean;
        break;
      case 'priority_support':
        permissions.priority_support = value as boolean;
        break;
      case 'dedicated_account_manager':
        permissions.dedicated_support = value as boolean;
        break;
      case 'integrations_enabled':
        permissions.can_use_webhooks = value as boolean;
        permissions.can_use_calendar_sync = value as boolean;
        break;
      case 'team_permissions':
        permissions.can_require_2fa = value as boolean;
        break;
      case 'audit_logs':
        permissions.can_download_logs = value as boolean;
        break;
      case 'custom_branding':
        permissions.can_customize_booking_page = value as boolean;
        break;
      case 'recurring_appointments':
        permissions.can_book_repeated_events = value as boolean;
        break;
    }
  }

  return permissions;
}
