// Personal.jsx
import React, { useState, useEffect } from 'react';
import { useNavigate, useLocation, Outlet } from 'react-router-dom';
import { getUserInfo, getDownloadQuota, getDownloadProgress } from '../../api/personal';
import './Personal.css';
import ActionCard from './ActionCard';

const Personal = () => {
  const navigate = useNavigate();
  const location = useLocation();
  const [userData, setUserData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  const [downloadProgress, setDownloadProgress] = useState({});

  useEffect(() => {
    const fetchData = async () => {
      try {
        // 并行获取用户信息和下载额度
        const [userInfo, downloadQuota] = await Promise.all([
          getUserInfo(),
          getDownloadQuota()
        ]);
        
        setUserData({
          username: userInfo.username,
          avatar: 'https://via.placeholder.com/150',
          joinDate: userInfo.registTime,
          level: userInfo.level, // 可以根据userInfo.level设置不同等级
          points: userInfo.magicPoints,
          upload: userInfo.upload,
          download: userInfo.download,
          ratio: userInfo.shareRate,
          downloadQuota: {
            total: downloadQuota.total,
            used: downloadQuota.used,
            remaining: downloadQuota.remaining
          }
        });
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, []);

  // 获取下载进度数据
  const fetchDownloadProgress = async () => {
    try {
      const progressData = await getDownloadProgress();
      setDownloadProgress(progressData);
    } catch (err) {
      console.error('获取下载进度失败:', err);
    }
  };

  useEffect(() => {
    // 初始获取下载进度
    fetchDownloadProgress();
    
    // 设置定时器，每10秒获取一次下载进度
    const intervalId = setInterval(fetchDownloadProgress, 10000);
    
    // 组件卸载时清除定时器
    return () => clearInterval(intervalId);
  }, []);


  if (loading) {
    return <div className="loading">加载中...</div>;
  }

  if (error) {
    return <div className="error">错误: {error}</div>;
  }

  if (!userData) {
    return <div className="error">未获取到用户数据</div>;
  }

  const features = [
    { 
      title: '兑换区', 
      description: '下载量/邀请码',
      path: '/personal/Exchange' // 相对路径
    },
    { 
      title: '上传记录', 
      description: '管理上传的资源',
      path: '/personal/Upload' 
    },
    { 
      title: '消息通知', 
      description: '查看系统消息',
      path: '/personal/Notice' 
    },
    { 
      title: '设置', 
      description: '修改个人资料',
      path: '/personal/Setting' 
    }
  ];

  const handleCardClick = (path) => {
    navigate(path); // 相对导航
  };

  const handleBack = () => {
    if (location.state?.fromSubpage) {
      // 如果是从子页面返回，则继续返回到Dashboard
      navigate(`/dashboard/${location.state.dashboardTab || ''}`, {
        replace: true
      });
    } else {
      // 普通返回逻辑
      navigate(-1);
    }
  };

  const formatSize = (bytes) => {
    if (bytes < 1024) return `${bytes} B`;
    const kb = bytes / 1024;
    if (kb < 1024) return `${kb.toFixed(2)} KB`;
    const mb = kb / 1024;
    if (mb < 1024) return `${mb.toFixed(2)} MB`;
    const gb = mb / 1024;
    return `${gb.toFixed(2)} GB`;
  };

  // 添加进度条颜色函数
  const getProgressColor = (percentage) => {
    if (percentage < 0.3) return '#4CAF50'; // 绿色
    if (percentage < 0.7) return '#FFC107'; // 黄色
    return '#F44336'; // 红色
  };

  return (
    <div className="personal-container">
      {/* 返回按钮 */}
      <button className="back-button" onClick={handleBack}>
      返回
      </button>
      
      {/* 用户基本信息卡片 */}
      <div className="profile-card">
        <div className="profile-header">
          <img 
            src={userData.avatar} 
            alt={userData.username} 
            className="profile-avatar"
          />
          <div className="profile-info">
            <h2 className="username">{userData.username}</h2>
            <div className="user-meta">
              <span>加入时间: {userData.joinDate}</span>
              <span>会员等级: Lv.{userData.level}</span> 
            </div>
          </div>
        </div>
        
        {/* 用户数据统计 */}
        <div className="stats-grid">
          <div className="stat-item">
            <div className="stat-label">保种积分</div>
            <div className="stat-value">{userData.points}</div>
          </div>
          <div className="stat-item">
            <div className="stat-label">上传量</div>
            <div className="stat-value">{formatSize(userData.upload)}</div>
          </div>
          <div className="stat-item">
            <div className="stat-label">下载量</div>
            <div className="stat-value">{formatSize(userData.download)}</div>
          </div>
          <div className="stat-item">
            <div className="stat-label">分享率</div>
            <div className="stat-value">{userData.ratio}</div>
          </div>
        </div>
      </div>
      
      {/* 下载额度卡片 */}
      <div className="quota-card">
        <h3>下载额度</h3>
        <div className="quota-info">
          <span className="quota-used">
            {formatSize(userData.downloadQuota.used)} 已使用
          </span>
          <span className="quota-remaining">
            {formatSize(userData.downloadQuota.remaining)} 剩余
          </span>
        </div>
        <div className="progress-bar">
          <div 
            className="progress-fill"
            style={{ 
              width: `${(userData.downloadQuota.used / userData.downloadQuota.total) * 100}%`,
              backgroundColor: getProgressColor(userData.downloadQuota.used / userData.downloadQuota.total)
            }}
          ></div>
        </div>
        <div className="quota-total">
          总额度: {formatSize(userData.downloadQuota.total)}
        </div>
      </div>

      {Object.keys(downloadProgress).length > 0 && (
        <div className="progress-card">
          <h3>当前下载进度</h3>
          {Object.entries(downloadProgress).map(([taskId, progress]) => (
            <div key={taskId} className="download-task">
              <div className="task-info">
                <span className="task-id">任务: {taskId.substring(0, 8)}...</span>
                <span className="task-progress">{Math.round(progress * 100)}%</span>
              </div>
              <div className="progress-bar">
                <div 
                  className="progress-fill"
                  style={{ width: `${progress * 100}%` }}
                ></div>
              </div>
            </div>
          ))}
        </div>
      )}
      
      {/* 功能卡片区 */}
      <div className="action-cards">
        {features.map((feature) => (
          <div 
            key={feature.path}
            className="action-card"
            onClick={() => handleCardClick(feature.path)}
          >
            <h3>{feature.title}</h3>
            <p>{feature.description}</p>
          </div>
        ))}
      </div>

      {/* 子路由出口 */}
      <div className="subpage-container">
        <Outlet />
      </div>
    </div>
  );
};

export default Personal;