import React, { useState } from 'react';
import PropTypes from 'prop-types';
import useSessionStats from '../../hooks/useSessionStats';
import StatsInfo from './StatsInfo';
import './TrackDiagnostics.css';
import closeIcon from '../../assets/img/client/close.svg';

const TrackDiagnostics = ({
  connStatsClientId,
  isVisible,
  participant,
  onMouseEnter,
  onMouseLeave,
  myTrack = false,
  onClose
}) => {
  TrackDiagnostics.propTypes = {
    connStatsClientId: PropTypes.string,
    isVisible: PropTypes.bool,
    participant: PropTypes.shape({
      user: PropTypes.shape({
        name: PropTypes.string,
        possessive: PropTypes.string
      })
    }),
    onMouseEnter: PropTypes.func,
    onMouseLeave: PropTypes.func,
    myTrack: PropTypes.bool,
    onClose: PropTypes.func
  };
  const { stats, loading, error } = useSessionStats(connStatsClientId);
  const [hoverType, setHoverType] = useState(null);
  const [hoverField, setHoverField] = useState(null);

  if (!isVisible) return null;
  if (loading)
    return (
      <div className="track-diagnostics">
        <div className="diagnostics-content">Loading...</div>
      </div>
    );
  if (error)
    return (
      <div className="track-diagnostics">
        <div className="diagnostics-content">Error loading stats</div>
      </div>
    );
  if (!stats) return null;

  const handleHover = (type, field) => {
    setHoverType(type);
    setHoverField(field);
  };

  const handleHoverOut = () => {
    setHoverType(null);
    setHoverField(null);
  };

  const renderStat = (properties, type, name, field, value) => {
    const classes = ['status-icon'];
    const classifier = properties[field + '_level'];
    if (classifier) {
      classes.push(classifier);
    }

    return (
      <div
        className="stat"
        onMouseEnter={() => handleHover(type, field)}
        onMouseLeave={handleHoverOut}
        key={`${type}-${field}`}
      >
        <span className="title">- {name}</span>
        <div className={classes.join(' ')} />
        <span className="stat-value">{value}</span>
      </div>
    );
  };

  // Get extra info for hovered stat
  const getExtraInfo = () => {
    if (!hoverType || !hoverField) {
      return 'Hover over a stat to learn more.';
    }

    const type = hoverType;
    const field = hoverField;

    const classifier = stats[type]?.[field + '_level'];

    if (classifier && StatsInfo[type]?.[field]?.[classifier]) {
      const info = StatsInfo[type][field][classifier](
        participant?.user || { name: 'User', possessive: 'Their' },
        stats
      );
      return <span dangerouslySetInnerHTML={{ __html: info }} />;
    }

    return <span>No extra info for this metric.</span>;
  };

  // Build stats sections with conditional logic matching web project
  const computerStats = [];
  const networkStats = [];
  const audioStats = [];
  const aggregateStats = [];

  const aggregate = stats.aggregate;
  const network = stats.network;
  const system = stats.system;
  const audio = stats.audio;

  // Aggregate stats (only if aggregate data exists AND not my track)
  if (aggregate && !myTrack) {
    if (aggregate.latency) {
      aggregateStats.push(renderStat(aggregate, 'aggregate', 'Tot Latency', 'latency', Math.round(aggregate.latency)));
    }
  }

  // System stats (always show if system data exists)
  if (system) {
    if (system.cpu) {
      computerStats.push(renderStat(system, 'system', 'Processor', 'cpu', Math.round(system.cpu) + ' %'));
    }
  }

  // Audio stats (always show if audio data exists, check individual fields)
  if (audio) {
    if (audio.latency) {
      audioStats.push(renderStat(audio, 'audio', 'Latency', 'latency', audio.latency.toFixed(1) + ' ms'));
    }
    if (audio.input_jitter) {
      audioStats.push(
        renderStat(audio, 'audio', 'Input Jitter', 'input_jitter', audio.input_jitter.toFixed(2) + ' ms')
      );
    }
    if (audio.output_jitter) {
      audioStats.push(
        renderStat(audio, 'audio', 'Output Jitter', 'output_jitter', audio.output_jitter.toFixed(2) + ' ms')
      );
    }

    if (audio.audio_in_type) {
      let audioType = '?';
      const audioLong = audio.audio_in_type.toLowerCase();
      if (audioLong.indexOf('asio') > -1) audioType = 'ASIO';
      else if (audioLong.indexOf('wdm') > -1) audioType = 'WDM';
      else if (audioLong.indexOf('core') > -1) audioType = 'CoreAudio';
      else if (audioLong.indexOf('alsa') > -1) audioType = 'JamBlaster';

      audioStats.push(renderStat(audio, 'audio', 'Gear Driver', 'audio_in_type', audioType));
    }

    if (audio.framesize) {
      const framesize = audio.framesize + ' ms';
      audioStats.push(renderStat(audio, 'audio', 'Frame Size', 'framesize', framesize));
    }
  }

  // Network stats (only if network data exists AND not my track)
  if (network && !myTrack) {
    if (network.ping) {
      networkStats.push(renderStat(network, 'network', 'Latency', 'ping', (network.ping / 2).toFixed(1) + ' ms'));
    }
    if (network.audiojq_median) {
      networkStats.push(
        renderStat(network, 'network', 'Jitter Queue', 'audiojq_median', network.audiojq_median.toFixed(1))
      );
    }
    if (network.jitter_var) {
      networkStats.push(renderStat(network, 'network', 'Jitter', 'jitter_var', network.jitter_var.toFixed(1) + ' ms'));
    }
    if (network.pkt_loss) {
      networkStats.push(renderStat(network, 'network', 'Packet Loss', 'pkt_loss', network.pkt_loss.toFixed(1) + ' %'));
    }
    if (network.wifi !== undefined) {
      const value = network.wifi ? 'Wi-Fi' : 'Wired';
      networkStats.push(renderStat(network, 'network', 'Connectivity', 'wifi', value));
    }
    if (network.audio_bitrate_rx) {
      networkStats.push(
        renderStat(
          network,
          'network',
          'Audio Bw Rx',
          'audio_bitrate_rx',
          Math.round(network.audio_bitrate_rx / 1000) + ' k'
        )
      );
    }
    if (network.audio_bitrate_tx) {
      networkStats.push(
        renderStat(
          network,
          'network',
          'Audio Bw Tx',
          'audio_bitrate_tx',
          Math.round(network.audio_bitrate_tx / 1000) + ' k'
        )
      );
    }
    if (network.video_rtpbw_rx) {
      networkStats.push(
        renderStat(
          network,
          'network',
          'Video Bw Rx',
          'video_rtpbw_rx',
          Math.round(network.video_rtpbw_rx / 1000) + ' k'
        )
      );
    }
    if (network.video_rtpbw_tx) {
      networkStats.push(
        renderStat(
          network,
          'network',
          'Video Bw Tx',
          'video_rtpbw_tx',
          Math.round(network.video_rtpbw_tx / 1000) + ' k'
        )
      );
    }
    if (network.rx_ars_vs_p2p) {
      networkStats.push(renderStat(network, 'network', 'RX Net Path', 'rx_ars_vs_p2p', network.rx_ars_vs_p2p));
    }
    if (network.tx_ars_vs_p2p) {
      networkStats.push(renderStat(network, 'network', 'TX Net Path', 'tx_ars_vs_p2p', network.tx_ars_vs_p2p));
    }
  }

  return (
    <div className="track-diagnostics" onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave}>
      <button className="close-button" onClick={onClose}>
        <img src={closeIcon} alt="Close" />
      </button>
      <h3>Diagnostics: {participant?.user?.name || 'Participant'}</h3>

      <div className="diagnostics-content">
        <div className="stats-area">
          {aggregateStats.length > 0 && <div className="aggregate-stats stats-holder">{aggregateStats}</div>}

          {computerStats.length > 0 && (
            <div className="computer-stats stats-holder">
              <h3>Computer</h3>
              {computerStats}
            </div>
          )}

          {audioStats.length > 0 && (
            <div className="audio-stats stats-holder">
              <h3>Audio Interface</h3>
              {audioStats}
            </div>
          )}

          {networkStats.length > 0 && (
            <div className="network-stats stats-holder">
              <h3>Internet</h3>
              {networkStats}
            </div>
          )}
        </div>

        <div className="stats-info">{getExtraInfo()}</div>
      </div>
    </div>
  );
};

export default TrackDiagnostics;
