﻿'use client'

import React, { useState, useEffect, useMemo, useRef } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { ArrowLeft, ChevronDown, ChevronUp, Info, Mic, TrendingUp, MessageCircle, BookOpen, Award, ArrowRight, Play, Pause, X, Loader2 } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { useNavigate } from '@/lib/nextRouterAdapter';
import { useParams } from 'next/navigation';
import { getApiPath } from '@/lib/basePath';

const internationalTests = [
  { name: 'IELTS', label: 'Speaking score predictor', value: '8.5', min: 0, max: 9, percent: 94, status: 'Outstanding', color: '#DC2626' },
  { name: 'TOEFL', label: 'Speaking score predictor', value: '28', min: 0, max: 30, percent: 93, status: 'Outstanding', color: '#059669' },
  { name: 'CEFR', label: 'Speaking score predictor', value: 'C2', min: 'A1', max: 'C2', percent: 100, status: 'Proficient', color: '#2563EB' },
  { name: 'Pearson PTE', label: 'Speaking score predictor', value: '87', min: 0, max: 90, percent: 97, status: 'Mastery', color: '#7C3AED' },
  { name: 'Duolingo', label: 'Speaking score predictor', value: '120', min: 10, max: 160, percent: 75, status: 'Advanced', color: '#059669' },
];

const skillTabs = [
  { id: 'pronunciation', label: 'Pronunciation', level: 'Proficient', color: '#A73121', icon: Mic },
  { id: 'intonation', label: 'Intonation', level: 'Proficient', color: '#D4B038', icon: TrendingUp },
  { id: 'fluency', label: 'Fluency', level: 'Proficient', color: '#2563EB', icon: MessageCircle },
  { id: 'grammar', label: 'Grammar', level: 'Advanced', color: '#059669', icon: BookOpen },
  { id: 'vocabulary', label: 'Vocabulary', level: 'Advanced', color: '#7C3AED', icon: Award },
];

const INTONATION_TUTORIAL_VIDEO_ID = 'zp0TGDymBb0';
const INTONATION_TUTORIAL_THUMBNAIL = `https://img.youtube.com/vi/${INTONATION_TUTORIAL_VIDEO_ID}/hqdefault.jpg`;
const FLUENCY_TUTORIAL_VIDEO_ID = '-oQXdfyA9JI';
const FLUENCY_TUTORIAL_THUMBNAIL = `https://img.youtube.com/vi/${FLUENCY_TUTORIAL_VIDEO_ID}/hqdefault.jpg`;
const VOCABULARY_TUTORIAL_VIDEO_ID = 'NsVKkTVfxCE';
const VOCABULARY_TUTORIAL_THUMBNAIL = `https://img.youtube.com/vi/${VOCABULARY_TUTORIAL_VIDEO_ID}/hqdefault.jpg`;

const transcript = [
  { time: '00:00:00', text: 'One of my good friends is Sasha. She is, um, an amazing lady. She recently got married. We met at an audition. Uh, she matters to me because' },
  { time: '00:00:13', text: 'she is very open-minded and she speaks her mind.' },
  { time: '00:00:18', text: "And she's very honest with me and most importantly, she gives me the space to be myself. Um, we have gone on, uh, a lot of coffee dates with each other and, uh," },
  { time: '00:00:30', text: "I particularly like this person because she inspires me to be a good human being every single day of my life." },
];

const levelLabelMap = {
  beginner: 'Beginner',
  elementary: 'Elementary',
  intermediate: 'Intermediate',
  upper_intermediate: 'Upper Intermediate',
  advanced: 'Advanced',
  proficient: 'Proficient',
};

function safeNumber(value, fallback = 0) {
  const num = Number(value);
  return Number.isFinite(num) ? num : fallback;
}

function clampScore(value) {
  const num = safeNumber(value, 0);
  return Math.max(0, Math.min(100, Math.round(num)));
}

function scoreToLevelLabel(score) {
  const value = safeNumber(score, 0);
  if (value >= 85) return 'Proficient';
  if (value >= 75) return 'Advanced';
  if (value >= 60) return 'Upper Intermediate';
  if (value >= 45) return 'Intermediate';
  if (value >= 30) return 'Elementary';
  return 'Beginner';
}

function hasExplicitScore(value) {
  return Number.isFinite(Number(value));
}

function levelKeyToLabel(levelKey, fallbackScore = 0) {
  const key = String(levelKey || '').toLowerCase();
  if (levelLabelMap[key]) return levelLabelMap[key];
  return scoreToLevelLabel(fallbackScore);
}

function parseDurationToSeconds(value) {
  if (typeof value === 'number' && Number.isFinite(value)) {
    return Math.max(0, Math.round(value));
  }
  const text = String(value || '').trim();
  if (!text) return 0;
  if (/^\d+(\.\d+)?$/.test(text)) {
    return Math.max(0, Math.round(Number(text)));
  }
  const parts = text.split(':').map((part) => Number(part));
  if (parts.some((part) => !Number.isFinite(part))) return 0;
  if (parts.length === 2) return parts[0] * 60 + parts[1];
  if (parts.length === 3) return parts[0] * 3600 + parts[1] * 60 + parts[2];
  return 0;
}

function formatDuration(secondsValue) {
  const raw = Number(secondsValue);
  const seconds = Number.isFinite(raw) ? Math.max(0, Math.round(raw)) : 0;
  const mins = Math.floor(seconds / 60);
  const secs = seconds % 60;
  return `${String(mins).padStart(2, '0')}:${String(secs).padStart(2, '0')}`;
}

function formatDateTime(value) {
  if (!value) return '';
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) return '';
  return date.toLocaleString('en-GB', {
    day: 'numeric',
    month: 'short',
    year: 'numeric',
    hour: '2-digit',
    minute: '2-digit',
  });
}

function chunkTranscript(text, totalSeconds) {
  const words = String(text || '').trim().split(/\s+/).filter(Boolean);
  if (!words.length) return [];
  const chunkSize = 28;
  const total = safeNumber(totalSeconds, 0);
  const chunks = [];
  for (let i = 0; i < words.length; i += chunkSize) {
    const ratio = total > 0 ? i / words.length : 0;
    const seconds = total > 0 ? Math.round(total * ratio) : 0;
    chunks.push({
      time: formatDuration(seconds),
      text: words.slice(i, i + chunkSize).join(' '),
    });
  }
  return chunks;
}

function percentFromRange(value, min, max) {
  const num = Number(value);
  if (!Number.isFinite(num) || max <= min) return null;
  const pct = ((num - min) / (max - min)) * 100;
  return Math.min(100, Math.max(0, Math.round(pct)));
}

const cefrOrder = ['A1', 'A2', 'B1', 'B2', 'C1', 'C2'];
function percentFromCefr(value) {
  const level = String(value || '').toUpperCase();
  const idx = cefrOrder.indexOf(level);
  if (idx === -1) return null;
  return Math.round(((idx + 1) / cefrOrder.length) * 100);
}

function computeWpm(text, totalSeconds) {
  const words = String(text || '').trim().split(/\s+/).filter(Boolean);
  const seconds = safeNumber(totalSeconds, 0);
  if (!words.length || !seconds) return 0;
  const minutes = seconds / 60;
  return Math.round(words.length / minutes);
}

function extractRephraseText(rawValue) {
  if (rawValue === null || rawValue === undefined) return '';

  let current = rawValue;
  for (let i = 0; i < 3; i += 1) {
    if (typeof current !== 'string') break;
    const trimmed = current.trim();
    if (!trimmed) return '';
    const looksJson =
      (trimmed.startsWith('{') && trimmed.endsWith('}')) ||
      (trimmed.startsWith('[') && trimmed.endsWith(']')) ||
      (trimmed.startsWith('"') && trimmed.endsWith('"'));
    if (!looksJson) {
      current = trimmed;
      break;
    }
    try {
      current = JSON.parse(trimmed);
    } catch {
      current = trimmed;
      break;
    }
  }

  if (typeof current === 'string') return current.trim();

  if (Array.isArray(current)) {
    return current
      .map((item) => (typeof item === 'string' ? item.trim() : ''))
      .filter(Boolean)
      .join(' ')
      .trim();
  }

  if (current && typeof current === 'object') {
    const direct =
      current.answer ??
      current.text ??
      current.rephrasing ??
      current.rephrase ??
      current.output ??
      current.response ??
      current.result;
    if (typeof direct === 'string') return direct.trim();
    if (direct && typeof direct === 'object') {
      const nested = direct.answer ?? direct.text ?? direct.output;
      if (typeof nested === 'string') return nested.trim();
    }
    if (Array.isArray(current.choices) && current.choices.length > 0) {
      const content = current.choices[0]?.message?.content ?? current.choices[0]?.text;
      if (typeof content === 'string') return content.trim();
    }
  }

  return String(rawValue || '').trim();
}

function SpeedometerGauge({ wpm = 137 }) {
  const [animated, setAnimated] = React.useState(false);

  React.useEffect(() => {
    const t = setTimeout(() => setAnimated(true), 300);
    return () => clearTimeout(t);
  }, []);

  // Gauge goes from 60 to 240 wpm across the upper semicircle (-180deg..0deg).
  const min = 60, max = 240;
  const clampedWpm = Math.min(Math.max(wpm, min), max);
  const wpmToAngle = (value) => -180 + ((value - min) / (max - min)) * 180;
  const needleAngle = animated ? wpmToAngle(clampedWpm) : -180;

  // Arc segments colours: red(60-80), orange(80-100), yellow(100-120), green(120-180), yellow(180-200), orange(200-220), red(220-240)
  const cx = 100, cy = 90, r = 70;
  const segments = [
    { from: 60,  to: 80,  color: '#DC2626' },
    { from: 80,  to: 100, color: '#F97316' },
    { from: 100, to: 120, color: '#EAB308' },
    { from: 120, to: 180, color: '#16A34A' },
    { from: 180, to: 200, color: '#EAB308' },
    { from: 200, to: 220, color: '#F97316' },
    { from: 220, to: 240, color: '#DC2626' },
  ];

  const toRad = (deg) => (deg * Math.PI) / 180;

  const arcPath = (fromWpm, toWpm, radius) => {
    const a1 = toRad(wpmToAngle(fromWpm));
    const a2 = toRad(wpmToAngle(toWpm));
    const x1 = cx + radius * Math.cos(a1);
    const y1 = cy + radius * Math.sin(a1);
    const x2 = cx + radius * Math.cos(a2);
    const y2 = cy + radius * Math.sin(a2);
    const largeArc = toWpm - fromWpm > (max - min) / 2 ? 1 : 0;
    return `M ${x1} ${y1} A ${radius} ${radius} 0 ${largeArc} 1 ${x2} ${y2}`;
  };

  const tickLabels = [60, 80, 100, 120, 140, 160, 180, 200, 220, 240];

  return (
    <svg viewBox="0 0 200 110" className="w-full max-w-[220px]">
      {/* Segments */}
      {segments.map((seg, i) => (
        <path
          key={i}
          d={arcPath(seg.from, seg.to, r)}
          fill="none"
          stroke={seg.color}
          strokeWidth="14"
          strokeLinecap="butt"
        />
      ))}

      {/* Tick labels */}
      {tickLabels.map((w) => {
        const angle = toRad(wpmToAngle(w));
        const lx = cx + (r + 14) * Math.cos(angle);
        const ly = cy + (r + 14) * Math.sin(angle);
        return (
          <text key={w} x={lx} y={ly} textAnchor="middle" dominantBaseline="middle" fontSize="7" fill="#6B5D52" fontWeight="600">
            {w}
          </text>
        );
      })}

      {/* Needle */}
      <g style={{ transformOrigin: `${cx}px ${cy}px`, transform: `rotate(${needleAngle}deg)`, transition: 'transform 1.4s cubic-bezier(0.34,1.56,0.64,1)' }}>
        <line x1={cx} y1={cy} x2={cx + r - 8} y2={cy} stroke="#1F2937" strokeWidth="2.5" strokeLinecap="round" />
        <circle cx={cx} cy={cy} r="5" fill="#1F2937" />
      </g>
    </svg>
  );
}

function clampVocabularyPercent(value) {
  const numeric = Number(value);
  if (!Number.isFinite(numeric)) return 0;
  return Math.max(0, Math.min(100, Math.round(numeric)));
}

function buildVocabularyDistribution(vocabularyStats) {
  const stats = vocabularyStats && typeof vocabularyStats === 'object' ? vocabularyStats : {};
  const levels = [
    { level: 'C2', percent: clampVocabularyPercent(stats?.CEFR_C2_pct), color: '#1E40AF' },
    { level: 'C1', percent: clampVocabularyPercent(stats?.CEFR_C1_pct), color: '#3B82F6' },
    { level: 'B2', percent: clampVocabularyPercent(stats?.CEFR_B2_pct), color: '#60A5FA' },
    { level: 'B1', percent: clampVocabularyPercent(stats?.CEFR_B1_pct), color: '#93C5FD' },
    { level: 'A2', percent: clampVocabularyPercent(stats?.CEFR_A2_pct), color: '#BFDBFE' },
    { level: 'A1', percent: clampVocabularyPercent(stats?.CEFR_A1_pct), color: '#DBEAFE' },
  ];

  return {
    levels,
    advancedPercent: clampVocabularyPercent(
      levels
        .filter((item) => ['B2', 'C1', 'C2'].includes(item.level))
        .reduce((sum, item) => sum + item.percent, 0)
    ),
  };
}

function VocabularyHighlights({ onVideoClick, score, level, vocabularyStats = null }) {
  const displayScore = Number.isFinite(score) && score > 0 ? score : 85;
  const displayLevel = level || 'Advanced';
  const { levels, advancedPercent } = React.useMemo(
    () => buildVocabularyDistribution(vocabularyStats),
    [vocabularyStats]
  );
  return (
    <div className="flex flex-col md:flex-row gap-4">
      {/* Score box */}
      <div className="flex flex-col items-center justify-center border-2 border-[#7C3AED] rounded-xl p-6 bg-[#F5F3FF] md:w-48 flex-shrink-0">
        <div className="w-20 h-20 bg-[#7C3AED] rounded-xl flex items-center justify-center mb-3 shadow-md">
          <span className="text-2xl font-extrabold text-white">{displayScore}%</span>
        </div>
        <div className="text-sm font-bold text-[#6B5D52]">Your Level</div>
        <div className="mt-1 max-w-[10rem] text-center text-base font-extrabold leading-tight text-[#7C3AED]">{displayLevel}</div>
      </div>

      {/* CEFR Distribution */}
      <div className="flex-1 bg-[#FAF5F0] rounded-xl border border-[#E5DDD5] p-4">
        <div className="flex items-center gap-1.5 mb-1">
          <h4 className="text-sm font-extrabold text-[#4A1429]">Vocabulary Distribution</h4>
          <Info className="w-3.5 h-3.5 text-[#6B5D52]" />
        </div>
        <p className="text-xs text-[#6B5D52] mb-3 leading-relaxed">
          Using advanced Vocabulary (CEFR levels B2, C1 and C2) adds colour and flair to your delivery.
        </p>
        <div className="flex items-start gap-4">
          <div className="text-center">
            <div className="text-2xl font-extrabold text-[#3B82F6]">{advancedPercent}%</div>
            <div className="text-[10px] text-[#6B5D52] font-medium">Advanced<br/>Vocabulary</div>
          </div>
          <div className="flex-1 space-y-1.5">
            {levels.map((item) => (
              <div key={item.level} className="flex items-center gap-2">
                <div className="w-7 h-7 rounded-full flex items-center justify-center text-white text-[10px] font-bold flex-shrink-0" style={{ backgroundColor: item.color }}>
                  {item.level}
                </div>
                <div className="flex-1 h-5 bg-gray-100 rounded-full overflow-hidden relative">
                  <motion.div
                    initial={{ width: 0 }}
                    animate={{ width: `${item.percent}%` }}
                    transition={{ duration: 0.9, ease: 'easeOut', delay: levels.indexOf(item) * 0.08 }}
                    className="h-full rounded-full flex items-center justify-end pr-1.5"
                    style={{ backgroundColor: item.color, minWidth: item.percent > 0 ? '1.5rem' : 0 }}
                  >
                    <span className="text-[9px] font-bold" style={{ color: item.level === 'A2' || item.level === 'A1' ? '#1E40AF' : '#fff' }}>
                      {item.percent}%
                    </span>
                  </motion.div>
                </div>
              </div>
            ))}
          </div>
        </div>
      </div>

      {/* Suggestions */}
      <div className="flex-1 bg-[#FAF5F0] rounded-xl border border-[#E5DDD5] p-4">
        <h4 className="text-sm font-extrabold text-[#4A1429] mb-2">Suggestions for Improvement</h4>
        <p className="text-xs text-[#6B5D52] mb-3 leading-relaxed">
          Exploring high-level synonyms will help you expand your Active Vocabulary Bank.
        </p>
        <div onClick={() => onVideoClick(VOCABULARY_TUTORIAL_VIDEO_ID)} className="flex items-center gap-3 bg-white rounded-xl border border-[#E5DDD5] p-2 cursor-pointer hover:bg-[#F5EFE7] transition-colors">
          <div className="w-12 h-9 rounded-lg overflow-hidden flex-shrink-0 bg-gray-200 relative">
            <img src={VOCABULARY_TUTORIAL_THUMBNAIL} alt="Vocabulary tutorial preview" className="w-full h-full object-cover" />
            <div className="absolute inset-0 flex items-center justify-center bg-black/30"><Play className="w-3 h-3 text-white" /></div>
          </div>
          <span className="text-xs font-semibold text-[#4A1429]">Vocabulary tutorial</span>
        </div>
      </div>
    </div>
  );
}

function PronunciationHighlights({ guides, onVideoClick, score, level }) {
  const displayScore = Number.isFinite(score) && score > 0 ? score : 92;
  const displayLevel = level || 'Proficient';
  const items = Array.isArray(guides)
    ? guides.filter((guide) => {
        const hasVideo = Boolean(guide?.video_id);
        const hasPreview = Boolean(String(guide?.preview_image || guide?.thumbnail || '').trim());
        return hasVideo && hasPreview;
      })
    : [];

  return (
    <div className="grid md:grid-cols-3 gap-4">
      <div className="h-fit self-start flex flex-col items-center justify-center border-2 border-[#A73121] rounded-xl p-6 bg-[#FFF5F5]">
        <div className="w-20 h-20 bg-[#A73121] rounded-xl flex items-center justify-center mb-3 shadow-md">
          <span className="text-2xl font-extrabold text-white">{displayScore}%</span>
        </div>
        <div className="text-sm font-bold text-[#6B5D52]">Your Level</div>
        <div className="mt-1 max-w-[10rem] text-center text-base font-extrabold leading-tight text-[#A73121]">{displayLevel}</div>
      </div>

      <div className="md:col-span-2">
        <div className="flex items-center gap-2 mb-3">
          <h4 className="text-sm font-extrabold text-[#4A1429]">Pronunciation by skill</h4>
          <Info className="w-3.5 h-3.5 text-[#6B5D52]" />
        </div>

        {!items.length ? (
          <div className="rounded-xl border border-dashed border-[#E5DDD5] bg-[#FAF5F0] px-4 py-5 text-sm text-[#6B5D52]">
            No pronunciation guide matched the phonemes detected in this answer yet.
          </div>
        ) : (
          <div className="max-h-[32rem] space-y-3 overflow-y-auto pr-2">
            {items.map((guide) => {
              const hasVideo = Boolean(guide?.video_id);
              const phonemeLabel = guide?.display_phoneme || `/${guide?.phoneme || ''}/`;
              const previewImage = guide?.preview_image || guide?.thumbnail || '';
              const exampleWords = Array.isArray(guide?.example_words) ? guide.example_words.filter(Boolean) : [];

              return (
                <div key={`${guide?.phoneme}-${guide?.video_id || 'guide'}`} className="flex items-start gap-3">
                  <div className="w-20 pt-2 text-xs font-bold text-[#4A1429]">Skill : {phonemeLabel}</div>
                  <button
                    type="button"
                    disabled={!hasVideo}
                    onClick={() => {
                      if (hasVideo) onVideoClick(guide.video_id);
                    }}
                    className={`flex-1 rounded-xl border border-[#E5DDD5] bg-[#FAF5F0] px-4 py-3 text-left transition-colors ${
                      hasVideo ? 'hover:bg-[#F5EFE7]' : 'cursor-default'
                    }`}
                  >
                    <div className="flex flex-col gap-3 sm:flex-row sm:items-start">
                      <div className="relative h-20 w-full overflow-hidden rounded-lg bg-[#E9DED3] sm:w-32 sm:flex-shrink-0">
                        {previewImage ? (
                          <img
                            src={previewImage}
                            alt={`Video preview for ${phonemeLabel}`}
                            className="h-full w-full object-cover"
                          />
                        ) : (
                          <div className="flex h-full w-full items-center justify-center bg-[#4A1429] text-sm font-extrabold text-[#D4B038]">
                            {phonemeLabel}
                          </div>
                        )}
                        <div className="absolute inset-0 flex items-center justify-center bg-black/25">
                          {hasVideo ? (
                            <div className="flex h-9 w-9 items-center justify-center rounded-full bg-black/55">
                              <Play className="ml-0.5 h-4 w-4 text-white" />
                            </div>
                          ) : (
                            <div className="rounded-full bg-white/90 px-2 py-1 text-[10px] font-bold text-[#4A1429]">
                              Guide
                            </div>
                          )}
                        </div>
                      </div>

                      <div className="min-w-0 flex-1">
                        <div className="flex flex-wrap items-center gap-2">
                          <span className="text-sm font-semibold text-[#4A1429]">
                            {hasVideo ? `Video tutorial for ${phonemeLabel}` : `Guide for ${phonemeLabel}`}
                          </span>
                          {guide?.average_score ? (
                            <span className="rounded-full bg-white px-2 py-0.5 text-[10px] font-bold text-[#A73121] border border-[#E5DDD5]">
                              {guide.average_score}% avg
                            </span>
                          ) : null}
                        </div>
                        <p className="mt-1 text-xs leading-relaxed text-[#6B5D52]">
                          {guide?.definition || 'Guide available for this phoneme.'}
                        </p>
                        {exampleWords.length ? (
                          <p className="mt-2 text-[10px] font-medium uppercase tracking-[0.12em] text-[#8B7967]">
                            Heard in: {exampleWords.join(', ')}
                          </p>
                        ) : null}
                      </div>
                    </div>
                  </button>
                </div>
              );
            })}
          </div>
        )}
      </div>
    </div>
  );
}

function GrammarHighlights({ score, level }) {
  const displayScore = Number.isFinite(score) && score > 0 ? score : 80;
  const displayLevel = level || 'Advanced';
  const suggestions = [
    'Using a mix of both simple and complex grammatical structures will allow you to express complex ideas with clarity while remaining direct and impactful!',
    'Use the active voice as often as possible. This will add punch and clarity to your speech!',
  ];

  return (
    <div className="flex flex-col md:flex-row gap-4">
      {/* Score box */}
      <div className="flex flex-col items-center justify-center border-2 border-[#059669] rounded-xl p-6 bg-[#F0FDF4] md:w-48 flex-shrink-0">
        <div className="w-20 h-20 bg-[#059669] rounded-xl flex items-center justify-center mb-3 shadow-md">
          <span className="text-2xl font-extrabold text-white">{displayScore}%</span>
        </div>
        <div className="text-sm font-bold text-[#6B5D52]">Your Level</div>
        <div className="mt-1 max-w-[10rem] text-center text-base font-extrabold leading-tight text-[#059669]">{displayLevel}</div>
      </div>

      {/* Suggestions */}
      <div className="flex-1 bg-[#FAF5F0] rounded-xl border border-[#E5DDD5] p-5">
        <h4 className="text-sm font-extrabold text-[#4A1429] mb-3">Suggestions for Improvement</h4>
        <div className="space-y-3">
          {suggestions.map((s, i) => (
            <div key={i} className="flex items-start gap-2 text-xs text-[#6B5D52] leading-relaxed">
              <div className="w-4 h-4 rounded-full border-2 border-[#059669] flex-shrink-0 mt-0.5" />
              <span>{s}</span>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

function AnimatedNumber({ target, suffix = '' }) {
  const [value, setValue] = React.useState(0);

  React.useEffect(() => {
    setValue(0);
    const duration = 1200;
    const steps = 40;
    const increment = target / steps;
    let current = 0;
    const timer = setInterval(() => {
      current += increment;
      if (current >= target) {
        setValue(target);
        clearInterval(timer);
      } else {
        setValue(Math.floor(current));
      }
    }, duration / steps);
    return () => clearInterval(timer);
  }, [target]);

  return <span>{value}{suffix}</span>;
}

function FluencyHighlights({ onVideoClick, wpm, score, level }) {
  const safeWpm = wpm && wpm > 0 ? wpm : 137;
  const paceLabel = safeWpm < 110 ? 'Slow Pace' : safeWpm <= 180 ? 'Good Pace' : 'Fast Pace';
  const displayScore = Number.isFinite(score) && score > 0 ? score : 90;
  const displayLevel = level || 'Proficient';
  return (
    <div className="flex flex-col md:flex-row gap-4">
      {/* Score box */}
      <div className="flex flex-col items-center justify-center border-2 border-[#16A34A] rounded-xl p-6 bg-[#F0FDF4] md:w-48 flex-shrink-0">
        <div className="w-20 h-20 bg-[#16A34A] rounded-xl flex items-center justify-center mb-3 shadow-md">
          <span className="text-2xl font-extrabold text-white">{displayScore}%</span>
        </div>
        <div className="text-sm font-bold text-[#6B5D52]">Your Level</div>
        <div className="mt-1 max-w-[10rem] text-center text-base font-extrabold leading-tight text-[#16A34A]">{displayLevel}</div>
      </div>

      {/* Pace Score gauge */}
      <div className="flex-1 flex flex-col items-center justify-center bg-[#FAF5F0] rounded-xl border border-[#E5DDD5] p-4 text-center">
        <div className="text-sm font-extrabold text-[#4A1429] mb-1">Pace Score</div>
        <SpeedometerGauge wpm={safeWpm} />
        <div className="text-xl font-extrabold text-[#4A1429] -mt-1">{safeWpm} wpm</div>
        <div className="text-sm font-extrabold text-[#16A34A]">{paceLabel}</div>
      </div>

      {/* Suggestions */}
      <div className="flex-1 bg-[#FAF5F0] rounded-xl border border-[#E5DDD5] p-4">
        <h4 className="text-sm font-extrabold text-[#4A1429] mb-1">Suggestions for Improvement</h4>
        <p className="text-xs text-[#6B5D52] mb-3 leading-relaxed">
          Maintaining your pace between 120 wpm and 180 wpm will help you keep your audience engaged.
        </p>
        <div onClick={() => onVideoClick(FLUENCY_TUTORIAL_VIDEO_ID)} className="flex items-center gap-3 bg-white rounded-xl border border-[#E5DDD5] p-2 cursor-pointer hover:bg-[#F5EFE7] transition-colors">
          <div className="w-12 h-9 rounded-lg overflow-hidden flex-shrink-0 bg-gray-200 relative">
            <img src={FLUENCY_TUTORIAL_THUMBNAIL} alt="Fluency tutorial preview" className="w-full h-full object-cover" />
            <div className="absolute inset-0 flex items-center justify-center bg-black/30"><Play className="w-3 h-3 text-white" /></div>
          </div>
          <span className="text-xs font-semibold text-[#4A1429]">Video tutorial for Fluency skill</span>
        </div>
      </div>
    </div>
  );
}

const rephrasedText = "One of my closest friends is Sasha - a truly remarkable woman who recently celebrated her wedding. We first crossed paths at an audition, and she has since become someone I deeply cherish. She is open-minded, honest, and encourages me to be my most authentic self. We have shared countless coffee outings, and I admire her deeply because she consistently inspires me to be a better human being.";

function TranscriptWithRephrase({ transcript, rephraseText }) {
  const [isLoading, setIsLoading] = useState(false);
  const [rephrased, setRephrased] = useState(false);
  const [displayedWords, setDisplayedWords] = useState([]);
  const finalRephraseText = (rephraseText || '').trim() || rephrasedText;
  const finalRephraseWords = useMemo(
    () => finalRephraseText.split(/\s+/).filter(Boolean),
    [finalRephraseText]
  );
  const typingTimerRef = useRef(null);

  const clearTypingTimer = () => {
    if (typingTimerRef.current) {
      clearTimeout(typingTimerRef.current);
      typingTimerRef.current = null;
    }
  };

  const getWordDelay = (word) => {
    const text = String(word || '').trim();
    if (!text) return 170;
    if (/[.!?]["']?$/.test(text)) return 420;
    if (/[,;:]["']?$/.test(text)) return 280;
    return text.length >= 8 ? 220 : 180;
  };

  useEffect(() => () => clearTypingTimer(), []);

  useEffect(() => {
    if (!rephrased || !finalRephraseWords.length) {
      clearTypingTimer();
      return undefined;
    }

    let cancelled = false;

    const revealNextWord = (index) => {
      if (cancelled) return;

      setDisplayedWords(finalRephraseWords.slice(0, index + 1));

      if (index + 1 >= finalRephraseWords.length) {
        typingTimerRef.current = null;
        return;
      }

      typingTimerRef.current = setTimeout(
        () => revealNextWord(index + 1),
        getWordDelay(finalRephraseWords[index])
      );
    };

    typingTimerRef.current = setTimeout(() => revealNextWord(0), 320);

    return () => {
      cancelled = true;
      clearTypingTimer();
    };
  }, [finalRephraseWords, rephrased]);

  const handleRephrase = () => {
    if (rephrased || isLoading) return;
    clearTypingTimer();
    setDisplayedWords([]);
    setIsLoading(true);
    setTimeout(() => {
      setIsLoading(false);
      setRephrased(true);
    }, 1200);
  };

  return (
    <motion.div
      initial={{ opacity: 0, y: 20 }}
      animate={{ opacity: 1, y: 0 }}
      transition={{ delay: 0.35 }}
      className="bg-white rounded-2xl shadow-md border border-[#E5DDD5] overflow-hidden"
    >
      <div className="bg-gradient-to-r from-[#4A1429] to-[#5A1839] px-6 py-4">
        <h3 className="text-base font-extrabold text-white">📝 Transcript</h3>
      </div>
      <div className="p-6 grid md:grid-cols-2 gap-6">
        <div className="space-y-4">
          {transcript.map((entry, i) => (
            <div key={i}>
              <div className="text-xs font-mono text-[#6B5D52] mb-1 flex items-center gap-1">
                <span className="text-[#D4B038]">⏱</span> {entry.time}
              </div>
              <p className="text-sm text-[#4A1429] leading-relaxed">{entry.text}</p>
            </div>
          ))}
        </div>
        <div className="flex flex-col items-start bg-[#FAF5F0] rounded-xl border border-[#E5DDD5] p-6 gap-4 min-h-[180px]">
          {!rephrased && !isLoading && (
            <>
              <div className="flex items-center gap-3 w-full">
                <div className="w-10 h-10 bg-[#4A1429] rounded-full flex items-center justify-center flex-shrink-0">
                  <span className="text-[#D4B038] font-extrabold text-sm">CV</span>
                </div>
                <p className="text-sm text-[#6B5D52] leading-relaxed">
                  Your speech could be better with the help of Cambridge Veritas. Click below to get a rephrased version.
                </p>
              </div>
              <Button onClick={handleRephrase} className="bg-[#4A1429] hover:bg-[#3A1020] text-white font-bold px-6 py-2 rounded-lg shadow-md text-sm w-full">
                Rephrase my speech
              </Button>
            </>
          )}
          {isLoading && (
            <div className="flex flex-col items-center justify-center w-full h-full gap-3 py-4">
              <Loader2 className="w-8 h-8 text-[#4A1429] animate-spin" />
              <p className="text-sm text-[#6B5D52] font-medium">AI is rephrasing your speech...</p>
            </div>
          )}
          {rephrased && (
            <div className="w-full">
              <div className="flex items-center gap-2 mb-3">
                <div className="w-7 h-7 bg-[#4A1429] rounded-full flex items-center justify-center flex-shrink-0">
                  <span className="text-[#D4B038] font-extrabold text-xs">CV</span>
                </div>
                <span className="text-xs font-bold text-[#4A1429]">Cambridge Veritas Suggestion</span>
              </div>
              <p className="text-sm text-[#4A1429] leading-relaxed break-normal whitespace-pre-wrap max-w-full">
                {displayedWords.map((word, i) => (
                  <motion.span
                    key={i}
                    initial={{ opacity: 0 }}
                    animate={{ opacity: 1 }}
                    className="mr-1 inline-block whitespace-nowrap"
                  >
                    {word}
                  </motion.span>
                ))}
                {displayedWords.length < finalRephraseWords.length && (
                  <span className="inline-block w-0.5 h-4 bg-[#4A1429] animate-pulse ml-0.5 align-middle" />
                )}
              </p>
            </div>
          )}
        </div>
      </div>
    </motion.div>
  );
}

function YouTubeModal({ videoId, onClose }) {
  return (
    <AnimatePresence>
      {videoId && (
        <motion.div
          initial={{ opacity: 0 }}
          animate={{ opacity: 1 }}
          exit={{ opacity: 0 }}
          className="fixed inset-0 z-50 flex items-center justify-center bg-black/70 p-4"
          onClick={onClose}
        >
          <motion.div
            initial={{ scale: 0.9 }}
            animate={{ scale: 1 }}
            exit={{ scale: 0.9 }}
            className="relative w-full max-w-2xl bg-black rounded-2xl overflow-hidden shadow-2xl"
            onClick={e => e.stopPropagation()}
          >
            <button onClick={onClose} className="absolute top-3 right-3 z-10 w-8 h-8 bg-black/60 hover:bg-black rounded-full flex items-center justify-center text-white">
              <X className="w-4 h-4" />
            </button>
            <div className="aspect-video">
              <iframe
                src={`https://www.youtube.com/embed/${videoId}?autoplay=1`}
                className="w-full h-full"
                allow="autoplay; encrypted-media"
                allowFullScreen
              />
            </div>
          </motion.div>
        </motion.div>
      )}
    </AnimatePresence>
  );
}

export default function ResultPage({ part, token }) {
  const navigate = useNavigate();
  const routeParams = useParams();
  const [showComparison, setShowComparison] = useState(false);
  const [activeSkill, setActiveSkill] = useState('pronunciation');
  const [youtubeVideoId, setYoutubeVideoId] = useState(null);
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState('');
  const audioRef = useRef(null);
  const [isPlaying, setIsPlaying] = useState(false);
  const [audioPosition, setAudioPosition] = useState(0);
  const [audioDuration, setAudioDuration] = useState(0);

  const routePart = Array.isArray(routeParams?.part) ? routeParams.part[0] : routeParams?.part;
  const routeToken = Array.isArray(routeParams?.token) ? routeParams.token[0] : routeParams?.token;
  const partId = Number(part || routePart) || 0;
  const tokenId = String(token || routeToken || '').trim();
  const summary = data?.summary || {};
  const resultRow = data?.result || {};
  const resultJson = data?.result_json || {};
  const intonationData = resultJson?.result?.intonation || null;
  const transcriptText = String(summary?.transcript || resultJson?.result?.transcription || '').trim();
  const totalSeconds = parseDurationToSeconds(summary?.speakingTime || resultJson?.result?.numeric_duration || resultJson?.result?.duration);
  const speakingTime = summary?.speakingTime || (totalSeconds ? formatDuration(totalSeconds) : '');
  const wordsPerMinute = useMemo(() => computeWpm(transcriptText, totalSeconds), [transcriptText, totalSeconds]);
  const transcriptRows = useMemo(() => {
    const chunks = chunkTranscript(transcriptText, totalSeconds);
    return chunks.length ? chunks : transcript;
  }, [transcriptText, totalSeconds]);
  const rephraseText = extractRephraseText(resultRow?.rephrasing);

  useEffect(() => {
    if (!tokenId) {
      setLoading(false);
      setError('Missing result token.');
      return;
    }

    let active = true;
    const controller = new AbortController();

    const fetchResult = async (source = 'tools', allowFallback = true) => {
      try {
        setLoading(true);
        setError('');
        const res = await fetch(getApiPath(`/api/speech/result?token=${encodeURIComponent(tokenId)}&source=${source}`), {
          signal: controller.signal,
        });

        if (!res.ok) {
          if (res.status === 404 && allowFallback) {
            return fetchResult('legacy', false);
          }
          const payload = await res.json().catch(() => ({}));
          throw new Error(payload?.message || 'Failed to load results.');
        }

        const payload = await res.json();
        if (!active) return;
        setData(payload);
        setLoading(false);
      } catch (err) {
        if (!active || err.name === 'AbortError') return;
        setError(err.message || 'Failed to load results.');
        setLoading(false);
      }
    };

    fetchResult();
    return () => {
      active = false;
      controller.abort();
    };
  }, [tokenId]);

  useEffect(() => {
    const audio = audioRef.current;
    if (!audio) return undefined;

    const resolveDuration = () => {
      const directDuration = Number(audio.duration);
      if (Number.isFinite(directDuration) && directDuration > 0) {
        return directDuration;
      }

      if (audio.seekable && audio.seekable.length > 0) {
        const seekableEnd = Number(audio.seekable.end(audio.seekable.length - 1));
        if (Number.isFinite(seekableEnd) && seekableEnd > 0) {
          return seekableEnd;
        }
      }

      return safeNumber(totalSeconds, 0);
    };

    const syncPlayback = () => {
      const nextPosition = Number(audio.currentTime);
      setAudioPosition(Number.isFinite(nextPosition) ? nextPosition : 0);
      setAudioDuration(resolveDuration());
    };

    const handlePlay = () => setIsPlaying(true);
    const handlePause = () => setIsPlaying(false);
    const handleEnded = () => {
      syncPlayback();
      setIsPlaying(false);
    };

    syncPlayback();
    audio.addEventListener('timeupdate', syncPlayback);
    audio.addEventListener('loadedmetadata', syncPlayback);
    audio.addEventListener('loadeddata', syncPlayback);
    audio.addEventListener('durationchange', syncPlayback);
    audio.addEventListener('canplay', syncPlayback);
    audio.addEventListener('play', handlePlay);
    audio.addEventListener('pause', handlePause);
    audio.addEventListener('ended', handleEnded);

    return () => {
      audio.removeEventListener('timeupdate', syncPlayback);
      audio.removeEventListener('loadedmetadata', syncPlayback);
      audio.removeEventListener('loadeddata', syncPlayback);
      audio.removeEventListener('durationchange', syncPlayback);
      audio.removeEventListener('canplay', syncPlayback);
      audio.removeEventListener('play', handlePlay);
      audio.removeEventListener('pause', handlePause);
      audio.removeEventListener('ended', handleEnded);
    };
  }, [data?.audio?.url, totalSeconds]);

  let overallScore = clampScore(summary?.overall);
  if (!overallScore) {
    const bandOverall = safeNumber(resultJson?.result?.overall, 0);
    if (bandOverall > 0) {
      overallScore = clampScore((bandOverall / 9) * 100);
    } else if (summary?.scores) {
      const values = Object.values(summary.scores).map((value) => safeNumber(value, 0)).filter((value) => value > 0);
      if (values.length) {
        overallScore = clampScore(values.reduce((sum, value) => sum + value, 0) / values.length);
      }
    }
  }

  const overallLevelLabel = levelKeyToLabel(summary?.level, overallScore);

  const computedSkillTabs = useMemo(() => {
    const scores = summary?.scores || {};
    const intonationUnavailable = String(intonationData?.analysis_status || '').toLowerCase() === 'unavailable';
    return skillTabs.map((skill) => {
      const rawScore = scores?.[skill.id];
      const scoreValue = clampScore(hasExplicitScore(rawScore) ? rawScore : skill.score);
      return {
        ...skill,
        score: scoreValue,
        level: skill.id === 'intonation' && intonationUnavailable
          ? 'Unavailable'
          : hasExplicitScore(rawScore)
            ? scoreToLevelLabel(scoreValue)
            : skill.level,
      };
    });
  }, [summary, intonationData]);

  useEffect(() => {
    if (!computedSkillTabs.length) return;
    const hasActive = computedSkillTabs.some((skill) => skill.id === activeSkill);
    if (!hasActive) {
      setActiveSkill(computedSkillTabs[0].id);
    }
  }, [computedSkillTabs, activeSkill]);

  const activeSkillInfo = computedSkillTabs.find((skill) => skill.id === activeSkill) || computedSkillTabs[0];
  const intonationPitchVariation = Number.isFinite(Number(intonationData?.pitch_variation))
    ? Math.round(Number(intonationData.pitch_variation))
    : null;
  const intonationStateLabel = String(intonationData?.pitch_state || intonationData?.level || '').trim() || 'Balanced';
  const intonationAnalysisError = String(intonationData?.analysis_error || '').trim();

  const computedTests = useMemo(() => {
    const eqScores = resultJson?.result?.equivalent_scores || {};
    const cefrLevel = eqScores?.cefr_levels?.overall || eqScores?.cefr || null;
    const values = [
      { name: 'IELTS', min: 0, max: 9, value: eqScores?.ielts ?? eqScores?.ielts_band ?? resultJson?.result?.overall ?? null, color: '#DC2626' },
      { name: 'TOEFL', min: 0, max: 30, value: eqScores?.toefl ?? eqScores?.toefl_scores?.overall ?? null, color: '#059669' },
      { name: 'CEFR', min: 'A1', max: 'C2', value: cefrLevel, color: '#2563EB' },
      { name: 'Pearson PTE', min: 0, max: 90, value: eqScores?.pte ?? eqScores?.pte_scores?.overall ?? null, color: '#7C3AED' },
      { name: 'Duolingo', min: 10, max: 160, value: eqScores?.duolingo ?? eqScores?.duolingo_scores?.overall ?? null, color: '#059669' },
    ];

    return values.map((entry, index) => {
      const fallback = internationalTests[index];
      let percent = fallback?.percent ?? 0;
      if (entry.name === 'CEFR') {
        const pct = percentFromCefr(entry.value);
        if (pct !== null) percent = pct;
      } else {
        const pct = percentFromRange(entry.value, entry.min, entry.max);
        if (pct !== null) percent = pct;
      }
      const displayValue = entry.value !== null && entry.value !== undefined && entry.value !== '' ? String(entry.value) : fallback?.value;
      const status = scoreToLevelLabel(percent);
      return {
        name: entry.name,
        label: fallback?.label || 'Speaking score predictor',
        value: displayValue,
        min: entry.min ?? fallback?.min,
        max: entry.max ?? fallback?.max,
        percent,
        status,
        color: entry.color || fallback?.color,
      };
    });
  }, [resultJson]);

  const pronunciationGuides = Array.isArray(data?.pronunciation_guides) ? data.pronunciation_guides : [];

  const audioUrl = data?.audio?.url || '';
  const createdAtText = formatDateTime(resultRow?.created_at);
  const testLabel = data?.test_label || data?.category?.test_label || '';
  const detailsUrl = tokenId && partId ? `/tools/speech-analyser-result-details/${partId}/${tokenId}` : '/tools/past-results';

  const togglePlayback = async () => {
    const audio = audioRef.current;
    if (!audio) return;
    if (audio.paused) {
      try {
        await audio.play();
      } catch {
        setIsPlaying(false);
      }
    } else {
      audio.pause();
    }
  };

  const displayDuration = Number.isFinite(audioDuration) && audioDuration > 0
    ? audioDuration
    : safeNumber(totalSeconds, 0);
  const progressPercent = displayDuration > 0
    ? Math.min(100, Math.max(0, (audioPosition / displayDuration) * 100))
    : 0;

  if (loading) {
    return (
      <div className="min-h-screen flex items-center justify-center bg-[#FAF5F0]">
        <div className="w-10 h-10 border-4 border-[#E5DDD5] border-t-[#4A1429] rounded-full animate-spin" />
      </div>
    );
  }

  if (error) {
    return (
      <div className="min-h-screen flex items-center justify-center bg-[#FAF5F0] px-4">
        <div className="bg-white rounded-2xl border border-[#E5DDD5] p-6 max-w-md w-full text-center">
          <div className="text-lg font-extrabold text-[#4A1429] mb-2">Result Not Available</div>
          <div className="text-sm text-[#6B5D52] mb-4">{error}</div>
          <Button onClick={() => navigate('/tools/dashboard')} className="bg-[#4A1429] hover:bg-[#3A1020] text-white font-bold px-6 py-2 rounded-lg">
            Back to Dashboard
          </Button>
        </div>
      </div>
    );
  }

  return (
    <div className="min-h-screen bg-[#FAF5F0]">
      <YouTubeModal videoId={youtubeVideoId} onClose={() => setYoutubeVideoId(null)} />
      {/* Header */}
      <div className="bg-gradient-to-r from-[#4A1429] to-[#5A1839] text-white sticky top-0 z-20 shadow-xl border-b-4 border-[#D4B038]">
        <div className="max-w-4xl mx-auto px-4 py-4 flex items-center justify-between">
          <button
            onClick={() => navigate(-1)}
            className="flex items-center gap-2 text-white/80 hover:text-white transition-colors"
          >
            <ArrowLeft className="w-5 h-5" />
            <span className="font-medium text-sm">Back</span>
          </button>
          <div className="text-xl font-extrabold text-[#D4B038]">Your Results</div>
          <div className="w-16" />
        </div>
      </div>

      <div className="max-w-4xl mx-auto px-4 py-6 space-y-6">
        {(testLabel || partId || speakingTime || createdAtText) && (
          <div className="flex flex-col md:flex-row md:items-center md:justify-between text-sm text-[#6B5D52] gap-2">
            <div className="font-semibold text-[#4A1429]">
              {testLabel ? `${testLabel}${partId ? ` - Part ${partId}` : ''}` : partId ? `Part ${partId}` : ''}
            </div>
            <div className="text-left md:text-right">
              {speakingTime && <div>Speaking Time: {speakingTime}</div>}
              {createdAtText && <div>{createdAtText}</div>}
            </div>
          </div>
        )}

        {/* Overall Score Card */}
        <motion.div
          initial={{ opacity: 0, y: 20 }}
          animate={{ opacity: 1, y: 0 }}
          className="bg-white rounded-2xl shadow-md border border-[#E5DDD5] p-6 flex flex-col md:flex-row items-center gap-6"
        >
          {/* Circle */}
          <div className="flex flex-shrink-0 flex-col items-center">
            <div className="relative" style={{ width: 140, height: 140 }}>
              <svg className="w-full h-full -rotate-90" viewBox="0 0 140 140">
                <circle cx="70" cy="70" r="58" fill="none" stroke="#F5EFE7" strokeWidth="14" />
                <motion.circle
                  cx="70" cy="70" r="58"
                  fill="none" stroke="#4A1429" strokeWidth="14"
                  strokeLinecap="round"
                  strokeDasharray={2 * Math.PI * 58}
                  initial={{ strokeDashoffset: 2 * Math.PI * 58 }}
                  animate={{ strokeDashoffset: 2 * Math.PI * 58 * (1 - overallScore / 100) }}
                  transition={{ duration: 1.2, ease: 'easeOut' }}
                />
              </svg>
              <div className="absolute inset-0 flex items-center justify-center">
                <div className="text-3xl font-extrabold text-[#4A1429]">{overallScore}%</div>
              </div>
            </div>
            <div className="mt-3 max-w-[9rem] px-2 text-center text-xs font-bold leading-tight text-[#6B5D52]">
              {overallLevelLabel}
            </div>
          </div>

          {/* Text */}
          <div className="flex-1 text-center md:text-left">
            <h2 className="text-xl font-extrabold text-[#4A1429] mb-1">Overall Speaking Score</h2>
            <p className="text-[#D4B038] font-bold text-base mb-2">Your level is {overallLevelLabel}. You&apos;re moving up in the world!</p>
            <p className="text-sm text-[#6B5D52] leading-relaxed">
              Ever wonder how your Overall Speaking Score relates to other scoring systems? The collapsible section below has all the answers you&apos;re looking for. Our English Speaking Score Predictor helps you compare your performance with other recognised scoring systems for English proficiency.
            </p>
          </div>
        </motion.div>

        {/* Compare Score Section */}
        <motion.div
          initial={{ opacity: 0, y: 20 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ delay: 0.1 }}
          className="bg-white rounded-2xl shadow-md border border-[#E5DDD5] overflow-hidden"
        >
          <button
            onClick={() => setShowComparison(!showComparison)}
            className="w-full flex items-center justify-between px-6 py-4 hover:bg-[#FAF5F0] transition-colors"
          >
            <div className="flex items-center gap-2">
              <h3 className="text-base font-extrabold text-[#4A1429]">Compare your score with other international tests</h3>
              <Info className="w-4 h-4 text-[#6B5D52]" />
            </div>
            {showComparison ? <ChevronUp className="w-5 h-5 text-[#4A1429]" /> : <ChevronDown className="w-5 h-5 text-[#4A1429]" />}
          </button>

          <AnimatePresence>
            {showComparison && (
              <motion.div
                initial={{ height: 0, opacity: 0 }}
                animate={{ height: 'auto', opacity: 1 }}
                exit={{ height: 0, opacity: 0 }}
                className="overflow-hidden border-t border-[#E5DDD5]"
              >
                <div className="p-4 grid grid-cols-2 md:grid-cols-5 gap-3">
                  {computedTests.map((test, i) => (
                    <motion.div
                      key={test.name}
                      initial={{ opacity: 0, scale: 0.9 }}
                      animate={{ opacity: 1, scale: 1 }}
                      transition={{ delay: i * 0.07 }}
                      className="bg-[#FAF5F0] rounded-xl p-3 border border-[#E5DDD5] text-center"
                    >
                      <div className="text-xs font-bold text-[#6B5D52] mb-0.5">{test.name}</div>
                      <div className="text-[10px] text-[#6B5D52] mb-2">{test.label}</div>
                      <div className="text-2xl font-extrabold mb-1" style={{ color: test.color }}>{test.value}</div>
                      <div className="flex justify-between text-[9px] text-[#6B5D52] mb-1">
                        <span>{test.min}</span><span>{test.max}</span>
                      </div>
                      <div className="h-1.5 bg-gray-100 rounded-full overflow-hidden mb-2">
                        <div className="h-full rounded-full" style={{ width: `${test.percent}%`, backgroundColor: test.color }} />
                      </div>
                      <div className="text-xs font-bold" style={{ color: test.color }}>{test.status}</div>
                    </motion.div>
                  ))}
                </div>
              </motion.div>
            )}
          </AnimatePresence>
        </motion.div>

        {/* Score Breakdown */}
        <motion.div
          initial={{ opacity: 0, y: 20 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ delay: 0.2 }}
          className="bg-white rounded-2xl shadow-md border border-[#E5DDD5] overflow-hidden"
        >
          <div className="px-6 py-4 border-b border-[#E5DDD5] flex items-center justify-between">
            <div>
              <h3 className="text-base font-extrabold text-[#4A1429]">Score Breakdown</h3>
              <p className="text-xs text-[#6B5D52] mt-0.5">Focus on your Intonation to sound more natural when you speak.</p>
            </div>
            <button
              onClick={() => navigate(detailsUrl)}
              className="flex items-center gap-1 text-[#D4B038] hover:text-[#BFA030] font-bold text-sm transition-colors whitespace-nowrap"
            >
              Click to see details <ArrowRight className="w-4 h-4" />
            </button>
          </div>

          {/* Skill Tabs */}
          <div className="flex overflow-x-auto border-b border-[#E5DDD5]">
            {computedSkillTabs.map((skill) => {
              const Icon = skill.icon;
              const isActive = activeSkill === skill.id;
              return (
                <button
                  key={skill.id}
                  onClick={() => setActiveSkill(skill.id)}
                  className={`flex items-center gap-2 px-4 py-3 text-sm whitespace-nowrap transition-all border-b-2 flex-1 justify-center ${
                    isActive ? 'border-[#4A1429] text-[#4A1429] font-bold bg-[#FAF5F0]' : 'border-transparent text-[#6B5D52] hover:bg-[#FAF5F0]'
                  }`}
                >
                  <Icon className="w-3.5 h-3.5" style={{ color: isActive ? skill.color : undefined }} />
                  <div className="text-left">
                    <div className="font-semibold text-xs">{skill.label}</div>
                    <div className="text-[10px]" style={{ color: skill.color }}>{skill.level}</div>
                  </div>
                </button>
              );
            })}
          </div>

          {/* Tab Content */}
          <div className="p-6">
            {activeSkill === 'fluency' ? (
              <FluencyHighlights
                onVideoClick={setYoutubeVideoId}
                wpm={wordsPerMinute}
                score={activeSkillInfo?.score}
                level={activeSkillInfo?.level}
              />
            ) : activeSkill === 'grammar' ? (
              <GrammarHighlights score={activeSkillInfo?.score} level={activeSkillInfo?.level} />
            ) : activeSkill === 'vocabulary' ? (
              <VocabularyHighlights
                onVideoClick={setYoutubeVideoId}
                score={activeSkillInfo?.score}
                level={activeSkillInfo?.level}
                vocabularyStats={resultJson?.result?.vocabulary_stats || null}
              />
            ) : activeSkill === 'intonation' ? (
              /* Intonation Highlights */
              <div className="flex flex-col md:flex-row gap-4">
                {/* Score box */}
                <div className="flex flex-col items-center justify-center border-2 border-[#D4B038] rounded-xl p-6 bg-[#FFFBEB] md:w-48 flex-shrink-0">
                  <div className="w-20 h-20 bg-[#D4B038] rounded-xl flex items-center justify-center mb-3 shadow-md">
                    <span className="text-2xl font-extrabold text-white">{activeSkillInfo?.score ?? 90}%</span>
                  </div>
                  <div className="text-sm font-bold text-[#6B5D52]">Your Level</div>
                  <div className="mt-1 max-w-[10rem] text-center text-base font-extrabold leading-tight text-[#D4B038]">{activeSkillInfo?.level || 'Proficient'}</div>
                </div>

                {/* Pitch variation + suggestions */}
                <div className="flex-1 flex flex-col md:flex-row gap-4">
                  {/* Average Pitch */}
                  <div className="flex-1 flex flex-col items-center justify-center bg-[#FAF5F0] rounded-xl border border-[#E5DDD5] p-4 text-center">
                  <div className="flex items-center gap-1.5 mb-2">
                      <span className="text-sm font-extrabold text-[#4A1429]">Average Pitch Variation</span>
                      <Info className="w-3.5 h-3.5 text-[#6B5D52]" />
                    </div>
                    {intonationPitchVariation !== null ? (
                      <>
                        <div className="text-3xl font-extrabold text-[#D4B038] mb-2">
                          <AnimatedNumber target={intonationPitchVariation} suffix=" Hz" />
                        </div>
                        <div className="flex items-end gap-0.5 mb-2 h-10">
                          {[4, 6, 8, 12, 10, 14, 16, 18, 14, 12, 16, 20, 18, 16, 14, 12, 10, 8, 10, 14].map((h, i) => (
                            <div key={i} className="w-1.5 rounded-sm" style={{ height: `${h * 2}px`, backgroundColor: '#D4B038', opacity: 0.8 }} />
                          ))}
                        </div>
                        <div className="text-sm font-extrabold text-[#D4B038]">{intonationStateLabel}</div>
                      </>
                    ) : (
                      <div className="rounded-xl border border-dashed border-[#E5DDD5] bg-white px-4 py-5 text-sm leading-relaxed text-[#6B5D52]">
                        {intonationAnalysisError || 'Pitch data is not available for this recording.'}
                      </div>
                    )}
                  </div>

                  {/* Suggestions */}
                  <div className="flex-1 bg-[#FAF5F0] rounded-xl border border-[#E5DDD5] p-4">
                    <h4 className="text-sm font-extrabold text-[#4A1429] mb-1">Suggestions for Improvement</h4>
                    <p className="text-xs text-[#6B5D52] mb-3 leading-relaxed">
                      {intonationPitchVariation !== null
                        ? `Your pitch variation is around ${intonationPitchVariation} Hz. Keep aiming for the 50Hz to 150Hz target range.`
                        : 'We could not build a reliable pitch contour for this answer, so intonation guidance is limited for this attempt.'}
                    </p>
                    <div onClick={() => setYoutubeVideoId(INTONATION_TUTORIAL_VIDEO_ID)} className="flex items-center gap-3 bg-white rounded-xl border border-[#E5DDD5] p-2 cursor-pointer hover:bg-[#F5EFE7] transition-colors">
                      <div className="w-12 h-9 rounded-lg overflow-hidden flex-shrink-0 bg-gray-200 relative">
                        <img src={INTONATION_TUTORIAL_THUMBNAIL} alt="Intonation tutorial preview" className="w-full h-full object-cover" />
                        <div className="absolute inset-0 flex items-center justify-center bg-black/30"><Play className="w-3 h-3 text-white" /></div>
                      </div>
                      <span className="text-xs font-semibold text-[#4A1429]">Video tutorial Intonation</span>
                    </div>
                  </div>
                </div>
              </div>
            ) : (
              <PronunciationHighlights
                guides={pronunciationGuides}
                onVideoClick={setYoutubeVideoId}
                score={activeSkillInfo?.score}
                level={activeSkillInfo?.level}
              />
            )}
          </div>
        </motion.div>

        {/* Audio Player */}
        <motion.div
          initial={{ opacity: 0, y: 20 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ delay: 0.3 }}
          className="bg-white rounded-2xl shadow-md border border-[#E5DDD5] p-4 flex flex-col items-center gap-2"
        >
          <audio ref={audioRef} src={audioUrl || undefined} preload="metadata" />
          <div className="flex items-center gap-4">
            <button
              className="w-10 h-10 rounded-full bg-[#FAF5F0] border border-[#E5DDD5] flex items-center justify-center text-[#4A1429] hover:bg-[#F5EFE7] transition-colors"
              disabled
            >
              ⏮
            </button>
            <button
              onClick={togglePlayback}
              disabled={!audioUrl}
              className="w-12 h-12 rounded-full bg-[#4A1429] flex items-center justify-center text-white hover:bg-[#3A1020] transition-colors shadow-md disabled:opacity-60"
            >
              {isPlaying ? <Pause className="w-5 h-5" /> : <Play className="w-5 h-5 ml-0.5" />}
            </button>
            <button
              className="w-10 h-10 rounded-full bg-[#FAF5F0] border border-[#E5DDD5] flex items-center justify-center text-[#4A1429] hover:bg-[#F5EFE7] transition-colors"
              disabled
            >
              ⏭
            </button>
          </div>
          <div className="text-xs text-[#6B5D52] font-mono">
            {formatDuration(audioPosition)} / {formatDuration(displayDuration)}
          </div>
          <div className="w-full h-1.5 bg-[#FAF5F0] rounded-full border border-[#E5DDD5]">
            <div
              className="h-full bg-[#4A1429] rounded-full"
              style={{ width: `${progressPercent}%` }}
            />
          </div>
        </motion.div>

        {/* Transcript */}
        <TranscriptWithRephrase transcript={transcriptRows} rephraseText={rephraseText} />

        {/* CTA: See Score Details */}
        <motion.div
          initial={{ opacity: 0, y: 20 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ delay: 0.4 }}
          className="sticky bottom-4"
        >
          <Button
          onClick={() => navigate(detailsUrl)}
            className="w-full h-14 bg-[#D4B038] hover:bg-[#BFA030] text-[#4A1429] font-extrabold text-lg rounded-2xl shadow-xl flex items-center justify-center gap-3"
          >
            Click to see Score Details
            <ArrowRight className="w-5 h-5" />
          </Button>
        </motion.div>

      </div>
    </div>
  );
}




