/**
 * Plan configuration — single source of truth for what each plan
 * includes. Read by:
 *   - useFeatureGate() / <FeatureGate /> on the client
 *   - requirePlanFeature() on the server (API route guards)
 *   - the pricing page's comparison table
 *   - the upgrade modal (recommends the cheapest plan containing
 *     the locked feature)
 *
 * Keep the `features` string[] in sync with the feature keys used
 * by FeatureGate wrappers — a typo here becomes a silent lockout.
 *
 * Prices on this table match the cards on /pricing. Changing one
 * must update the other.
 */

export type PlanId =
  | "trial"
  | "growth"
  | "professional"
  | "agency"
  | "agency_pro"
  | "enterprise";

export type BillingCycle = "monthly" | "annual";

// ─── Feature keys ─────────────────────────────────────────────────
//
// Stable string keys used by the FeatureGate wrappers + API plan
// checks. Renaming one is a breaking change for every consumer —
// add new keys rather than repurposing existing ones.
export type FeatureKey =
  // Always-available (no gate):
  | "dashboard"
  | "site_tag_analytics"
  | "gsc_integration"
  | "ga4_integration"
  | "technical_audit"
  | "content_intel"
  | "ai_strategist"
  | "keyword_research"
  | "broken_links"
  | "core_web_intelligence"
  | "signals_center"
  // Professional+:
  | "rank_tracker"
  | "competitor_intel"
  | "ai_visibility"
  | "backlinks"
  | "industry_intel"
  | "schema_generator"
  | "report_studio"
  | "seo_content_brief"
  | "page_launch_tracker"
  | "session_explorer"
  | "ux_frustration"
  | "heatmaps"
  | "link_inspector"
  | "llmo_content_brief"
  | "content_intel_full"
  | "report_studio_full"
  // Professional+:
  | "ai_recommendations"
  | "competitive_ai_alerts"
  // Agency+:
  | "ai_roi_dashboard"
  | "auto_query_expansion"
  | "content_brief_trigger"
  | "ai_forecasting"
  // Agency+:
  | "writing_assistant"
  | "page_studio"
  | "client_portal"
  | "custom_domain"
  | "email_reports"
  | "client_management"
  | "conversion_intelligence"
  | "topic_map"
  | "paid_media"
  | "ott_attribution"
  | "household_clustering"
  | "visitor_identity_graph"
  | "channel_classification"
  // Agency Pro+:
  | "priority_support"
  | "api_access"
  | "bulk_operations";

// ─── Plan shape ───────────────────────────────────────────────────

export interface PlanLimits {
  maxBrands: number | "unlimited";
  /** Team seats included in the plan. Going over requires an
   *  additional-seat add-on (priced in PLAN_ADDONS.seatPricePerPlan). */
  seats: number | "unlimited";
  aiCredits: number | "unlimited";
  rankKeywords: number | "unlimited";
  competitorsPerBrand: number | "unlimited";
  contentBriefs: number | "unlimited";
  schemaGenerations: number | "unlimited";
  dataForSeoLookups: number | "unlimited";
  siteTagEvents: number | "unlimited";
  emailSchedules: number | "unlimited";
  reportExports: number | "unlimited";
}

export interface Plan {
  id: PlanId;
  name: string;
  monthlyPrice: number | null;         // null = Enterprise (custom)
  annualMonthlyPrice: number | null;
  annualSavings: number | null;        // dollars saved per year vs monthly
  limits: PlanLimits;
  features: FeatureKey[] | ["*"];      // ["*"] = wildcard (all features)
}

const GROWTH_FEATURES: FeatureKey[] = [
  // Base kit everyone gets.
  "site_tag_analytics", "dashboard", "gsc_integration", "ga4_integration",
  "technical_audit", "content_intel", "ai_strategist", "keyword_research",
  "broken_links", "core_web_intelligence", "signals_center",
  // Growth extras per spec:
  "rank_tracker", "page_studio", "conversion_intelligence",
  "seo_content_brief", "report_studio",
];

const PROFESSIONAL_FEATURES: FeatureKey[] = [
  ...GROWTH_FEATURES,
  "competitor_intel", "ai_visibility", "backlinks",
  "schema_generator", "page_launch_tracker", "email_reports",
  "session_explorer", "ux_frustration", "heatmaps", "link_inspector",
  "llmo_content_brief", "content_intel_full", "report_studio_full",
  "ai_recommendations", "competitive_ai_alerts",
];

const AGENCY_FEATURES: FeatureKey[] = [
  ...PROFESSIONAL_FEATURES,
  "writing_assistant",
  "client_portal", "custom_domain", "client_management",
  "industry_intel", "topic_map",
  "paid_media", "ott_attribution", "household_clustering",
  "visitor_identity_graph", "channel_classification",
  "ai_roi_dashboard", "auto_query_expansion", "content_brief_trigger", "ai_forecasting",
];

const AGENCY_PRO_FEATURES: FeatureKey[] = [
  ...AGENCY_FEATURES,
  "priority_support", "api_access", "bulk_operations",
];

// ─── Plan registry ────────────────────────────────────────────────
// Order matters — iteration order determines the suggestion logic
// in the upgrade modal (it picks the first plan containing the
// requested feature), and upgrade paths climb in this order.

export const PLANS: Record<PlanId, Plan> = {
  trial: {
    // Trial grants Professional-level entitlements for 14 days.
    // After expiry the caller is responsible for downgrading to
    // growth; feature checks treat trial as professional until
    // the expiry stamp has passed.
    id: "trial",
    name: "Free Trial",
    monthlyPrice: 0,
    annualMonthlyPrice: 0,
    annualSavings: null,
    limits: {
      maxBrands: 2,
      seats: 5,              // Professional-equivalent
      aiCredits: 1140,
      rankKeywords: 500,
      competitorsPerBrand: 5,
      contentBriefs: 40,
      schemaGenerations: 20,
      dataForSeoLookups: 1000,
      siteTagEvents: 500_000,
      emailSchedules: 3,
      reportExports: 50,
    },
    features: PROFESSIONAL_FEATURES,
  },
  growth: {
    id: "growth",
    name: "Growth",
    monthlyPrice: 299,
    annualMonthlyPrice: 249,
    annualSavings: 598,
    limits: {
      maxBrands: 3,
      seats: 2,
      aiCredits: 235,
      rankKeywords: 50,
      competitorsPerBrand: 2,
      contentBriefs: 10,
      schemaGenerations: 10,
      dataForSeoLookups: 50,
      siteTagEvents: 50_000,
      emailSchedules: 0,
      reportExports: 0,
    },
    features: GROWTH_FEATURES,
  },
  professional: {
    id: "professional",
    name: "Professional",
    monthlyPrice: 499,
    annualMonthlyPrice: 416,
    annualSavings: 998,
    limits: {
      maxBrands: 10,
      seats: 5,
      aiCredits: 1140,
      rankKeywords: 500,
      competitorsPerBrand: 5,
      contentBriefs: 40,
      schemaGenerations: 20,
      dataForSeoLookups: 1000,
      siteTagEvents: 500_000,
      emailSchedules: 5,
      reportExports: 50,
    },
    features: PROFESSIONAL_FEATURES,
  },
  agency: {
    id: "agency",
    name: "Agency",
    monthlyPrice: 1499,
    annualMonthlyPrice: 1249,
    annualSavings: 2998,
    limits: {
      maxBrands: 25,
      seats: 10,
      aiCredits: 5600,
      rankKeywords: 2000,
      competitorsPerBrand: "unlimited",
      contentBriefs: 200,
      schemaGenerations: 100,
      dataForSeoLookups: 5000,
      siteTagEvents: 2_000_000,
      emailSchedules: 25,
      reportExports: 500,
    },
    features: AGENCY_FEATURES,
  },
  agency_pro: {
    id: "agency_pro",
    name: "Agency Pro",
    monthlyPrice: 3499,
    annualMonthlyPrice: 2916,
    annualSavings: 6998,
    limits: {
      maxBrands: 50,
      seats: 25,
      aiCredits: 15000,
      rankKeywords: 5000,
      competitorsPerBrand: 15,
      contentBriefs: 2000,
      schemaGenerations: 500,
      dataForSeoLookups: 15000,
      siteTagEvents: 10_000_000,
      emailSchedules: 100,
      reportExports: 2000,
    },
    features: AGENCY_PRO_FEATURES,
  },
  enterprise: {
    id: "enterprise",
    name: "Enterprise",
    monthlyPrice: null,
    annualMonthlyPrice: null,
    annualSavings: null,
    limits: {
      maxBrands: "unlimited",
      seats: "unlimited",
      aiCredits: "unlimited",
      rankKeywords: "unlimited",
      competitorsPerBrand: "unlimited",
      contentBriefs: "unlimited",
      schemaGenerations: "unlimited",
      dataForSeoLookups: "unlimited",
      siteTagEvents: "unlimited",
      emailSchedules: "unlimited",
      reportExports: "unlimited",
    },
    features: ["*"],
  },
};

// ─── Add-on pricing ───────────────────────────────────────────────
//
// Additional-seat price varies by plan (cheaper at higher tiers as a
// volume incentive). Keeping the matrix here next to PLANS so changes
// to seat counts and prices never drift between the pricing page, the
// add-ons strip, and the seat-limit upgrade modal.

export const PLAN_ADDONS = {
  seatPricePerPlan: {
    trial: 25,
    growth: 29,
    professional: 25,
    agency: 19,
    agency_pro: 15,
    enterprise: 0, // included
  } as Record<PlanId, number>,
  additionalBrandPrice: {
    trial: 79,
    growth: 79,
    professional: 69,
    agency: 59,
    agency_pro: 49,
    enterprise: 0,
  } as Record<PlanId, number>,
  aiCreditPack: { credits: 500, price: 49 },
  dataForSeoBoost: { lookups: 5000, price: 29 },
  prioritySupportUpgrade: { price: 99 },
};

// ─── Runtime helpers ──────────────────────────────────────────────

export interface PlanContext {
  plan: PlanId;
  /** Only meaningful when plan === "trial". After this the plan
   *  drops back to growth on the server; the client also checks
   *  this so the UI mirrors the entitlement state. */
  planExpiresAt?: Date | null;
}

/** Does the given plan include the feature? Trials act as
 *  Professional until expired; Enterprise wildcard returns true
 *  for any feature. */
export function planHasFeature(ctx: PlanContext, feature: FeatureKey): boolean {
  const effective = resolveEffectivePlan(ctx);
  const plan = PLANS[effective];
  if (!plan) return false;
  if (plan.features[0] === "*") return true;
  return (plan.features as FeatureKey[]).includes(feature);
}

/** Resolve the effective plan for gating purposes. Expired trials
 *  collapse to "growth". Unknown plan ids fall back to "growth"
 *  (safe default — least access). */
export function resolveEffectivePlan(ctx: PlanContext): PlanId {
  if (ctx.plan === "trial") {
    const expiry = ctx.planExpiresAt ? new Date(ctx.planExpiresAt) : null;
    if (!expiry || expiry.getTime() > Date.now()) return "trial";
    return "growth";
  }
  if (PLANS[ctx.plan]) return ctx.plan;
  return "growth";
}

/** Find the cheapest plan that includes a given feature. Used by
 *  the upgrade modal's recommendation logic. Skips the trial plan
 *  (can't "upgrade" to a trial) and Enterprise (requires sales). */
export function recommendPlanFor(feature: FeatureKey): PlanId | null {
  const paidOrder: PlanId[] = ["growth", "professional", "agency", "agency_pro"];
  for (const id of paidOrder) {
    const plan = PLANS[id];
    if (plan.features[0] === "*" || (plan.features as FeatureKey[]).includes(feature)) {
      return id;
    }
  }
  // Only Enterprise has this feature → tell the caller to book a demo.
  return "enterprise";
}

/** Numeric comparison helper — is planA at least planB? Used for
 *  "show this only if the user is on Professional or higher" UI. */
export function planAtLeast(a: PlanId, b: PlanId): boolean {
  const rank: Record<PlanId, number> = {
    trial: 2, // trial ~= professional while active
    growth: 1,
    professional: 2,
    agency: 3,
    agency_pro: 4,
    enterprise: 5,
  };
  return rank[a] >= rank[b];
}

/** Display helper for price strings on the upgrade modal. */
export function formatPlanPrice(plan: Plan, cycle: BillingCycle): string {
  const price = cycle === "annual" ? plan.annualMonthlyPrice : plan.monthlyPrice;
  if (price == null) return "Custom";
  return `$${price.toLocaleString()}/mo`;
}
