# farm.py
import time
import random
import logging
from copy import deepcopy
from combat import generate_uuid
from notification import send_private

logger = logging.getLogger(__name__)

class FarmSystem:
    def __init__(self, game_engine=None, max_plots=6):
        self.game_engine = game_engine
        self.max_plots = max_plots
        self._cached_stages = None   # 缓存阶段模板

    def set_game_engine(self, game_engine):
        self.game_engine = game_engine
        self._cached_stages = None   # 重置缓存

    def _ensure_farm_data(self, state):
        if 'farm' not in state:
            state['farm'] = {
                'plots': [None] * self.max_plots,
                'unlocked_plots': self.max_plots
            }
        if len(state['farm']['plots']) != self.max_plots:
            state['farm']['plots'] = (state['farm']['plots'] + [None] * self.max_plots)[:self.max_plots]
        return state

    def _ensure_seed_storage(self, state):
        if 'seed_storage' not in state:
            state['seed_storage'] = []
        return state

    def _get_crop_by_id(self, crop_id):
        if not self.game_engine:
            return None
        crops = self.game_engine.config.get('crops', [])
        for crop in crops:
            if crop.get('id') == crop_id:
                return crop
        return None

    def _get_seed_config_by_crop_id(self, crop_id):
        if not self.game_engine:
            return None
        seeds = self.game_engine.config.get('seeds', [])
        for seed in seeds:
            if seed.get('crop_id') == crop_id:
                return seed
        return None

    def _get_global_stages(self):
        """获取阶段模板（带缓存）"""
        if self._cached_stages is not None:
            return self._cached_stages

        stages = []
        if self.game_engine:
            stages = self.game_engine.config.get('farm_stages', [])
        if not stages:
            # 降级：提供一个合理的默认阶段（不要直接成熟）
            stages = [
                {'name': '播种', 'required_actions': [], 'action_interval': 0, 'duration_ratio': 0.2},
                {'name': '生长', 'required_actions': ['water'], 'action_interval': 600, 'duration_ratio': 0.4},
                {'name': '成熟', 'required_actions': [], 'action_interval': 0, 'duration_ratio': 0.4}
            ]
        # 归一化 duration_ratio
        total_ratio = sum(s.get('duration_ratio', 0) for s in stages)
        if total_ratio <= 0:
            stages[0]['duration_ratio'] = 1.0
        else:
            for s in stages:
                s['duration_ratio'] = s.get('duration_ratio', 0) / total_ratio
        self._cached_stages = stages
        return stages

    def _build_dynamic_stages(self, total_growth_seconds):
        template = self._get_global_stages()
        # 分离成熟阶段和非成熟阶段
        non_mature = [t for t in template if t.get('name') != '成熟']
        mature = [t for t in template if t.get('name') == '成熟']

        if not non_mature:
            # 保底：只要一个成熟阶段
            return [{'name': '成熟', 'duration': 0, 'required_actions': [], 'action_interval': 0}]

        # 归一化非成熟阶段的比例
        total_ratio = sum(t.get('duration_ratio', 0) for t in non_mature)
        if total_ratio <= 0:
            # 平均分配
            per = 1.0 / len(non_mature)
            for t in non_mature:
                t['duration_ratio'] = per
            total_ratio = 1.0

        stages = []
        # 为每个非成熟阶段计算时长（整数秒），保证至少1秒
        for t in non_mature:
            dur = total_growth_seconds * (t.get('duration_ratio', 0) / total_ratio)
            if dur < 1:
                dur = 1
            dur_int = int(dur)
            stages.append({
                'name': t['name'],
                'duration': dur_int,
                'required_actions': t.get('required_actions', []),
                'action_interval': t.get('action_interval', 0)
            })

        # 调整总时长精确匹配 total_growth_seconds（因为取整带来的误差）
        total_assigned = sum(s['duration'] for s in stages)
        diff = total_growth_seconds - total_assigned
        idx = 0
        while diff != 0 and idx < len(stages):
            if diff > 0:
                stages[idx]['duration'] += 1
                diff -= 1
            else:
                # 极少出现的负误差，从前面阶段扣除，但不低于1秒
                if stages[idx]['duration'] > 1:
                    stages[idx]['duration'] -= 1
                    diff += 1
            idx += 1

        # 添加成熟阶段（duration=0）
        if mature:
            stages.append({
                'name': '成熟',
                'duration': 0,
                'required_actions': mature[0].get('required_actions', []),
                'action_interval': mature[0].get('action_interval', 0)
            })
        else:
            stages.append({'name': '成熟', 'duration': 0, 'required_actions': [], 'action_interval': 0})

        return stages

    def _send_maintenance_reminder(self, player_name, crop, stage):
        required = stage.get('required_actions', [])
        if not required:
            return
        actions_name = {'water': '浇水', 'weed': '除草', 'spray': '打药'}
        action_text = '、'.join([actions_name.get(a, a) for a in required])
        msg = f'🌾【农场提醒】你的{crop["name"]}已进入【{stage["name"]}】阶段，需要尽快进行：{action_text}，否则生长会停滞并影响收成！'
        send_private(player_name, msg)

    def _send_private_message(self, player_name, msg):
        send_private(player_name, msg)

    def _calculate_growth_speed(self, plot, crop, now):
        stages = plot.get('_stages', [])
        stage_idx = plot.get('stage_index', 0)
        if stage_idx >= len(stages):
            return 1.0
        current_stage = stages[stage_idx]
        required_actions = current_stage.get('required_actions', [])
        action_interval = current_stage.get('action_interval', 0)
        if not required_actions or action_interval <= 0:
            return 1.0

        maintenance_config = self.game_engine.config.get('maintenance', {})
        stagnation_penalty = maintenance_config.get('stagnation_penalty', 0.5)
        decay_per_miss = maintenance_config.get('decay_per_miss', 0.2)

        all_valid = True
        for act in required_actions:
            last_time = plot.get('last_action_times', {}).get(act, 0)
            if now - last_time > action_interval:
                all_valid = False
                miss_flag = f'missed_{act}_flag'
                if not plot.get(miss_flag, False):
                    plot[miss_flag] = True
                    plot['missed_actions'] = plot.get('missed_actions', 0) + 1
                    plot['health'] = max(0, plot.get('health', 100) - decay_per_miss * 100)
                    plot['stage_maintenance_failed'] = True
                    player_name = plot.get('_player_name')
                    if player_name:
                        actions_name = {'water': '浇水', 'weed': '除草', 'spray': '打药'}
                        self._send_private_message(player_name, f'⚠️ 你的{crop["name"]}错过了{actions_name.get(act, act)}，生长速度下降，健康度降低！本次收成将无法产生变异果实。')
        return 1.0 if all_valid else stagnation_penalty

    def _update_plot_growth(self, state, plot_idx):
        plot = state['farm']['plots'][plot_idx]
        if plot is None:
            return
        crop = self._get_crop_by_id(plot['crop_id'])
        if not crop:
            return

        # 如果阶段数据无效，尝试重建
        if '_stages' not in plot or not plot['_stages']:
            total_growth = plot.get('total_growth_time', 3600)
            stages = self._build_dynamic_stages(total_growth)
            plot['_stages'] = stages
            plot['stage_index'] = 0
            plot['stage_start_time'] = time.time()
            plot['health'] = 100
            plot['missed_actions'] = 0
            plot['last_action_times'] = {}
            return

        stages = plot['_stages']
        now = time.time()
        speed = self._calculate_growth_speed(plot, crop, now)
        plot['growth_speed_multiplier'] = speed

        stage_idx = plot.get('stage_index', 0)
        stage_start = plot.get('stage_start_time', now)

        elapsed_real = now - stage_start
        effective_elapsed = elapsed_real * speed

        # 推进阶段
        while stage_idx < len(stages) - 1:   # 最后一个阶段（成熟）不推进
            stage_duration = stages[stage_idx].get('duration', 0)
            if stage_duration <= 0:
                stage_idx += 1
                continue
            if effective_elapsed >= stage_duration:
                effective_elapsed -= stage_duration
                stage_idx += 1
                plot['stage_index'] = stage_idx
                plot['stage_start_time'] = now
                plot['stage_maintenance_failed'] = False
                # 进入新阶段，发送提醒
                player_name = state['player']['name']
                self._send_maintenance_reminder(player_name, crop, stages[stage_idx])
            else:
                break

        # 计算剩余总时间（用于兼容前端）
        total_remaining = 0
        for i in range(stage_idx, len(stages)):
            total_remaining += stages[i].get('duration', 0)
        if speed > 0:
            plot['harvest_time'] = now + (total_remaining - effective_elapsed) / speed
        else:
            plot['harvest_time'] = float('inf')

        now = time.time()
        last_event = plot.get('last_event_time', 0)
        if now - last_event > 1200:
            self._trigger_random_event(plot, crop, state)
            plot['last_event_time'] = now

    def _get_current_stage_info(self, plot):
        stages = plot.get('_stages', [])
        stage_idx = plot.get('stage_index', 0)
        if not stages or stage_idx >= len(stages):
            return '未知', 0, False
        stage = stages[stage_idx]
        stage_name = stage.get('name', '未知阶段')
        now = time.time()
        speed = plot.get('growth_speed_multiplier', 1.0)
        stage_start = plot.get('stage_start_time', now)
        elapsed = (now - stage_start) * speed
        remaining = max(0, stage.get('duration', 0) - elapsed)
        ready = (stage.get('duration', 0) == 0) or (stage_idx == len(stages)-1 and remaining <= 0)
        return stage_name, int(remaining), ready

    def maintain(self, state, plot_index, action_type):
        state = self._ensure_farm_data(state)
        if plot_index < 0 or plot_index >= self.max_plots:
            return state, '无效的地块索引'
        plot = state['farm']['plots'][plot_index]
        if plot is None:
            return state, '该地块没有作物'
        crop = self._get_crop_by_id(plot['crop_id'])
        if not crop:
            return state, '作物配置错误'
        stages = plot.get('_stages')
        if not stages:
            return state, '作物阶段数据异常'
        stage_idx = plot.get('stage_index', 0)
        if stage_idx >= len(stages):
            return state, '作物已成熟，无需维护'
        current_stage = stages[stage_idx]
        required_actions = current_stage.get('required_actions', [])
        action_interval = current_stage.get('action_interval', 0)

        if action_type not in required_actions:
            return state, f'当前阶段不需要{action_type}操作'

        # ---------- 工具检查 ----------
        tool_map = {'water': 'watering_can', 'weed': 'hoe', 'spray': 'sprayer'}
        required_tool = tool_map.get(action_type)
        if required_tool:
            storage = state.get('seed_storage', [])
            tool_item = None
            for idx, it in enumerate(storage):
                if it.get('type') == 'tool' and it.get('id') == required_tool and it.get('quantity', 0) > 0:
                    tool_item = it
                    break
            if not tool_item:
                return state, f'没有{required_tool}，请先去商店购买'
        # ---------------------------------

        now = time.time()
        last_time = plot.get('last_action_times', {}).get(action_type, 0)
        # 如果本次操作在间隔内已经完成过，则只提示，不消耗工具、不加健康度
        if last_time > 0 and (now - last_time) < action_interval:
            actions_name = {'water': '浇水', 'weed': '除草', 'spray': '打药'}
            return state, f'{actions_name.get(action_type, action_type)}已经完成，无需重复操作'

        # 扣除工具
        if required_tool:
            if tool_item.get('quantity', 0) > 1:
                tool_item['quantity'] -= 1
            else:
                storage.pop(storage.index(tool_item))

        # 记录操作时间
        if 'last_action_times' not in plot:
            plot['last_action_times'] = {}
        plot['last_action_times'][action_type] = now
        plot.pop(f'missed_{action_type}_flag', None)

        # 增加健康度
        maintenance_config = self.game_engine.config.get('maintenance', {})
        health_increase = maintenance_config.get('health_increase_per_action', 5)
        plot['health'] = min(100, plot.get('health', 100) + health_increase)

        player_name = state['player']['name']

        # 检查是否所有当前阶段要求的动作都已按时完成
        if required_actions and action_interval > 0:
            all_done = True
            for act in required_actions:
                last = plot.get('last_action_times', {}).get(act, 0)
                if now - last > action_interval:
                    all_done = False
                    break
            if all_done:
                plot['stage_maintenance_failed'] = False
                self._send_private_message(player_name, f'🎉 所有维护操作已完成，{crop["name"]}恢复健康，变异几率恢复正常！')

        actions_name = {'water': '浇水', 'weed': '除草', 'spray': '打药'}
        self._send_private_message(player_name, f'✅ 你对{crop["name"]}进行了{actions_name.get(action_type, action_type)}，作物状态良好！')
        return state, f'已对{crop["name"]}完成{action_type}操作'

    def _trigger_random_event(self, plot, crop, state):
        event_chance = 0.05
        if random.random() > event_chance:
            return
        events = [
            {'name': '虫灾', 'health_loss': 15, 'msg': '🐛 虫灾来袭，作物健康度下降15！'},
            {'name': '干旱', 'health_loss': 10, 'msg': '☀️ 干旱导致作物健康度下降10！'},
            {'name': '野兔', 'health_loss': 5, 'msg': '🐇 野兔偷吃，作物健康度下降5！'},
            {'name': '肥沃', 'health_gain': 10, 'msg': '🌱 土地变得肥沃，作物健康度+10！'},
            {'name': '及时雨', 'health_gain': 15, 'msg': '🌧️ 一场及时雨，作物健康度+15！'}
        ]
        event = random.choice(events)
        if 'health_loss' in event:
            plot['health'] = max(0, plot.get('health', 100) - event['health_loss'])
        elif 'health_gain' in event:
            plot['health'] = min(100, plot.get('health', 100) + event['health_gain'])
        player_name = state['player']['name']
        self._send_private_message(player_name, event['msg'])

    def get_farm_state(self, state):
        state = self._ensure_farm_data(state)
        plots = []
        for idx, plot in enumerate(state['farm']['plots']):
            if plot is None:
                plots.append({'index': idx, 'is_empty': True, 'remaining': 0, 'ready': False})
                continue

            crop = self._get_crop_by_id(plot['crop_id'])
            if not crop:
                plots.append({'index': idx, 'is_empty': False, 'crop_name': '错误作物', 'remaining': 0, 'ready': False, 'error': True})
                continue

            self._update_plot_growth(state, idx)
            stage_name, stage_remaining, ready = self._get_current_stage_info(plot)
            harvest_time = plot.get('harvest_time', 0)
            now = time.time()
            total_remaining = max(0, int(harvest_time - now)) if harvest_time != float('inf') else 0

            stages = plot.get('_stages', [])
            stage_idx = plot.get('stage_index', 0)
            if stage_idx < len(stages):
                current_stage = stages[stage_idx]
                required_actions_raw = current_stage.get('required_actions', [])
                action_interval = current_stage.get('action_interval', 0)
                now = time.time()
                required_actions = []
                for act in required_actions_raw:
                    last_time = plot.get('last_action_times', {}).get(act, 0)
                    if now - last_time > action_interval:
                        required_actions.append(act)
            else:
                required_actions = []

            plots.append({
                'index': idx,
                'is_empty': False,
                'crop_id': plot['crop_id'],
                'crop_name': crop.get('name', '未知作物'),
                'crop_icon': crop.get('icon', '🌱'),
                'stage_name': stage_name,
                'stage_remaining': stage_remaining,
                'remaining': total_remaining,
                'ready': ready,
                'health': plot.get('health', 100),
                'growth_speed': plot.get('growth_speed_multiplier', 1.0),
                'mutate_possible': True,
                'required_actions': required_actions
            })
        return plots

    def plant(self, state, plot_index, seed_uuid):
        state = self._ensure_farm_data(state)
        state = self._ensure_seed_storage(state)

        if plot_index < 0 or plot_index >= self.max_plots:
            return state, '无效的地块索引'
        if state['farm']['plots'][plot_index] is not None:
            return state, '该地块已有作物'

        # 查找种子
        storage = state['seed_storage']
        seed_idx = None
        seed_item = None
        for i, s in enumerate(storage):
            if s.get('uuid') == seed_uuid:
                seed_item = s
                seed_idx = i
                break
        if not seed_item:
            return state, '种子仓库中没有该种子'

        crop_id = seed_item.get('crop_id')
        if not crop_id:
            return state, '无效的种子（缺少作物ID）'

        crop = self._get_crop_by_id(crop_id)
        if not crop:
            return state, f'作物配置不存在 (ID: {crop_id})'

        # 关键修复：重新从种子配置获取生长时间（避免物品中丢失）
        seed_cfg = self._get_seed_config_by_crop_id(crop_id)
        if not seed_cfg:
            return state, '种子配置丢失，请重新购买'
        total_growth = seed_cfg.get('growthTime', crop.get('growthTime', 3600))
        if total_growth <= 0:
            total_growth = 3600

        # 扣除种子
        qty = seed_item.get('quantity', 1)
        if qty < 1:
            return state, '种子数量不足'
        if qty == 1:
            storage.pop(seed_idx)
        else:
            seed_item['quantity'] = qty - 1

        # 生成动态阶段
        stages = self._build_dynamic_stages(total_growth)
        if not stages:
            return state, '阶段配置错误，无法种植'

        now = time.time()
        plot_data = {
            'crop_id': crop_id,
            'plant_time': now,
            '_stages': stages,
            'stage_index': 0,
            'stage_start_time': now,
            'last_action_times': {},
            'health': 100,
            'missed_actions': 0,
            'growth_speed_multiplier': 1.0,
            '_player_name': state['player']['name'],
            'stage_maintenance_failed': False,
            'total_growth_time': total_growth   # 保留原始总时长，以便重建
        }
        # 发送第一个阶段的提醒
        if stages and len(stages) > 0:
            self._send_maintenance_reminder(state['player']['name'], crop, stages[0])

        state['farm']['plots'][plot_index] = plot_data
        return state, f'成功种植{crop["name"]}，请留意农场消息及时维护'

    def _get_normal_fruit(self, crop):
        return {
            'id': int(crop.get('fruit_id', crop.get('id', 0) + 1000)),   # 强制整数
            'name': crop.get('fruit_name', f'{crop["name"]}果实'),
            'type': 'fruit',
            'icon': crop.get('icon', '🍎'),
            'buff': {
                'type': crop.get('effectType', 'expMultiplier'),
                'value': crop.get('effectValue', 2),
                'duration': crop.get('duration', 1800),
                'target': 'both'
            },
            'price': crop.get('price', 1000),
            'description': crop.get('description', ''),
            'maxStack': 9999,        # 允许大量堆叠
            'is_mutated': False
        }

    def _generate_mutated_fruit(self, crop, plot, health_factor):
        base_effect_type = crop.get('effectType', 'expMultiplier')
        base_effect_value = crop.get('effectValue', 2)
        base_duration = crop.get('duration', 1800)
    
        multiplier = random.uniform(1.5, 3.0)
        multiplier *= (0.8 + health_factor * 0.4)
        missed = plot.get('missed_actions', 0)
        multiplier *= max(0.5, 1.0 - missed * 0.05)
        multiplier = round(multiplier, 1)
    
        mutated_value = int(base_effect_value * multiplier) if isinstance(base_effect_value, int) else base_effect_value * multiplier
        mutated_duration = int(base_duration * multiplier)
    
        fruit_name = f'变异{crop.get("fruit_name", crop["name"]+"果实")}'
        fruit_id = crop.get('id', 0) + 1100   # 固定偏移，变异果实可叠加
    
        fruit = {
            'id': fruit_id,
            'name': fruit_name,
            'type': 'fruit',
            'icon': '✨' + crop.get('icon', '🍎'),
            'buff': {
                'type': base_effect_type,
                'value': mutated_value,
                'duration': mutated_duration,
                'target': 'both'
            },
            'price': int(crop.get('price', 1000) * multiplier),
            'description': f'变异果实，{base_effect_type}效果提升{multiplier}倍',
            'maxStack': 9999,      # 变异果实也可叠加（若需限制可改为1）
            'is_mutated': True,
            'mutate_multiplier': multiplier
        }
        if random.random() < 0.3:
            extra_gold = random.randint(5000, 20000)
            fruit['extra_gold'] = extra_gold
            fruit['description'] += f'，使用时额外获得{extra_gold}金币'
        return fruit

    def harvest(self, state, plot_index):
        state = self._ensure_farm_data(state)
        if plot_index < 0 or plot_index >= self.max_plots:
            return state, '无效的地块索引'

        plot = state['farm']['plots'][plot_index]
        if plot is None:
            return state, '该地块没有作物'

        crop = self._get_crop_by_id(plot['crop_id'])
        if not crop:
            state['farm']['plots'][plot_index] = None
            return state, '作物配置错误，已清除'

        self._update_plot_growth(state, plot_index)
        _, _, ready = self._get_current_stage_info(plot)
        if not ready:
            remaining = max(0, int(plot.get('harvest_time', 0) - time.time()))
            return state, f'作物尚未成熟，还需{remaining}秒'

        # 变异概率
        if plot.get('stage_maintenance_failed', False):
            mutate_rate = 0.0
        else:
            base_mutate_rate = crop.get('mutate_base_rate', 0.05)
            dynamic_factors = crop.get('mutate_dynamic_factors', {})
            health = plot.get('health', 100) / 100.0
            score_bonus = dynamic_factors.get('maintenance_score', 0.02) * health
            missed_penalty = min(0.3, plot.get('missed_actions', 0) * 0.02)
            mutate_rate = base_mutate_rate + score_bonus - missed_penalty
            mutate_rate = max(0, min(1, mutate_rate))
        is_mutated = random.random() < mutate_rate

        # 产量
        min_yield = crop.get('minYield', 1)
        max_yield = crop.get('maxYield', 3)
        base_quantity = random.randint(min_yield, max_yield)
        health_factor = plot.get('health', 100) / 100.0
        quantity = max(1, int(base_quantity * (0.5 + health_factor * 0.5)))

        if is_mutated:
            fruit = self._generate_mutated_fruit(crop, plot, health_factor)
            msg = f'🎉 收获变异果实✨ {fruit["name"]} x{quantity}，属性大幅提升！'
        else:
            fruit = self._get_normal_fruit(crop)
            msg = f'收获 {fruit["name"]} x{quantity}'

        fruit['uuid'] = generate_uuid()
        fruit['quantity'] = quantity

        if not self.game_engine._add_item_to_inventory(state, fruit):
            return state, '背包已满，无法收获'

        state['farm']['plots'][plot_index] = None
        return state, msg

    def get_seed_list(self):
        if not self.game_engine:
            return []
        seeds = self.game_engine.config.get('seeds', [])
        crops = {c['id']: c for c in self.game_engine.config.get('crops', [])}
        result = []
        for seed_cfg in seeds:
            crop = crops.get(seed_cfg.get('crop_id'))
            result.append({
                'crop_id': seed_cfg.get('crop_id'),
                'seed_id': seed_cfg.get('id'),
                'seed_name': seed_cfg.get('name'),
                'price': seed_cfg.get('price', 10000),
                'description': seed_cfg.get('description', ''),
                'icon': seed_cfg.get('icon', '🌱'),
                'crop_name': crop.get('name') if crop else '未知作物',
                'growthTime': seed_cfg.get('growthTime', 3600)
            })
        return result

    def buy_seed(self, state, crop_id, quantity=1):
        if not self.game_engine:
            return state, '系统错误'
        seed_cfg = self._get_seed_config_by_crop_id(crop_id)
        if not seed_cfg:
            return state, '无效的作物ID'

        crop = self._get_crop_by_id(crop_id)
        if not crop:
            return state, '作物配置错误'

        seed_price = seed_cfg.get('price', 10000)
        total_cost = seed_price * quantity
        if state['player']['gold'] < total_cost:
            return state, f'金币不足，需要{total_cost}金币'

        state['player']['gold'] -= total_cost

        seed_item = {
            'id': seed_cfg.get('id'),
            'name': seed_cfg.get('name'),
            'type': 'seed',
            'crop_id': crop_id,
            'price': seed_price,
            'icon': seed_cfg.get('icon', crop.get('icon', '🌱')),
            'description': seed_cfg.get('description', f'种植后可收获{crop.get("fruit_name", "果实")}'),
            'quantity': quantity,
            'maxStack': 9999,
            'uuid': generate_uuid(),
            'growthTime': seed_cfg.get('growthTime', crop.get('growthTime', 3600))
        }

        storage = self._ensure_seed_storage(state)['seed_storage']
        merged = False
        for existing in storage:
            if existing.get('id') == seed_item['id']:
                existing['quantity'] = existing.get('quantity', 0) + quantity
                if 'growthTime' not in existing:
                    existing['growthTime'] = seed_item.get('growthTime', 3600)
                merged = True
                break
        if not merged:
            storage.append(seed_item)

        return state, f'成功购买 {seed_item["name"]} x{quantity}，已存入种子仓库，花费{total_cost}金币'

    def get_seed_storage(self, state):
        state = self._ensure_seed_storage(state)
        return {'seeds': state['seed_storage']}

    def buy_tool(self, state, tool_id, quantity=1):
        tools = self.game_engine.config.get('farm_tools', [])
        tool_cfg = next((t for t in tools if t['id'] == tool_id), None)
        if not tool_cfg:
            return state, '无效的工具ID'

        total_cost = tool_cfg['price'] * quantity
        if state['player']['gold'] < total_cost:
            return state, f'金币不足，需要{total_cost}金币'

        state['player']['gold'] -= total_cost

        tool_item = {
            'id': tool_cfg['id'],
            'name': tool_cfg['name'],
            'type': 'tool',
            'action': tool_cfg['action'],
            'price': tool_cfg['price'],
            'icon': tool_cfg.get('icon', '🔧'),
            'description': tool_cfg.get('description', ''),
            'quantity': quantity,
            'maxStack': tool_cfg.get('maxStack', 99),
            'uuid': generate_uuid()
        }

        storage = self._ensure_seed_storage(state)['seed_storage']
        merged = False
        for existing in storage:
            if existing.get('type') == 'tool' and existing.get('id') == tool_id:
                new_qty = existing.get('quantity', 0) + quantity
                if new_qty <= existing.get('maxStack', 99):
                    existing['quantity'] = new_qty
                    merged = True
                else:
                    return state, f'工具数量已达堆叠上限，无法购买'
                break
        if not merged:
            storage.append(tool_item)

        return state, f'成功购买 {tool_cfg["name"]} x{quantity}，已存入种子仓库'

    def use_fruit(self, state, fruit_uuid):
        inventory = state.get('inventory', [])
        fruit_item = None
        fruit_idx = None
        for i, item in enumerate(inventory):
            if item.get('uuid') == fruit_uuid and item.get('type') == 'fruit':
                fruit_item = item
                fruit_idx = i
                break

        if not fruit_item:
            return state, '物品不存在或不是果实', None

        buff = fruit_item.get('buff')
        if not buff:
            return state, '该果实没有增益效果', None

        buff_type = buff['type']
        value = buff['value']
        duration = buff['duration']
        is_mutated = fruit_item.get('is_mutated', False)

        # ---------- 为单个目标应用增益（复用原有冲突逻辑）----------
        def apply_to_target(state, target):
            now = time.time()
            existing_key = None
            existing_data = None
            existing_source = None

            # 查找该目标上同类型的增益
            if 'temporary_buffs' in state:
                for key, buf in state['temporary_buffs'].items():
                    if buf.get('target') != target:
                        continue
                    attrs = buf.get('attributes', {})
                    if buff_type in attrs:
                        existing_key = key
                        existing_data = buf
                        existing_source = buf.get('source', 'normal')
                        break

            # 冲突处理
            if existing_data:
                # 已有变异增益
                if existing_source == 'mutated':
                    if not is_mutated:
                        # 普通果实不能覆盖变异
                        return state, False, f'{target}已有更强的变异效果，无法使用该果实'
                    else:
                        # 变异覆盖变异：删除旧的，后面创建新的
                        del state['temporary_buffs'][existing_key]
                # 已有普通增益
                elif existing_source == 'normal' and not is_mutated:
                    # 普通叠加普通 → 延长持续时间
                    state['temporary_buffs'][existing_key]['expire_time'] += duration
                    return state, True, f'{target}{self._get_buff_chinese(buff_type)}效果已延长{duration}秒'
                # 变异覆盖普通：删除旧的，后面创建新的
                if is_mutated and existing_source == 'normal':
                    del state['temporary_buffs'][existing_key]

            # 创建新增益
            unique_id = f"{buff_type}_{target}_{int(now * 1000000)}"
            state['temporary_buffs'][unique_id] = {
                'target': target,
                'attributes': {buff_type: value},
                'expire_time': now + duration,
                'source': 'mutated' if is_mutated else 'normal'
            }
            return state, True, f'{target}{self._get_buff_chinese(buff_type)}效果已生效（{"变异" if is_mutated else "普通"}，持续{duration}秒）'

        # 分别作用于玩家和英雄（全体）
        state, ok1, msg1 = apply_to_target(state, 'player')
        state, ok2, msg2 = apply_to_target(state, 'hero')

        if not ok1 or not ok2:
            return state, f'使用失败：{msg1 if not ok1 else msg2}', None

        # 扣除果实
        if fruit_item.get('quantity', 1) > 1:
            fruit_item['quantity'] -= 1
        else:
            inventory.pop(fruit_idx)

        state = self.game_engine._update_final_stats(state)
        # 统一消息，不区分具体目标
        return state, f'全体{self._get_buff_chinese(buff_type)}效果已生效，持续{duration}秒', None
        
    def _get_buff_chinese(self, buff_type):
        type_map = {
            'attack': '攻击力', 'defense': '防御力', 'hp': '生命值',
            'gameSpeed': '游戏速度', 'expMultiplier': '经验倍率',
            'accuracy': '命中', 'dodge': '躲闪'
        }
        return type_map.get(buff_type, buff_type)