package com.dora.service.impl;

import com.dora.dto.ToolDto;
import com.dora.entity.ToolConfig;
import com.dora.entity.ToolUsageDailyStats;
import com.dora.exception.BusinessException;
import com.dora.mapper.ToolConfigMapper;
import com.dora.mapper.ToolUsageDailyStatsMapper;
import com.dora.mapper.ToolUsageLogMapper;
import com.dora.service.AdminToolConfigService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 管理端工具配置服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class AdminToolConfigServiceImpl implements AdminToolConfigService {

    private final ToolConfigMapper toolConfigMapper;
    private final ToolUsageLogMapper toolUsageLogMapper;
    private final ToolUsageDailyStatsMapper toolUsageDailyStatsMapper;

    // ==================== 工具配置管理 ====================

    @Override
    public List<ToolDto.ConfigResponse> getAllConfigs() {
        List<ToolConfig> configs = toolConfigMapper.selectAll();
        return configs.stream()
                .map(this::convertToConfigResponse)
                .collect(Collectors.toList());
    }

    @Override
    public ToolDto.ConfigResponse getConfigById(Long id) {
        ToolConfig config = toolConfigMapper.selectById(id);
        if (config == null) {
            throw new BusinessException("工具配置不存在");
        }
        return convertToConfigResponse(config);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ToolDto.ConfigResponse createConfig(ToolDto.ConfigRequest request) {
        // 验证工具编码唯一性
        int count = toolConfigMapper.countByToolCode(request.getToolCode(), 0L);
        if (count > 0) {
            throw new BusinessException("工具编码已存在: " + request.getToolCode());
        }

        ToolConfig config = new ToolConfig();
        config.setToolCode(request.getToolCode());
        config.setToolName(request.getToolName());
        config.setCategory(request.getCategory());
        config.setDescription(request.getDescription());
        config.setApiEndpoint(request.getApiEndpoint());
        config.setRequestMethod(request.getRequestMethod() != null ? request.getRequestMethod() : "GET");
        config.setPointsCost(request.getPointsCost() != null ? request.getPointsCost() : 1);
        config.setIsEnabled(request.getIsEnabled() != null ? request.getIsEnabled() : 1);
        config.setSortOrder(request.getSortOrder() != null ? request.getSortOrder() : 0);

        int result = toolConfigMapper.insert(config);
        if (result <= 0) {
            throw new BusinessException("创建工具配置失败");
        }

        log.info("创建工具配置成功: toolCode={}, toolName={}", config.getToolCode(), config.getToolName());
        return convertToConfigResponse(config);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ToolDto.ConfigResponse updateConfig(Long id, ToolDto.ConfigRequest request) {
        ToolConfig existing = toolConfigMapper.selectById(id);
        if (existing == null) {
            throw new BusinessException("工具配置不存在");
        }

        // 验证工具编码唯一性（排除自身）
        if (!existing.getToolCode().equals(request.getToolCode())) {
            int count = toolConfigMapper.countByToolCode(request.getToolCode(), id);
            if (count > 0) {
                throw new BusinessException("工具编码已存在: " + request.getToolCode());
            }
        }

        existing.setToolCode(request.getToolCode());
        existing.setToolName(request.getToolName());
        existing.setCategory(request.getCategory());
        existing.setDescription(request.getDescription());
        existing.setApiEndpoint(request.getApiEndpoint());
        existing.setRequestMethod(request.getRequestMethod());
        existing.setPointsCost(request.getPointsCost());
        existing.setIsEnabled(request.getIsEnabled());
        existing.setSortOrder(request.getSortOrder());

        int result = toolConfigMapper.updateById(existing);
        if (result <= 0) {
            throw new BusinessException("更新工具配置失败");
        }

        log.info("更新工具配置成功: id={}, toolCode={}", id, existing.getToolCode());
        return convertToConfigResponse(existing);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updatePointsCost(Long id, Integer pointsCost) {
        if (pointsCost == null || pointsCost < 0) {
            throw new BusinessException("积分消耗必须大于等于0");
        }

        ToolConfig existing = toolConfigMapper.selectById(id);
        if (existing == null) {
            throw new BusinessException("工具配置不存在");
        }

        int result = toolConfigMapper.updatePointsCost(id, pointsCost);
        log.info("更新工具积分消耗: id={}, toolCode={}, pointsCost={}", id, existing.getToolCode(), pointsCost);
        return result > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateStatus(Long id, Integer isEnabled) {
        ToolConfig existing = toolConfigMapper.selectById(id);
        if (existing == null) {
            throw new BusinessException("工具配置不存在");
        }

        int result = toolConfigMapper.updateStatus(id, isEnabled);
        log.info("更新工具状态: id={}, toolCode={}, isEnabled={}", id, existing.getToolCode(), isEnabled);
        return result > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteConfig(Long id) {
        ToolConfig existing = toolConfigMapper.selectById(id);
        if (existing == null) {
            throw new BusinessException("工具配置不存在");
        }

        int result = toolConfigMapper.deleteById(id);
        log.info("删除工具配置: id={}, toolCode={}", id, existing.getToolCode());
        return result > 0;
    }

    // ==================== 使用统计 ====================

    @Override
    public ToolDto.StatsSummaryResponse getStatsSummary(LocalDate startDate, LocalDate endDate) {
        if (startDate == null) startDate = LocalDate.now().minusDays(30);
        if (endDate == null) endDate = LocalDate.now();

        // 从每日统计表获取汇总数据
        ToolUsageDailyStatsMapper.StatsSummary summary = 
                toolUsageDailyStatsMapper.selectSummaryByDateRange(startDate, endDate);

        // 获取按工具分组的统计
        List<ToolUsageDailyStatsMapper.ToolStatsSummary> toolStats = 
                toolUsageDailyStatsMapper.selectToolSummaryByDateRange(startDate, endDate);

        List<ToolDto.ToolStatsItem> toolStatsItems = toolStats.stream()
                .map(ts -> ToolDto.ToolStatsItem.builder()
                        .toolCode(ts.getToolCode())
                        .toolName(ts.getToolName())
                        .totalCalls(ts.getTotalCalls())
                        .successCalls(ts.getSuccessCalls())
                        .totalPointsCost(ts.getTotalPointsCost())
                        .build())
                .collect(Collectors.toList());

        return ToolDto.StatsSummaryResponse.builder()
                .totalCalls(summary != null ? summary.getTotalCalls() : 0L)
                .successCalls(summary != null ? summary.getSuccessCalls() : 0L)
                .failedCalls(summary != null ? summary.getFailedCalls() : 0L)
                .totalPointsCost(summary != null ? summary.getTotalPointsCost() : 0L)
                .toolStats(toolStatsItems)
                .build();
    }

    @Override
    public List<ToolDto.DailyStatsResponse> getDailyStats(LocalDate startDate, LocalDate endDate, String toolCode) {
        if (startDate == null) startDate = LocalDate.now().minusDays(7);
        if (endDate == null) endDate = LocalDate.now();

        List<ToolUsageDailyStats> statsList;
        if (toolCode != null && !toolCode.trim().isEmpty()) {
            statsList = toolUsageDailyStatsMapper.selectByToolCodeAndDateRange(toolCode, startDate, endDate);
        } else {
            statsList = toolUsageDailyStatsMapper.selectByDateRange(startDate, endDate);
        }

        return statsList.stream()
                .map(s -> ToolDto.DailyStatsResponse.builder()
                        .statsDate(s.getStatsDate())
                        .toolCode(s.getToolCode())
                        .toolName(s.getToolName())
                        .totalCalls(s.getTotalCalls())
                        .successCalls(s.getSuccessCalls())
                        .failedCalls(s.getFailedCalls())
                        .totalPointsCost(s.getTotalPointsCost())
                        .uniqueUsers(s.getUniqueUsers())
                        .build())
                .collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void refreshDailyStats(LocalDate date) {
        if (date == null) date = LocalDate.now();

        LocalDateTime startTime = date.atStartOfDay();
        LocalDateTime endTime = date.atTime(LocalTime.MAX);

        // 从调用记录表统计数据
        List<ToolUsageLogMapper.ToolUsageStats> statsList = 
                toolUsageLogMapper.selectStatsByTimeRange(startTime, endTime);

        // 获取独立用户数
        Long uniqueUsers = toolUsageLogMapper.countUniqueUsersByTimeRange(startTime, endTime);

        // 更新每日统计表
        for (ToolUsageLogMapper.ToolUsageStats stats : statsList) {
            ToolConfig config = toolConfigMapper.selectByToolCode(stats.getToolCode());
            
            ToolUsageDailyStats dailyStats = new ToolUsageDailyStats();
            dailyStats.setStatsDate(date);
            dailyStats.setToolId(config != null ? config.getId() : null);
            dailyStats.setToolCode(stats.getToolCode());
            dailyStats.setToolName(stats.getToolName());
            dailyStats.setTotalCalls(stats.getTotalCalls() != null ? stats.getTotalCalls().intValue() : 0);
            dailyStats.setSuccessCalls(stats.getSuccessCalls() != null ? stats.getSuccessCalls().intValue() : 0);
            dailyStats.setFailedCalls(dailyStats.getTotalCalls() - dailyStats.getSuccessCalls());
            dailyStats.setTotalPointsCost(stats.getTotalPointsCost() != null ? stats.getTotalPointsCost().intValue() : 0);
            dailyStats.setUniqueUsers(uniqueUsers != null ? uniqueUsers.intValue() : 0);

            toolUsageDailyStatsMapper.insertOrUpdate(dailyStats);
        }

        log.info("刷新每日统计完成: date={}, toolCount={}", date, statsList.size());
    }

    @Override
    public ToolStatsInfo getToolStatsInfo() {
        Long totalTools = toolConfigMapper.countAll();
        Long enabledTools = toolConfigMapper.countEnabled();

        // 今日统计
        LocalDate today = LocalDate.now();
        LocalDateTime startTime = today.atStartOfDay();
        LocalDateTime endTime = today.atTime(LocalTime.MAX);

        Long todayCalls = toolUsageLogMapper.countByTimeRange(startTime, endTime);
        
        // 计算今日消耗积分
        List<ToolUsageLogMapper.ToolUsageStats> todayStats = 
                toolUsageLogMapper.selectStatsByTimeRange(startTime, endTime);
        Long todayPointsCost = todayStats.stream()
                .mapToLong(s -> s.getTotalPointsCost() != null ? s.getTotalPointsCost() : 0L)
                .sum();

        return new ToolStatsInfo(totalTools, enabledTools, todayCalls, todayPointsCost);
    }

    private ToolDto.ConfigResponse convertToConfigResponse(ToolConfig config) {
        return ToolDto.ConfigResponse.builder()
                .id(config.getId())
                .toolCode(config.getToolCode())
                .toolName(config.getToolName())
                .category(config.getCategory())
                .description(config.getDescription())
                .apiEndpoint(config.getApiEndpoint())
                .requestMethod(config.getRequestMethod())
                .pointsCost(config.getPointsCost())
                .isEnabled(config.getIsEnabled())
                .sortOrder(config.getSortOrder())
                .createTime(config.getCreateTime())
                .updateTime(config.getUpdateTime())
                .build();
    }
}
