/**
 * PlotlyParameterImportance - Interactive parameter importance chart using Plotly
 *
 * Features:
 * - Horizontal bar chart showing correlation/importance
 * - Color coding by positive/negative correlation
 * - Hover tooltips with details
 * - Sortable by importance
 */

import { useMemo, useState } from 'react';
import Plot from 'react-plotly.js';

interface Trial {
  trial_number: number;
  values: number[];
  params: Record<string, number>;
  user_attrs?: Record<string, any>;
}

interface DesignVariable {
  name: string;
  unit?: string;
}

interface PlotlyParameterImportanceProps {
  trials: Trial[];
  designVariables: DesignVariable[];
  objectiveIndex?: number;
  objectiveName?: string;
  height?: number;
}

// Calculate Pearson correlation coefficient
function pearsonCorrelation(x: number[], y: number[]): number {
  const n = x.length;
  if (n === 0) return 0;

  const sumX = x.reduce((a, b) => a + b, 0);
  const sumY = y.reduce((a, b) => a + b, 0);
  const sumXY = x.reduce((acc, xi, i) => acc + xi * y[i], 0);
  const sumX2 = x.reduce((acc, xi) => acc + xi * xi, 0);
  const sumY2 = y.reduce((acc, yi) => acc + yi * yi, 0);

  const numerator = n * sumXY - sumX * sumY;
  const denominator = Math.sqrt((n * sumX2 - sumX * sumX) * (n * sumY2 - sumY * sumY));

  if (denominator === 0) return 0;
  return numerator / denominator;
}

export function PlotlyParameterImportance({
  trials,
  designVariables,
  objectiveIndex = 0,
  objectiveName = 'Objective',
  height = 400
}: PlotlyParameterImportanceProps) {
  const [sortBy, setSortBy] = useState<'importance' | 'name'>('importance');

  // Calculate correlations for each parameter
  const correlations = useMemo(() => {
    if (!trials.length || !designVariables.length) return [];

    // Get objective values
    const objValues = trials.map(t => {
      if (t.values && t.values[objectiveIndex] !== undefined) {
        return t.values[objectiveIndex];
      }
      return t.user_attrs?.[objectiveName] ?? null;
    }).filter((v): v is number => v !== null && isFinite(v));

    if (objValues.length < 3) return []; // Need at least 3 points for correlation

    const results: { name: string; correlation: number; absCorrelation: number }[] = [];

    designVariables.forEach(dv => {
      const paramValues = trials
        .map((t) => {
          const objVal = t.values?.[objectiveIndex] ?? t.user_attrs?.[objectiveName];
          if (objVal === null || objVal === undefined || !isFinite(objVal)) return null;
          return { param: t.params[dv.name], obj: objVal };
        })
        .filter((v): v is { param: number; obj: number } => v !== null && v.param !== undefined);

      if (paramValues.length < 3) return;

      const x = paramValues.map(v => v.param);
      const y = paramValues.map(v => v.obj);
      const corr = pearsonCorrelation(x, y);

      results.push({
        name: dv.name,
        correlation: corr,
        absCorrelation: Math.abs(corr)
      });
    });

    // Sort by absolute correlation or name
    if (sortBy === 'importance') {
      results.sort((a, b) => b.absCorrelation - a.absCorrelation);
    } else {
      results.sort((a, b) => a.name.localeCompare(b.name));
    }

    return results;
  }, [trials, designVariables, objectiveIndex, objectiveName, sortBy]);

  if (!correlations.length) {
    return (
      <div className="flex items-center justify-center h-64 text-gray-500">
        Not enough data to calculate parameter importance
      </div>
    );
  }

  // Build bar chart data
  const names = correlations.map(c => c.name);
  const values = correlations.map(c => c.correlation);
  const colors = values.map(v => v > 0 ? '#EF4444' : '#22C55E'); // Red for positive (worse), Green for negative (better) when minimizing
  const hoverTexts = correlations.map(c =>
    `${c.name}<br>Correlation: ${c.correlation.toFixed(4)}<br>|r|: ${c.absCorrelation.toFixed(4)}<br>${c.correlation > 0 ? 'Higher → Higher objective' : 'Higher → Lower objective'}`
  );

  return (
    <div className="w-full">
      {/* Controls */}
      <div className="flex justify-between items-center mb-3">
        <div className="text-sm text-gray-600">
          Correlation with <span className="font-semibold">{objectiveName}</span>
        </div>
        <div className="flex gap-2">
          <button
            onClick={() => setSortBy('importance')}
            className={`px-3 py-1 text-xs rounded ${sortBy === 'importance' ? 'bg-blue-500 text-white' : 'bg-gray-100 text-gray-700'}`}
          >
            By Importance
          </button>
          <button
            onClick={() => setSortBy('name')}
            className={`px-3 py-1 text-xs rounded ${sortBy === 'name' ? 'bg-blue-500 text-white' : 'bg-gray-100 text-gray-700'}`}
          >
            By Name
          </button>
        </div>
      </div>

      <Plot
        data={[
          {
            type: 'bar',
            orientation: 'h',
            y: names,
            x: values,
            text: hoverTexts,
            hoverinfo: 'text',
            marker: {
              color: colors,
              line: { color: '#fff', width: 1 }
            }
          }
        ]}
        layout={{
          height: Math.max(height, correlations.length * 30 + 80),
          margin: { l: 150, r: 30, t: 10, b: 50 },
          paper_bgcolor: 'rgba(0,0,0,0)',
          plot_bgcolor: 'rgba(0,0,0,0)',
          xaxis: {
            title: { text: 'Correlation Coefficient' },
            range: [-1, 1],
            gridcolor: '#E5E7EB',
            zerolinecolor: '#9CA3AF',
            zerolinewidth: 2
          },
          yaxis: {
            automargin: true
          },
          font: { family: 'Inter, system-ui, sans-serif', size: 11 },
          bargap: 0.3
        }}
        config={{
          displayModeBar: true,
          displaylogo: false,
          modeBarButtonsToRemove: ['lasso2d', 'select2d'],
          toImageButtonOptions: {
            format: 'png',
            filename: 'parameter_importance',
            height: 600,
            width: 800,
            scale: 2
          }
        }}
        style={{ width: '100%' }}
      />

      {/* Legend */}
      <div className="flex gap-6 justify-center mt-3 text-xs">
        <div className="flex items-center gap-1.5">
          <div className="w-4 h-3 rounded" style={{ backgroundColor: '#EF4444' }} />
          <span className="text-gray-600">Positive correlation (higher param → higher objective)</span>
        </div>
        <div className="flex items-center gap-1.5">
          <div className="w-4 h-3 rounded" style={{ backgroundColor: '#22C55E' }} />
          <span className="text-gray-600">Negative correlation (higher param → lower objective)</span>
        </div>
      </div>
    </div>
  );
}
