/**
 * Agentic Readiness Score v2.0
 * Algorithm based on 6-dimension methodology with continuous normalization
 */

import type { TierKey, SubFactor, AgenticReadinessResult, CustomerSegment } from '../types';
import { AGENTIC_READINESS_WEIGHTS, AGENTIC_READINESS_THRESHOLDS } from '../constants';

export interface AgenticReadinessInput {
  // Basic data (SILVER)
  volumen_mes: number;
  aht_values: number[];
  escalation_rate: number;
  cpi_humano: number;
  volumen_anual: number;

  // Advanced data (GOLD)
  structured_fields_pct?: number;
  exception_rate?: number;
  hourly_distribution?: number[];
  off_hours_pct?: number;
  csat_values?: number[];
  motivo_contacto_entropy?: number;
  resolucion_entropy?: number;

  // Tier
  tier: TierKey;
}

/**
 * SUB-FACTOR 1: REPEATABILITY (25%)
 * Based on monthly volume with logistic normalization
 */
function calculateRepeatabilityScore(volumen_mes: number): SubFactor {
  const { k, x0 } = AGENTIC_READINESS_THRESHOLDS.repetitividad;

  // Logistic function: score = 10 / (1 + exp(-k * (volume - x0)))
  const score = 10 / (1 + Math.exp(-k * (volumen_mes - x0)));

  return {
    name: 'repeatability',
    displayName: 'Repeatability',
    score: Math.round(score * 10) / 10,
    weight: AGENTIC_READINESS_WEIGHTS.repetitividad,
    description: `Monthly volume: ${volumen_mes} interactions`,
    details: {
      volumen_mes,
      threshold_medio: x0
    }
  };
}

/**
 * SUB-FACTOR 2: PREDICTABILITY (20%)
 * Based on AHT variability + escalation rate + input/output variability
 */
function calculatePredictabilityScore(
  aht_values: number[],
  escalation_rate: number,
  motivo_contacto_entropy?: number,
  resolucion_entropy?: number
): SubFactor {
  const thresholds = AGENTIC_READINESS_THRESHOLDS.predictibilidad;

  // 1. AHT VARIABILITY (40%)
  const aht_mean = aht_values.reduce((a, b) => a + b, 0) / aht_values.length;
  const aht_variance = aht_values.reduce((sum, val) => sum + Math.pow(val - aht_mean, 2), 0) / aht_values.length;
  const aht_std = Math.sqrt(aht_variance);
  const cv_aht = aht_std / aht_mean;

  // Normalize CV to 0-10 scale
  const score_aht = Math.max(0, Math.min(10,
    10 * (1 - (cv_aht - thresholds.cv_aht_excellent) / (thresholds.cv_aht_poor - thresholds.cv_aht_excellent))
  ));

  // 2. ESCALATION RATE (30%)
  const score_escalacion = Math.max(0, Math.min(10,
    10 * (1 - escalation_rate / thresholds.escalation_poor)
  ));

  // 3. INPUT/OUTPUT VARIABILITY (30%)
  let score_variabilidad: number;
  if (motivo_contacto_entropy !== undefined && resolucion_entropy !== undefined) {
    // High input entropy + Low output entropy = GOOD for automation
    const input_normalized = Math.min(motivo_contacto_entropy / 3.0, 1.0);
    const output_normalized = Math.min(resolucion_entropy / 3.0, 1.0);
    score_variabilidad = 10 * (input_normalized * (1 - output_normalized));
  } else {
    // If no entropy data, use average of AHT and escalation
    score_variabilidad = (score_aht + score_escalacion) / 2;
  }

  // FINAL WEIGHTING
  const predictabilidad = (
    0.40 * score_aht +
    0.30 * score_escalacion +
    0.30 * score_variabilidad
  );

  return {
    name: 'predictability',
    displayName: 'Predictability',
    score: Math.round(predictabilidad * 10) / 10,
    weight: AGENTIC_READINESS_WEIGHTS.predictibilidad,
    description: `AHT CV: ${(cv_aht * 100).toFixed(1)}%, Escalation: ${(escalation_rate * 100).toFixed(1)}%`,
    details: {
      cv_aht: Math.round(cv_aht * 1000) / 1000,
      escalation_rate,
      score_aht: Math.round(score_aht * 10) / 10,
      score_escalacion: Math.round(score_escalacion * 10) / 10,
      score_variabilidad: Math.round(score_variabilidad * 10) / 10
    }
  };
}

/**
 * SUB-FACTOR 3: STRUCTURING (15%)
 * Percentage of structured fields vs free text
 */
function calculateStructuringScore(structured_fields_pct: number): SubFactor {
  const score = structured_fields_pct * 10;

  return {
    name: 'structuring',
    displayName: 'Structuring',
    score: Math.round(score * 10) / 10,
    weight: AGENTIC_READINESS_WEIGHTS.estructuracion,
    description: `${(structured_fields_pct * 100).toFixed(0)}% structured fields`,
    details: {
      structured_fields_pct
    }
  };
}

/**
 * SUB-FACTOR 4: INVERSE COMPLEXITY (15%)
 * Based on exception rate
 */
function calculateInverseComplexityScore(exception_rate: number): SubFactor {
  // Lower exception rate → Higher score
  // < 5% → Excellent (score 10)
  // > 30% → Very complex (score 0)
  const score_excepciones = Math.max(0, Math.min(10, 10 * (1 - exception_rate / 0.30)));

  return {
    name: 'inverseComplexity',
    displayName: 'Inverse Complexity',
    score: Math.round(score_excepciones * 10) / 10,
    weight: AGENTIC_READINESS_WEIGHTS.complejidad_inversa,
    description: `${(exception_rate * 100).toFixed(1)}% exceptions`,
    details: {
      exception_rate
    }
  };
}

/**
 * SUB-FACTOR 5: STABILITY (10%)
 * Based on hourly distribution and % off-hours calls
 */
function calculateStabilityScore(
  hourly_distribution: number[],
  off_hours_pct: number
): SubFactor {
  // 1. HOURLY DISTRIBUTION UNIFORMITY (60%)
  // Calculate Shannon entropy
  const total = hourly_distribution.reduce((a, b) => a + b, 0);
  let score_uniformidad = 0;
  let entropy_normalized = 0;

  if (total > 0) {
    const probs = hourly_distribution.map(v => v / total).filter(p => p > 0);
    const entropy = -probs.reduce((sum, p) => sum + p * Math.log2(p), 0);
    const max_entropy = Math.log2(hourly_distribution.length);
    entropy_normalized = entropy / max_entropy;
    score_uniformidad = entropy_normalized * 10;
  }

  // 2. % OFF-HOURS CALLS (40%)
  // More off-hours calls → Higher agent need → Higher score
  const score_off_hours = Math.min(10, (off_hours_pct / 0.30) * 10);

  // WEIGHTING
  const estabilidad = (
    0.60 * score_uniformidad +
    0.40 * score_off_hours
  );

  return {
    name: 'stability',
    displayName: 'Stability',
    score: Math.round(estabilidad * 10) / 10,
    weight: AGENTIC_READINESS_WEIGHTS.estabilidad,
    description: `${(off_hours_pct * 100).toFixed(1)}% off-hours`,
    details: {
      entropy_normalized: Math.round(entropy_normalized * 1000) / 1000,
      off_hours_pct,
      score_uniformidad: Math.round(score_uniformidad * 10) / 10,
      score_off_hours: Math.round(score_off_hours * 10) / 10
    }
  };
}

/**
 * SUB-FACTOR 6: ROI (15%)
 * Based on annual potential savings
 */
function calculateROIScore(
  volumen_anual: number,
  cpi_humano: number,
  automation_savings_pct: number = 0.70
): SubFactor {
  const ahorro_anual = volumen_anual * cpi_humano * automation_savings_pct;

  // Logistic normalization
  const { k, x0 } = AGENTIC_READINESS_THRESHOLDS.roi;
  const score = 10 / (1 + Math.exp(-k * (ahorro_anual - x0)));

  return {
    name: 'roi',
    displayName: 'ROI',
    score: Math.round(score * 10) / 10,
    weight: AGENTIC_READINESS_WEIGHTS.roi,
    description: `€${(ahorro_anual / 1000).toFixed(0)}K annual potential savings`,
    details: {
      ahorro_anual: Math.round(ahorro_anual),
      volumen_anual,
      cpi_humano,
      automation_savings_pct
    }
  };
}

/**
 * CSAT DISTRIBUTION ADJUSTMENT (Optional, ±10%)
 * Normal distribution → Stable process
 */
function calculateCSATDistributionAdjustment(csat_values: number[]): number {
  // Simplified normality test (based on skewness and kurtosis)
  const n = csat_values.length;
  const mean = csat_values.reduce((a, b) => a + b, 0) / n;
  const variance = csat_values.reduce((sum, val) => sum + Math.pow(val - mean, 2), 0) / n;
  const std = Math.sqrt(variance);

  // Skewness
  const skewness = csat_values.reduce((sum, val) => sum + Math.pow((val - mean) / std, 3), 0) / n;

  // Kurtosis
  const kurtosis = csat_values.reduce((sum, val) => sum + Math.pow((val - mean) / std, 4), 0) / n;

  // Normality: skewness close to 0, kurtosis close to 3
  const skewness_score = Math.max(0, 1 - Math.abs(skewness));
  const kurtosis_score = Math.max(0, 1 - Math.abs(kurtosis - 3) / 3);
  const normality_score = (skewness_score + kurtosis_score) / 2;

  // Adjustment: +5% if very normal, -5% if very abnormal
  const adjustment = 1 + ((normality_score - 0.5) * 0.10);

  return adjustment;
}

/**
 * COMPLETE ALGORITHM (Tier GOLD)
 */
export function calculateAgenticReadinessScoreGold(data: AgenticReadinessInput): AgenticReadinessResult {
  const sub_factors: SubFactor[] = [];

  // 1. REPEATABILITY
  sub_factors.push(calculateRepeatabilityScore(data.volumen_mes));

  // 2. PREDICTABILITY
  sub_factors.push(calculatePredictabilityScore(
    data.aht_values,
    data.escalation_rate,
    data.motivo_contacto_entropy,
    data.resolucion_entropy
  ));

  // 3. STRUCTURING
  sub_factors.push(calculateStructuringScore(data.structured_fields_pct || 0.5));

  // 4. INVERSE COMPLEXITY
  sub_factors.push(calculateInverseComplexityScore(data.exception_rate || 0.15));

  // 5. STABILITY
  sub_factors.push(calculateStabilityScore(
    data.hourly_distribution || Array(24).fill(1),
    data.off_hours_pct || 0.2
  ));

  // 6. ROI
  sub_factors.push(calculateROIScore(
    data.volumen_anual,
    data.cpi_humano
  ));

  // BASE WEIGHTING
  const agentic_readiness_base = sub_factors.reduce(
    (sum, factor) => sum + (factor.score * factor.weight),
    0
  );

  // CSAT DISTRIBUTION ADJUSTMENT (Optional)
  let agentic_readiness_final = agentic_readiness_base;
  if (data.csat_values && data.csat_values.length > 10) {
    const adjustment = calculateCSATDistributionAdjustment(data.csat_values);
    agentic_readiness_final = agentic_readiness_base * adjustment;
  }

  // Limit to 0-10 range
  agentic_readiness_final = Math.max(0, Math.min(10, agentic_readiness_final));

  // Interpretation
  let interpretation = '';
  let confidence: 'high' | 'medium' | 'low' = 'high';

  if (agentic_readiness_final >= 8) {
    interpretation = 'Excellent candidate for complete automation (Automate)';
  } else if (agentic_readiness_final >= 5) {
    interpretation = 'Good candidate for agentic assistance (Assist)';
  } else if (agentic_readiness_final >= 3) {
    interpretation = 'Candidate for human augmentation (Augment)';
  } else {
    interpretation = 'Not recommended for automation at this time';
  }

  return {
    score: Math.round(agentic_readiness_final * 10) / 10,
    sub_factors,
    tier: 'gold',
    confidence,
    interpretation
  };
}

/**
 * SIMPLIFIED ALGORITHM (Tier SILVER)
 */
export function calculateAgenticReadinessScoreSilver(data: AgenticReadinessInput): AgenticReadinessResult {
  const sub_factors: SubFactor[] = [];

  // 1. REPEATABILITY (30%)
  const repeatability = calculateRepeatabilityScore(data.volumen_mes);
  repeatability.weight = 0.30;
  sub_factors.push(repeatability);

  // 2. SIMPLIFIED PREDICTABILITY (30%)
  const predictability = calculatePredictabilityScore(
    data.aht_values,
    data.escalation_rate
  );
  predictability.weight = 0.30;
  sub_factors.push(predictability);

  // 3. ROI (40%)
  const roi = calculateROIScore(data.volumen_anual, data.cpi_humano);
  roi.weight = 0.40;
  sub_factors.push(roi);

  // SIMPLIFIED WEIGHTING
  const agentic_readiness = sub_factors.reduce(
    (sum, factor) => sum + (factor.score * factor.weight),
    0
  );

  // Interpretation
  let interpretation = '';
  if (agentic_readiness >= 7) {
    interpretation = 'Good candidate for automation';
  } else if (agentic_readiness >= 4) {
    interpretation = 'Candidate for agentic assistance';
  } else {
    interpretation = 'Requires deeper analysis (consider GOLD)';
  }

  return {
    score: Math.round(agentic_readiness * 10) / 10,
    sub_factors,
    tier: 'silver',
    confidence: 'medium',
    interpretation
  };
}

/**
 * MAIN FUNCTION - Selects algorithm based on tier
 */
export function calculateAgenticReadinessScore(data: AgenticReadinessInput): AgenticReadinessResult {
  if (data.tier === 'gold') {
    return calculateAgenticReadinessScoreGold(data);
  } else if (data.tier === 'silver') {
    return calculateAgenticReadinessScoreSilver(data);
  } else {
    // BRONZE: No Agentic Readiness
    return {
      score: 0,
      sub_factors: [],
      tier: 'bronze',
      confidence: 'low',
      interpretation: 'Bronze analysis does not include Agentic Readiness Score'
    };
  }
}
