import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Progress } from "@/components/ui/progress";
import { Badge } from "@/components/ui/badge";
import {
  Collapsible,
  CollapsibleContent,
  CollapsibleTrigger,
} from "@/components/ui/collapsible";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import {
  ChevronDown,
  Activity,
  Waves,
  BarChart3,
  Gauge,
  Music2,
  Zap,
  TrendingUp,
  TrendingDown,
  Minus,
  Target,
  ArrowRight,
} from "lucide-react";
import { useState, useMemo } from "react";
import { cn } from "@/lib/utils";
import type { VoiceParameters } from "@shared/schema";

interface ParameterAnalysisPanelProps {
  sourceParams?: VoiceParameters;
  targetParams?: VoiceParameters;
  resultParams?: VoiceParameters;
  matchScore?: number;
}

interface ParameterRowProps {
  label: string;
  icon: React.ReactNode;
  sourceValue?: number;
  targetValue?: number;
  resultValue?: number;
  unit?: string;
  maxValue?: number;
  formatFn?: (value: number) => string;
  showDelta?: boolean;
}

function DeltaIndicator({ delta, unit = "" }: { delta: number; unit?: string }) {
  const absValue = Math.abs(delta);
  const isPositive = delta > 0;
  const isNeutral = absValue < 0.001;

  if (isNeutral) {
    return (
      <div className="flex items-center gap-1 text-muted-foreground">
        <Minus className="h-3 w-3" />
        <span className="text-xs font-mono">0</span>
      </div>
    );
  }

  return (
    <div className={cn(
      "flex items-center gap-1",
      isPositive ? "text-green-500" : "text-red-500"
    )}>
      {isPositive ? (
        <TrendingUp className="h-3 w-3" />
      ) : (
        <TrendingDown className="h-3 w-3" />
      )}
      <span className="text-xs font-mono">
        {isPositive ? "+" : ""}{delta.toFixed(1)}{unit}
      </span>
    </div>
  );
}

function ParameterRow({
  label,
  icon,
  sourceValue,
  targetValue,
  resultValue,
  unit = "",
  maxValue = 100,
  formatFn,
  showDelta = true,
}: ParameterRowProps) {
  const format = formatFn || ((v: number) => v.toFixed(1));
  const normalize = (v: number) => Math.min(Math.max((v / maxValue) * 100, 0), 100);

  const delta = useMemo(() => {
    if (targetValue !== undefined && resultValue !== undefined) {
      return resultValue - targetValue;
    }
    return 0;
  }, [targetValue, resultValue]);

  const matchPercent = useMemo(() => {
    if (sourceValue !== undefined && targetValue !== undefined && resultValue !== undefined) {
      const targetDiff = Math.abs(sourceValue - targetValue);
      if (targetDiff < 0.001) {
        return Math.abs(resultValue - sourceValue) < 0.001 ? 100 : 0;
      }
      const resultDiff = Math.abs(resultValue - sourceValue);
      const matchRatio = 1 - (resultDiff / targetDiff);
      return Math.max(0, Math.min(100, matchRatio * 100));
    }
    return undefined;
  }, [sourceValue, targetValue, resultValue]);

  return (
    <div className="py-3 border-b border-border/50 last:border-0">
      <div className="flex items-center justify-between mb-2">
        <div className="flex items-center gap-2">
          <div className="text-muted-foreground">{icon}</div>
          <span className="text-sm font-medium">{label}</span>
        </div>
        {matchPercent !== undefined && (
          <Badge variant="outline" className="text-xs font-mono">
            {matchPercent.toFixed(0)}% match
          </Badge>
        )}
      </div>

      <div className="grid grid-cols-3 gap-4">
        <div className="space-y-1">
          <div className="flex items-center justify-between text-xs">
            <span className="text-muted-foreground">Source</span>
            {sourceValue !== undefined && (
              <span className="font-mono text-primary" data-testid={`text-source-${label.toLowerCase().replace(/\s/g, "-")}`}>
                {format(sourceValue)}{unit}
              </span>
            )}
          </div>
          {sourceValue !== undefined && (
            <Progress value={normalize(sourceValue)} className="h-1.5" />
          )}
        </div>

        <div className="space-y-1">
          <div className="flex items-center justify-between text-xs">
            <span className="text-muted-foreground">Target</span>
            {targetValue !== undefined && (
              <span className="font-mono text-chart-2" data-testid={`text-target-${label.toLowerCase().replace(/\s/g, "-")}`}>
                {format(targetValue)}{unit}
              </span>
            )}
          </div>
          {targetValue !== undefined && (
            <Progress value={normalize(targetValue)} className="h-1.5 [&>div]:bg-chart-2" />
          )}
        </div>

        <div className="space-y-1">
          <div className="flex items-center justify-between text-xs">
            <span className="text-muted-foreground">Result</span>
            {resultValue !== undefined ? (
              <div className="flex items-center gap-2">
                <span className="font-mono text-green-500" data-testid={`text-result-${label.toLowerCase().replace(/\s/g, "-")}`}>
                  {format(resultValue)}{unit}
                </span>
                {showDelta && <DeltaIndicator delta={delta} />}
              </div>
            ) : (
              <span className="text-muted-foreground/50">—</span>
            )}
          </div>
          {resultValue !== undefined && (
            <Progress value={normalize(resultValue)} className="h-1.5 [&>div]:bg-green-500" />
          )}
        </div>
      </div>
    </div>
  );
}

function MFCCVisualization({
  sourceCoeffs,
  targetCoeffs,
  resultCoeffs,
}: {
  sourceCoeffs?: number[];
  targetCoeffs?: number[];
  resultCoeffs?: number[];
}) {
  const maxCoeffs = 13;
  const coeffIndices = Array.from({ length: maxCoeffs }, (_, i) => i);

  const normalizeCoeff = (value: number) => {
    const min = -20;
    const max = 20;
    return ((value - min) / (max - min)) * 100;
  };

  return (
    <div className="space-y-4">
      <div className="flex items-center justify-between">
        <h4 className="text-sm font-medium">MFCC Coefficients</h4>
        <div className="flex items-center gap-4 text-xs">
          <div className="flex items-center gap-1">
            <div className="w-3 h-3 rounded-sm bg-primary" />
            <span className="text-muted-foreground">Source</span>
          </div>
          <div className="flex items-center gap-1">
            <div className="w-3 h-3 rounded-sm bg-chart-2" />
            <span className="text-muted-foreground">Target</span>
          </div>
          <div className="flex items-center gap-1">
            <div className="w-3 h-3 rounded-sm bg-green-500" />
            <span className="text-muted-foreground">Result</span>
          </div>
        </div>
      </div>

      <div className="flex items-end gap-1 h-32">
        {coeffIndices.map((i) => {
          const sourceVal = sourceCoeffs?.[i] ?? 0;
          const targetVal = targetCoeffs?.[i] ?? 0;
          const resultVal = resultCoeffs?.[i] ?? 0;

          return (
            <div key={i} className="flex-1 flex gap-0.5 h-full items-end" data-testid={`mfcc-bar-${i}`}>
              {sourceCoeffs && (
                <div
                  className="flex-1 bg-primary/80 rounded-t-sm transition-all"
                  style={{ height: `${normalizeCoeff(sourceVal)}%` }}
                  title={`Source C${i}: ${sourceVal.toFixed(2)}`}
                />
              )}
              {targetCoeffs && (
                <div
                  className="flex-1 bg-chart-2/80 rounded-t-sm transition-all"
                  style={{ height: `${normalizeCoeff(targetVal)}%` }}
                  title={`Target C${i}: ${targetVal.toFixed(2)}`}
                />
              )}
              {resultCoeffs && (
                <div
                  className="flex-1 bg-green-500/80 rounded-t-sm transition-all"
                  style={{ height: `${normalizeCoeff(resultVal)}%` }}
                  title={`Result C${i}: ${resultVal.toFixed(2)}`}
                />
              )}
            </div>
          );
        })}
      </div>

      <div className="flex justify-between text-xs text-muted-foreground">
        {coeffIndices.map((i) => (
          <span key={i} className="flex-1 text-center">C{i}</span>
        ))}
      </div>
    </div>
  );
}

function FormantRadarChart({
  sourceParams,
  targetParams,
  resultParams,
}: {
  sourceParams?: VoiceParameters;
  targetParams?: VoiceParameters;
  resultParams?: VoiceParameters;
}) {
  const formants = [
    { key: "formantF1", label: "F1", max: 1000 },
    { key: "formantF2", label: "F2", max: 3000 },
    { key: "formantF3", label: "F3", max: 4000 },
    { key: "formantF4", label: "F4", max: 5000 },
  ] as const;

  const centerX = 120;
  const centerY = 100;
  const maxRadius = 80;

  const getPolygonPoints = (params: VoiceParameters | undefined) => {
    if (!params) return "";
    
    return formants
      .map((f, i) => {
        const angle = (Math.PI * 2 * i) / formants.length - Math.PI / 2;
        const value = params[f.key] as number;
        const normalizedValue = Math.min(value / f.max, 1);
        const radius = normalizedValue * maxRadius;
        const x = centerX + radius * Math.cos(angle);
        const y = centerY + radius * Math.sin(angle);
        return `${x},${y}`;
      })
      .join(" ");
  };

  return (
    <div className="space-y-4">
      <div className="flex items-center justify-between">
        <h4 className="text-sm font-medium">Formant Distribution</h4>
        <div className="flex items-center gap-4 text-xs">
          <div className="flex items-center gap-1">
            <div className="w-3 h-3 rounded-full border-2 border-primary" />
            <span className="text-muted-foreground">Source</span>
          </div>
          <div className="flex items-center gap-1">
            <div className="w-3 h-3 rounded-full border-2 border-chart-2" />
            <span className="text-muted-foreground">Target</span>
          </div>
          <div className="flex items-center gap-1">
            <div className="w-3 h-3 rounded-full border-2 border-green-500" />
            <span className="text-muted-foreground">Result</span>
          </div>
        </div>
      </div>

      <svg viewBox="0 0 240 200" className="w-full h-48" data-testid="formant-radar">
        {[0.25, 0.5, 0.75, 1].map((scale) => (
          <circle
            key={scale}
            cx={centerX}
            cy={centerY}
            r={maxRadius * scale}
            fill="none"
            stroke="currentColor"
            strokeOpacity={0.1}
            strokeWidth={1}
          />
        ))}

        {formants.map((f, i) => {
          const angle = (Math.PI * 2 * i) / formants.length - Math.PI / 2;
          const x = centerX + maxRadius * Math.cos(angle);
          const y = centerY + maxRadius * Math.sin(angle);
          const labelX = centerX + (maxRadius + 20) * Math.cos(angle);
          const labelY = centerY + (maxRadius + 20) * Math.sin(angle);

          return (
            <g key={f.key}>
              <line
                x1={centerX}
                y1={centerY}
                x2={x}
                y2={y}
                stroke="currentColor"
                strokeOpacity={0.2}
                strokeWidth={1}
              />
              <text
                x={labelX}
                y={labelY}
                textAnchor="middle"
                dominantBaseline="middle"
                className="fill-muted-foreground text-xs"
              >
                {f.label}
              </text>
            </g>
          );
        })}

        {sourceParams && (
          <polygon
            points={getPolygonPoints(sourceParams)}
            fill="hsl(var(--primary))"
            fillOpacity={0.1}
            stroke="hsl(var(--primary))"
            strokeWidth={2}
          />
        )}

        {targetParams && (
          <polygon
            points={getPolygonPoints(targetParams)}
            fill="hsl(var(--chart-2))"
            fillOpacity={0.1}
            stroke="hsl(var(--chart-2))"
            strokeWidth={2}
          />
        )}

        {resultParams && (
          <polygon
            points={getPolygonPoints(resultParams)}
            fill="hsl(142 76% 36%)"
            fillOpacity={0.15}
            stroke="hsl(142 76% 36%)"
            strokeWidth={2}
          />
        )}
      </svg>

      <div className="grid grid-cols-4 gap-2 text-center">
        {formants.map((f) => (
          <div key={f.key} className="space-y-1">
            <div className="text-xs text-muted-foreground">{f.label}</div>
            <div className="text-xs font-mono space-y-0.5">
              {sourceParams && (
                <div className="text-primary">{(sourceParams[f.key] as number).toFixed(0)}</div>
              )}
              {resultParams && (
                <div className="text-green-500">{(resultParams[f.key] as number).toFixed(0)}</div>
              )}
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

function TransformationSummary({
  sourceParams,
  targetParams,
  resultParams,
  matchScore,
}: ParameterAnalysisPanelProps) {
  const summaryItems = useMemo(() => {
    if (!targetParams || !resultParams) return [];

    return [
      {
        label: "Pitch Shift",
        from: targetParams.pitchMean,
        to: resultParams.pitchMean,
        target: sourceParams?.pitchMean,
        unit: "Hz",
        icon: <Music2 className="h-4 w-4" />,
      },
      {
        label: "Energy Change",
        from: targetParams.rmsEnergy * 100,
        to: resultParams.rmsEnergy * 100,
        target: sourceParams ? sourceParams.rmsEnergy * 100 : undefined,
        unit: "%",
        icon: <Zap className="h-4 w-4" />,
      },
      {
        label: "Tempo Adjustment",
        from: targetParams.tempo,
        to: resultParams.tempo,
        target: sourceParams?.tempo,
        unit: "BPM",
        icon: <Gauge className="h-4 w-4" />,
      },
      {
        label: "Spectral Shift",
        from: targetParams.spectralCentroid,
        to: resultParams.spectralCentroid,
        target: sourceParams?.spectralCentroid,
        unit: "Hz",
        icon: <BarChart3 className="h-4 w-4" />,
      },
    ];
  }, [sourceParams, targetParams, resultParams]);

  if (summaryItems.length === 0) {
    return (
      <div className="flex flex-col items-center justify-center py-8 text-muted-foreground">
        <Target className="h-8 w-8 mb-2 opacity-50" />
        <p className="text-sm">Complete a transformation to see the summary</p>
      </div>
    );
  }

  return (
    <div className="space-y-4">
      {matchScore !== undefined && (
        <div className="p-4 rounded-lg bg-green-500/10 border border-green-500/20">
          <div className="flex items-center justify-between">
            <div className="flex items-center gap-2">
              <Target className="h-5 w-5 text-green-500" />
              <span className="font-medium">Overall Match Score</span>
            </div>
            <span className="text-2xl font-bold text-green-500" data-testid="text-overall-match">
              {matchScore.toFixed(1)}%
            </span>
          </div>
          <p className="text-xs text-muted-foreground mt-2">
            How closely the transformed result matches the source voice characteristics
          </p>
        </div>
      )}

      <div className="mb-4 p-3 rounded-lg bg-muted/20 border border-border/50">
        <p className="text-xs text-muted-foreground">
          <span className="font-medium">Target</span> (original voice) <ArrowRight className="h-3 w-3 inline mx-1" /> 
          <span className="font-medium text-green-500">Result</span> (transformed to match source)
        </p>
      </div>

      <div className="space-y-3">
        {summaryItems.map((item) => (
          <div
            key={item.label}
            className="p-3 rounded-lg bg-muted/30"
            data-testid={`summary-${item.label.toLowerCase().replace(/\s/g, "-")}`}
          >
            <div className="flex items-center justify-between mb-2">
              <div className="flex items-center gap-3">
                <div className="text-muted-foreground">{item.icon}</div>
                <span className="text-sm font-medium">{item.label}</span>
              </div>
              {item.target !== undefined && (
                <Badge variant="outline" className="text-xs font-mono">
                  Source: {item.target.toFixed(1)}{item.unit}
                </Badge>
              )}
            </div>
            <div className="flex items-center gap-2">
              <span className="text-sm font-mono text-chart-2" title="Original target value">
                {item.from.toFixed(1)}{item.unit}
              </span>
              <ArrowRight className="h-4 w-4 text-muted-foreground" />
              <span className="text-sm font-mono text-green-500" title="Transformed result">
                {item.to.toFixed(1)}{item.unit}
              </span>
              <span className="text-xs text-muted-foreground ml-2">
                ({item.to > item.from ? "+" : ""}{(item.to - item.from).toFixed(1)}{item.unit})
              </span>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

export function ParameterAnalysisPanel({
  sourceParams,
  targetParams,
  resultParams,
  matchScore,
}: ParameterAnalysisPanelProps) {
  const [isOpen, setIsOpen] = useState(true);

  const hasData = sourceParams || targetParams || resultParams;

  return (
    <Collapsible open={isOpen} onOpenChange={setIsOpen}>
      <Card className="overflow-visible">
        <CollapsibleTrigger asChild>
          <CardHeader className="cursor-pointer flex flex-row items-center justify-between gap-2 py-4 px-6">
            <div className="flex items-center gap-3">
              <CardTitle className="text-lg">Voice Analysis Dashboard</CardTitle>
              {matchScore !== undefined && (
                <Badge variant="outline" className="bg-green-500/10 text-green-500 border-green-500/30">
                  {matchScore.toFixed(1)}% Match
                </Badge>
              )}
            </div>
            <ChevronDown
              className={cn(
                "h-5 w-5 text-muted-foreground transition-transform",
                isOpen && "rotate-180"
              )}
            />
          </CardHeader>
        </CollapsibleTrigger>

        <CollapsibleContent>
          <CardContent className="px-6 pb-6 pt-0">
            {hasData ? (
              <Tabs defaultValue="summary" className="w-full">
                <TabsList className="grid w-full grid-cols-4 mb-4">
                  <TabsTrigger value="summary" data-testid="tab-summary">Summary</TabsTrigger>
                  <TabsTrigger value="parameters" data-testid="tab-parameters">Parameters</TabsTrigger>
                  <TabsTrigger value="formants" data-testid="tab-formants">Formants</TabsTrigger>
                  <TabsTrigger value="mfcc" data-testid="tab-mfcc">MFCC</TabsTrigger>
                </TabsList>

                <TabsContent value="summary" className="mt-0">
                  <TransformationSummary
                    sourceParams={sourceParams}
                    targetParams={targetParams}
                    resultParams={resultParams}
                    matchScore={matchScore}
                  />
                </TabsContent>

                <TabsContent value="parameters" className="mt-0">
                  <div className="space-y-0">
                    <ParameterRow
                      label="Pitch (Mean)"
                      icon={<Music2 className="h-4 w-4" />}
                      sourceValue={sourceParams?.pitchMean}
                      targetValue={targetParams?.pitchMean}
                      resultValue={resultParams?.pitchMean}
                      unit=" Hz"
                      maxValue={500}
                      formatFn={(v) => v.toFixed(0)}
                    />
                    <ParameterRow
                      label="Pitch Range"
                      icon={<Music2 className="h-4 w-4" />}
                      sourceValue={sourceParams ? sourceParams.pitchMax - sourceParams.pitchMin : undefined}
                      targetValue={targetParams ? targetParams.pitchMax - targetParams.pitchMin : undefined}
                      resultValue={resultParams ? resultParams.pitchMax - resultParams.pitchMin : undefined}
                      unit=" Hz"
                      maxValue={300}
                      formatFn={(v) => v.toFixed(0)}
                    />
                    <ParameterRow
                      label="Spectral Centroid"
                      icon={<BarChart3 className="h-4 w-4" />}
                      sourceValue={sourceParams?.spectralCentroid}
                      targetValue={targetParams?.spectralCentroid}
                      resultValue={resultParams?.spectralCentroid}
                      unit=" Hz"
                      maxValue={5000}
                      formatFn={(v) => v.toFixed(0)}
                    />
                    <ParameterRow
                      label="Spectral Bandwidth"
                      icon={<Zap className="h-4 w-4" />}
                      sourceValue={sourceParams?.spectralBandwidth}
                      targetValue={targetParams?.spectralBandwidth}
                      resultValue={resultParams?.spectralBandwidth}
                      unit=" Hz"
                      maxValue={3000}
                      formatFn={(v) => v.toFixed(0)}
                    />
                    <ParameterRow
                      label="RMS Energy"
                      icon={<Gauge className="h-4 w-4" />}
                      sourceValue={sourceParams?.rmsEnergy}
                      targetValue={targetParams?.rmsEnergy}
                      resultValue={resultParams?.rmsEnergy}
                      maxValue={1}
                      formatFn={(v) => v.toFixed(4)}
                    />
                    <ParameterRow
                      label="Harmonic Ratio"
                      icon={<Activity className="h-4 w-4" />}
                      sourceValue={sourceParams?.harmonicRatio}
                      targetValue={targetParams?.harmonicRatio}
                      resultValue={resultParams?.harmonicRatio}
                      unit="%"
                      maxValue={100}
                      formatFn={(v) => v.toFixed(1)}
                    />
                    <ParameterRow
                      label="Zero Crossing Rate"
                      icon={<Activity className="h-4 w-4" />}
                      sourceValue={sourceParams?.zeroCrossingRate}
                      targetValue={targetParams?.zeroCrossingRate}
                      resultValue={resultParams?.zeroCrossingRate}
                      maxValue={0.5}
                      formatFn={(v) => v.toFixed(4)}
                    />
                    <ParameterRow
                      label="Tempo"
                      icon={<Gauge className="h-4 w-4" />}
                      sourceValue={sourceParams?.tempo}
                      targetValue={targetParams?.tempo}
                      resultValue={resultParams?.tempo}
                      unit=" BPM"
                      maxValue={200}
                      formatFn={(v) => v.toFixed(0)}
                    />
                  </div>
                </TabsContent>

                <TabsContent value="formants" className="mt-0">
                  <div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
                    <FormantRadarChart
                      sourceParams={sourceParams}
                      targetParams={targetParams}
                      resultParams={resultParams}
                    />
                    <div className="space-y-0">
                      <ParameterRow
                        label="Formant F1"
                        icon={<Waves className="h-4 w-4" />}
                        sourceValue={sourceParams?.formantF1}
                        targetValue={targetParams?.formantF1}
                        resultValue={resultParams?.formantF1}
                        unit=" Hz"
                        maxValue={1000}
                        formatFn={(v) => v.toFixed(0)}
                      />
                      <ParameterRow
                        label="Formant F2"
                        icon={<Waves className="h-4 w-4" />}
                        sourceValue={sourceParams?.formantF2}
                        targetValue={targetParams?.formantF2}
                        resultValue={resultParams?.formantF2}
                        unit=" Hz"
                        maxValue={3000}
                        formatFn={(v) => v.toFixed(0)}
                      />
                      <ParameterRow
                        label="Formant F3"
                        icon={<Waves className="h-4 w-4" />}
                        sourceValue={sourceParams?.formantF3}
                        targetValue={targetParams?.formantF3}
                        resultValue={resultParams?.formantF3}
                        unit=" Hz"
                        maxValue={4000}
                        formatFn={(v) => v.toFixed(0)}
                      />
                      <ParameterRow
                        label="Formant F4"
                        icon={<Waves className="h-4 w-4" />}
                        sourceValue={sourceParams?.formantF4}
                        targetValue={targetParams?.formantF4}
                        resultValue={resultParams?.formantF4}
                        unit=" Hz"
                        maxValue={5000}
                        formatFn={(v) => v.toFixed(0)}
                      />
                    </div>
                  </div>
                </TabsContent>

                <TabsContent value="mfcc" className="mt-0">
                  <MFCCVisualization
                    sourceCoeffs={sourceParams?.mfccCoefficients}
                    targetCoeffs={targetParams?.mfccCoefficients}
                    resultCoeffs={resultParams?.mfccCoefficients}
                  />
                </TabsContent>
              </Tabs>
            ) : (
              <div className="flex flex-col items-center justify-center py-8 text-muted-foreground">
                <Activity className="h-8 w-8 mb-2 opacity-50" />
                <p className="text-sm">Upload audio files to see voice analysis</p>
              </div>
            )}
          </CardContent>
        </CollapsibleContent>
      </Card>
    </Collapsible>
  );
}
