// export default NewbieTasks;
import React, { useEffect, useState } from 'react';
import axios from 'axios';

const NewbieTasks = () => {
  const [tasks, setTasks] = useState([]);
  const [experience, setExperience] = useState({});
  const [currentStep, setCurrentStep] = useState({});
  const [loading, setLoading] = useState(true);

  const baseURL = '/echo/task/tutorial';
  const userId = 1;

  const fetchTasks = async () => {
    try {
      const response = await axios.get(`${baseURL}/getAllTasks`, {
        params: { user_id: userId },
      });
      setTasks(response.data.tasks || []);
    } catch (error) {
      console.error('获取任务失败:', error);
    }
  };

  const fetchExperience = async () => {
    try {
      const response = await axios.get(`${baseURL}/getAllTasks`, {
        params: { user_id: userId },
      });
      setExperience(response.data || {});
    } catch (error) {
      console.error('获取经验失败:', error);
    }
  };

  const fetchCurrentStep = async () => {
    try {
      const response = await axios.get(`${baseURL}/getNewStep`, {
        params: { user_id: userId },
      });
      setCurrentStep(response.data || {});
    } catch (error) {
      console.error('获取引导步骤失败:', error);
    }
  };

  const updateStatus = async (taskId) => {
    try {
      await axios.post(`${baseURL}/updateStatus`, {
        user_id: userId,
        task_id: taskId,
      });
      await fetchTasks();
      await fetchExperience();
    } catch (error) {
      console.error('更新状态失败:', error);
    }
  };

  const updateProgress = async (taskId, progress) => {
    try {
      await axios.post(`${baseURL}/updateProgress`, {
        user_id: userId,
        task_id: taskId,
        progress,
      });
      await fetchTasks();
    } catch (error) {
      console.error('更新进度失败:', error);
    }
  };

  const claimReward = async (taskId) => {
    try {
      await axios.post(`${baseURL}/rewardClaim`, {
        user_id: userId,
        task_id: taskId,
      });
      await fetchTasks();
      await fetchExperience();
    } catch (error) {
      console.error('领取奖励失败:', error);
    }
  };

  const checkRewardStatus = async (taskId) => {
    try {
      const response = await axios.post(`${baseURL}/rewardReview`, {
        user_id: userId,
        task_id: taskId,
      });
      alert(response.data.message || '已完成');
    } catch (error) {
      console.error('查看失败:', error);
    }
  };

  useEffect(() => {
    const init = async () => {
      await fetchTasks();
      await fetchExperience();
      await fetchCurrentStep();
      setLoading(false);
    };
    init();
  }, []);

  if (loading) return <p className="loading">加载中...</p>;

  return (
    <div className="common-card right-content">
      <div className="profile-header">
        <h1>🎯 成长任务</h1>
      </div>

      <div className="profile-details">
        <p><strong>当前经验：</strong>{experience.current_experience}</p>
        <p><strong>等级：</strong>{experience.level}</p>
        <p><strong>奖励经验：</strong>{experience.reward?.experience || 0}</p>
        <p><strong>奖励积分：</strong>{experience.reward?.points || 0}</p>
      </div>

      <div className="profile-details">
        <p><strong>🧭 当前引导步骤：</strong>{currentStep.current_step}</p>
        <p>{currentStep.step_description}</p>
      </div>

      <div className="profile-details">
        <h2>任务列表</h2>
        <ul>
          {tasks.map(task => (
            <li key={task.task_id} style={{ marginBottom: '20px', borderBottom: '1px solid #eee', paddingBottom: '10px' }}>
              <p><strong>任务：</strong>{task.title}</p>
              <p><strong>描述：</strong>{task.description}</p>
              <p><strong>进度：</strong>{task.progress}%</p>
              <p><strong>状态：</strong>{task.status}</p>
              <p><strong>奖励：</strong>经验 {task.reward.experience}，积分 {task.reward.points}</p>

              <div className="task-btn-group">
                <button className="task-btn" onClick={() => updateStatus(task.task_id)}>更新状态</button>
                <button className="task-btn" onClick={() => updateProgress(task.task_id, 100)}>提交进度</button>
                <button className="task-btn" onClick={() => claimReward(task.task_id)}>领取奖励</button>
                <button className="task-btn" onClick={() => checkRewardStatus(task.task_id)}>查看奖励状态</button>
              </div>
            </li>
          ))}
        </ul>
      </div>
    </div>
  );
};

export default NewbieTasks;

