import { NextFunction, Request, Response } from 'express'
import { prisma } from '../../lib/prisma'
import { getAccessLevel } from '../subscriptions/subscription.policy'
import { sendForbidden, sendUnauthorized } from '../../middleware/authHelpers'

export type SettingsFeatureKey =
  | 'settings.company_profile'
  | 'settings.public_contact'
  | 'settings.locale_currency'
  | 'settings.carplace_listing'
  | 'settings.branding_basic'
  | 'settings.branding_custom'
  | 'settings.branding_hero'
  | 'settings.renter_payments'
  | 'settings.rental_policies_basic'
  | 'settings.additional_driver_fees'
  | 'settings.insurance_policies'
  | 'settings.pricing_rules'
  | 'settings.accounting_defaults'
  | 'settings.accounting_scheduled_delivery'
  | 'settings.accounting_advanced_formats'

export type SettingsSectionKey =
  | 'company'
  | 'carplace'
  | 'payments'
  | 'rental-policies'
  | 'insurance'
  | 'pricing'
  | 'accounting'

type Locale = 'en' | 'fr' | 'ar'
type Plan = 'STARTER' | 'GROWTH' | 'PRO'
type SubscriptionStatus =
  | 'TRIALING'
  | 'ACTIVE'
  | 'PAYMENT_PENDING'
  | 'PAST_DUE'
  | 'SUSPENDED'
  | 'CANCELLED'
  | 'EXPIRED'
  | 'PAUSED'
  | 'UNPAID'

type MenuState = 'ENABLED' | 'LOCKED'

const ALL_PLANS: Plan[] = ['STARTER', 'GROWTH', 'PRO']
const GROWTH_PLUS: Plan[] = ['GROWTH', 'PRO']
const PRO_ONLY: Plan[] = ['PRO']

const SECTION_COPY: Record<Locale, Record<SettingsSectionKey, { label: string; description: string }>> = {
  en: {
    company: { label: 'Company Profile', description: 'Manage public company details and defaults.' },
    carplace: { label: 'Branding and Carplace', description: 'Control Carplace listing, logo, colors, and media.' },
    payments: { label: 'Payment Methods', description: 'Configure renter payment providers.' },
    'rental-policies': { label: 'Rental Policies', description: 'Set fuel, damage, and additional-driver policies.' },
    insurance: { label: 'Insurance Policies', description: 'Manage optional and required insurance products.' },
    pricing: { label: 'Pricing Rules', description: 'Automate surcharges, discounts, and driver-based pricing.' },
    accounting: { label: 'Accounting and Reports', description: 'Configure accounting defaults and report delivery.' },
  },
  fr: {
    company: { label: 'Profil entreprise', description: 'Gérez les informations publiques et les valeurs par défaut.' },
    carplace: { label: 'Marque et vitrine', description: 'Contrôlez la publication, le logo, les couleurs et les médias.' },
    payments: { label: 'Méthodes de paiement', description: 'Configurez les prestataires de paiement des locataires.' },
    'rental-policies': { label: 'Politiques de location', description: 'Définissez les règles carburant, dommages et conducteurs.' },
    insurance: { label: 'Polices d’assurance', description: 'Gérez les assurances optionnelles et obligatoires.' },
    pricing: { label: 'Règles tarifaires', description: 'Automatisez les suppléments, remises et règles conducteur.' },
    accounting: { label: 'Comptabilité et rapports', description: 'Configurez les paramètres comptables et l’envoi des rapports.' },
  },
  ar: {
    company: { label: 'ملف الشركة', description: 'إدارة بيانات الشركة العامة والإعدادات الافتراضية.' },
    carplace: { label: 'العلامة والواجهة', description: 'التحكم في الظهور والشعار والألوان ووسائط الواجهة.' },
    payments: { label: 'طرق الدفع', description: 'إعداد مزودي دفع المستأجرين.' },
    'rental-policies': { label: 'سياسات الإيجار', description: 'ضبط سياسات الوقود والأضرار والسائق الإضافي.' },
    insurance: { label: 'سياسات التأمين', description: 'إدارة منتجات التأمين الاختيارية والإلزامية.' },
    pricing: { label: 'قواعد التسعير', description: 'أتمتة الرسوم والخصومات وقواعد السائق.' },
    accounting: { label: 'المحاسبة والتقارير', description: 'إعداد الافتراضات المحاسبية وتسليم التقارير.' },
  },
}

export const SETTINGS_MENU_CATALOG: Array<{
  menuKey: SettingsSectionKey
  sectionKey: SettingsSectionKey
  iconKey: string
  sortOrder: number
  plans: Plan[]
  requiredPlan: Plan | null
}> = [
  { menuKey: 'company', sectionKey: 'company', iconKey: 'building', sortOrder: 10, plans: ALL_PLANS, requiredPlan: null },
  { menuKey: 'carplace', sectionKey: 'carplace', iconKey: 'palette', sortOrder: 20, plans: ALL_PLANS, requiredPlan: null },
  { menuKey: 'payments', sectionKey: 'payments', iconKey: 'credit-card', sortOrder: 30, plans: GROWTH_PLUS, requiredPlan: 'GROWTH' },
  { menuKey: 'rental-policies', sectionKey: 'rental-policies', iconKey: 'file-text', sortOrder: 40, plans: ALL_PLANS, requiredPlan: null },
  { menuKey: 'insurance', sectionKey: 'insurance', iconKey: 'shield', sortOrder: 50, plans: GROWTH_PLUS, requiredPlan: 'GROWTH' },
  { menuKey: 'pricing', sectionKey: 'pricing', iconKey: 'tags', sortOrder: 60, plans: GROWTH_PLUS, requiredPlan: 'GROWTH' },
  { menuKey: 'accounting', sectionKey: 'accounting', iconKey: 'bar-chart', sortOrder: 70, plans: GROWTH_PLUS, requiredPlan: 'GROWTH' },
]

const FEATURE_PLANS: Record<SettingsFeatureKey, { plans: Plan[]; requiredPlan: Plan | null }> = {
  'settings.company_profile': { plans: ALL_PLANS, requiredPlan: null },
  'settings.public_contact': { plans: ALL_PLANS, requiredPlan: null },
  'settings.locale_currency': { plans: ALL_PLANS, requiredPlan: null },
  'settings.carplace_listing': { plans: ALL_PLANS, requiredPlan: null },
  'settings.branding_basic': { plans: ALL_PLANS, requiredPlan: null },
  'settings.branding_custom': { plans: GROWTH_PLUS, requiredPlan: 'GROWTH' },
  'settings.branding_hero': { plans: GROWTH_PLUS, requiredPlan: 'GROWTH' },
  'settings.renter_payments': { plans: GROWTH_PLUS, requiredPlan: 'GROWTH' },
  'settings.rental_policies_basic': { plans: ALL_PLANS, requiredPlan: null },
  'settings.additional_driver_fees': { plans: GROWTH_PLUS, requiredPlan: 'GROWTH' },
  'settings.insurance_policies': { plans: GROWTH_PLUS, requiredPlan: 'GROWTH' },
  'settings.pricing_rules': { plans: GROWTH_PLUS, requiredPlan: 'GROWTH' },
  'settings.accounting_defaults': { plans: GROWTH_PLUS, requiredPlan: 'GROWTH' },
  'settings.accounting_scheduled_delivery': { plans: PRO_ONLY, requiredPlan: 'PRO' },
  'settings.accounting_advanced_formats': { plans: PRO_ONLY, requiredPlan: 'PRO' },
}

export function normalizeSettingsLocale(value?: string): Locale {
  return value === 'fr' || value === 'ar' ? value : 'en'
}

async function getSubscription(companyId: string) {
  const subscriptionModel = (prisma as any).subscription
  if (!subscriptionModel?.findUnique) {
    return {
      plan: 'GROWTH' as Plan,
      subscriptionStatus: 'ACTIVE' as SubscriptionStatus,
      currentPeriodEnd: null,
      trialEndAt: null,
    }
  }

  const subscription = await subscriptionModel.findUnique({ where: { companyId } })
  return {
    plan: subscription?.plan ?? 'STARTER',
    subscriptionStatus: subscription?.status ?? 'EXPIRED',
    currentPeriodEnd: subscription?.currentPeriodEnd?.toISOString() ?? null,
    trialEndAt: subscription?.trialEndAt?.toISOString() ?? null,
  }
}

function statusAllowsAvailability(status: SubscriptionStatus) {
  return getAccessLevel(status) !== 'none'
}

function statusAllowsEditing(status: SubscriptionStatus, featureKey: SettingsFeatureKey) {
  const accessLevel = getAccessLevel(status)
  if (accessLevel === 'full') return true
  if (status === 'PAST_DUE') {
    return [
      'settings.company_profile',
      'settings.public_contact',
      'settings.locale_currency',
      'settings.carplace_listing',
      'settings.branding_basic',
      'settings.rental_policies_basic',
    ].includes(featureKey)
  }
  return false
}

export async function resolveSettingsEntitlements(companyId: string) {
  const subscription = await getSubscription(companyId)
  const accessLevel = getAccessLevel(subscription.subscriptionStatus)
  const features = Object.fromEntries(
    Object.entries(FEATURE_PLANS).map(([featureKey, assignment]) => {
      const assigned = assignment.plans.includes(subscription.plan)
      const available = assigned && statusAllowsAvailability(subscription.subscriptionStatus)
      const editable = available && statusAllowsEditing(subscription.subscriptionStatus, featureKey as SettingsFeatureKey)
      return [featureKey, {
        available,
        editable,
        requiredPlan: assigned ? null : assignment.requiredPlan,
        reason: available ? null : assigned ? 'subscription_status_restricted' : 'plan_required',
      }]
    }),
  )

  return {
    plan: subscription.plan,
    subscriptionStatus: subscription.subscriptionStatus,
    currentPeriodEnd: subscription.currentPeriodEnd,
    trialEndAt: subscription.trialEndAt,
    accessLevel,
    features,
  }
}

export async function resolveSettingsMenu(companyId: string, locale: Locale) {
  const entitlements = await resolveSettingsEntitlements(companyId)
  return {
    version: 1,
    items: SETTINGS_MENU_CATALOG.map((item) => {
      const assigned = item.plans.includes(entitlements.plan)
      const coreAvailable = entitlements.accessLevel !== 'none' || item.sectionKey === 'company'
      const state: MenuState = assigned && coreAvailable ? 'ENABLED' : 'LOCKED'
      const copy = SECTION_COPY[locale][item.sectionKey]
      return {
        menuKey: item.menuKey,
        sectionKey: item.sectionKey,
        label: copy.label,
        description: copy.description,
        iconKey: item.iconKey,
        sortOrder: item.sortOrder,
        state,
        requiredPlan: state === 'LOCKED' ? item.requiredPlan : null,
      }
    }),
  }
}

export function requireSettingsFeature(featureKey: SettingsFeatureKey) {
  return async (req: Request, res: Response, next: NextFunction) => {
    if (!req.companyId) return sendUnauthorized(res, 'unauthenticated', 'Authentication required')

    const entitlements = await resolveSettingsEntitlements(req.companyId)
    const feature = entitlements.features[featureKey]
    if (!feature?.editable) {
      return sendForbidden(res, 'feature_unavailable', 'This settings feature is not available for your current subscription.', {
        featureKey,
        requiredPlan: feature?.requiredPlan ?? null,
        subscriptionStatus: entitlements.subscriptionStatus,
        accessLevel: entitlements.accessLevel,
      })
    }

    next()
  }
}
