import React, { useEffect, useRef, useState } from 'react';

import { SCORE_WEIGHTS } from '../../lib/dashboard-score';

interface ScoreRingProps {
  score: number;
  grade: string;
  monthOverMonth?: number;
  size?: number;
  strokeWidth?: number;
}

interface RingTheme {
  stroke: string;
  number: string;
  grade: string;
}

const ringThemeForGrade = (grade: string): RingTheme => {
  switch (grade) {
    case 'A':
      return {
        stroke: '#10b981',
        number: 'text-emerald-600',
        grade: 'text-emerald-600',
      };
    case 'B':
      return {
        stroke: '#84cc16',
        number: 'text-lime-600',
        grade: 'text-lime-600',
      };
    case 'C':
      return {
        stroke: '#f59e0b',
        number: 'text-amber-600',
        grade: 'text-amber-600',
      };
    case 'D':
      return {
        stroke: '#f97316',
        number: 'text-orange-600',
        grade: 'text-orange-600',
      };
    default:
      return {
        stroke: '#ef4444',
        number: 'text-red-600',
        grade: 'text-red-600',
      };
  }
};

const THRESHOLD_BANDS: Array<{ range: string; label: string; pill: string }> = [
  {
    range: '0-39',
    label: 'AI engines rarely cite you',
    pill: 'bg-red-50 text-red-600 border border-red-200',
  },
  {
    range: '40-59',
    label: 'Inconsistent mentions',
    pill: 'bg-amber-50 text-amber-700 border border-amber-200',
  },
  {
    range: '60-74',
    label: 'AI engines start citing you regularly',
    pill: 'bg-emerald-50 text-emerald-700 border border-emerald-200',
  },
  {
    range: '75+',
    label: 'You hold position against competitors',
    pill: 'bg-[#ffeef8] text-[#B7007C] border border-[#B7007C]/20',
  },
];

export function ScoreRing({
  score,
  grade,
  monthOverMonth,
  size = 240,
  strokeWidth = 12,
}: ScoreRingProps) {
  const radius: number = (size - strokeWidth) / 2;
  const circumference: number = 2 * Math.PI * radius;
  const clampedScore: number = Math.max(0, Math.min(100, score));
  const offset: number = circumference - (clampedScore / 100) * circumference;
  const theme: RingTheme = ringThemeForGrade(grade);
  const [infoOpen, setInfoOpen] = useState<boolean>(false);
  const popoverRef = useRef<HTMLDivElement | null>(null);

  useEffect(() => {
    if (!infoOpen) return;
    const handleClickOutside = (event: MouseEvent): void => {
      if (
        popoverRef.current &&
        event.target instanceof Node &&
        !popoverRef.current.contains(event.target)
      ) {
        setInfoOpen(false);
      }
    };
    const handleEscape = (event: KeyboardEvent): void => {
      if (event.key === 'Escape') setInfoOpen(false);
    };
    document.addEventListener('mousedown', handleClickOutside);
    document.addEventListener('keydown', handleEscape);
    return () => {
      document.removeEventListener('mousedown', handleClickOutside);
      document.removeEventListener('keydown', handleEscape);
    };
  }, [infoOpen]);

  return (
    <div
      className="relative flex items-center justify-center"
      style={{ width: size, height: size }}
    >
      <svg width={size} height={size} className="-rotate-90">
        <circle
          cx={size / 2}
          cy={size / 2}
          r={radius}
          stroke="#e5e7eb"
          strokeWidth={strokeWidth}
          fill="none"
        />
        <circle
          cx={size / 2}
          cy={size / 2}
          r={radius}
          stroke={theme.stroke}
          strokeWidth={strokeWidth}
          fill="none"
          strokeLinecap="round"
          strokeDasharray={circumference}
          strokeDashoffset={offset}
          style={{ transition: 'stroke-dashoffset 600ms ease-out' }}
        />
      </svg>
      <div className="absolute inset-0 flex flex-col items-center justify-center">
        <div
          className={`text-6xl font-semibold tabular-nums leading-none ${theme.number}`}
        >
          {clampedScore}
        </div>
        <div className={`mt-1 text-xl font-medium leading-none ${theme.grade}`}>
          {grade}
        </div>
        <div className="relative mt-4 inline-flex items-center gap-1.5">
          <span className="text-[10px] font-semibold uppercase tracking-[0.15em] text-gray-500">
            AI Readiness Score
          </span>
          <button
            type="button"
            aria-label="About the AI Readiness Score"
            aria-expanded={infoOpen}
            onClick={() => setInfoOpen(open => !open)}
            className="flex h-4 w-4 cursor-pointer items-center justify-center rounded-full border border-gray-300 text-[9px] font-semibold text-gray-500 hover:border-[#B7007C] hover:text-[#B7007C]"
          >
            i
          </button>
        </div>
        {typeof monthOverMonth === 'number' && monthOverMonth !== 0 && (
          <div
            className={`mt-2 inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[11px] font-medium ${
              monthOverMonth > 0
                ? 'bg-emerald-50 text-emerald-700'
                : 'bg-red-50 text-red-600'
            }`}
          >
            {monthOverMonth > 0 ? '↑' : '↓'} {Math.abs(monthOverMonth)} mo/mo
          </div>
        )}
      </div>
      {infoOpen && (
        <ScoreInfoPopover ref={popoverRef} onClose={() => setInfoOpen(false)} />
      )}
    </div>
  );
}

interface ScoreInfoPopoverProps {
  onClose: () => void;
}

function ScoreInfoPopover({
  ref,
  onClose,
}: ScoreInfoPopoverProps & { ref: React.RefObject<HTMLDivElement | null> }) {
  const composite: Array<{ label: string; weight: number }> = [
    { label: 'AI Visibility', weight: SCORE_WEIGHTS.visibility },
    { label: 'Catalog Quality', weight: SCORE_WEIGHTS.catalog },
    { label: 'Agent Quality', weight: SCORE_WEIGHTS.agent },
  ];

  return (
    <div
      ref={ref as React.RefObject<HTMLDivElement>}
      role="dialog"
      className="absolute left-1/2 top-full z-40 mt-3 w-[320px] -translate-x-1/2 rounded-2xl border border-gray-200 bg-white p-5 shadow-xl"
    >
      <button
        type="button"
        onClick={onClose}
        aria-label="Close"
        className="absolute right-3 top-3 flex h-5 w-5 cursor-pointer items-center justify-center rounded text-gray-500 hover:bg-gray-100 hover:text-gray-900"
      >
        ×
      </button>
      <p className="pr-4 font-mono text-[11px] uppercase tracking-wider leading-relaxed text-gray-900">
        The score AI engines use to decide whether to recommend your store.
      </p>
      <div className="mt-5">
        <p className="text-[10px] font-semibold uppercase tracking-[0.15em] text-gray-500">
          Composite
        </p>
        <ul className="mt-2 space-y-2">
          {composite.map(component => (
            <li
              key={component.label}
              className="flex items-center justify-between font-mono text-xs uppercase tracking-wider"
            >
              <span className="text-gray-900">{component.label}</span>
              <span className="rounded-full bg-gray-100 px-2 py-0.5 tabular-nums text-gray-600">
                {Math.round(component.weight * 100)}%
              </span>
            </li>
          ))}
        </ul>
      </div>
      <div className="mt-5">
        <p className="text-[10px] font-semibold uppercase tracking-[0.15em] text-gray-500">
          Thresholds
        </p>
        <ul className="mt-2 space-y-2">
          {THRESHOLD_BANDS.map(band => (
            <li
              key={band.range}
              className="flex items-center gap-3 font-mono text-[11px] uppercase tracking-wider"
            >
              <span
                className={`inline-flex min-w-[3rem] justify-center rounded-md px-2 py-0.5 tabular-nums ${band.pill}`}
              >
                {band.range}
              </span>
              <span className="text-gray-500">{band.label}</span>
            </li>
          ))}
        </ul>
      </div>
    </div>
  );
}
