package com.it.rattan.monisuo.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.it.rattan.monisuo.common.Result;
import com.it.rattan.monisuo.entity.OrderFund;
import com.it.rattan.monisuo.entity.OrderTrade;
import com.it.rattan.monisuo.entity.User;
import com.it.rattan.monisuo.mapper.AccountFundMapper;
import com.it.rattan.monisuo.mapper.OrderFundMapper;
import com.it.rattan.monisuo.mapper.OrderTradeMapper;
import com.it.rattan.monisuo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * 业务分析接口
 */
@RestController
@RequestMapping("/admin/analysis")
public class AnalysisController {

    @Autowired
    private OrderFundMapper orderFundMapper;

    @Autowired
    private OrderTradeMapper orderTradeMapper;

    @Autowired
    private AccountFundMapper accountFundMapper;

    @Autowired
    private UserService userService;

    /**
     * 盈利分析
     */
    @GetMapping("/profit")
    public Result<Map<String, Object>> getProfitAnalysis(
            @RequestParam(defaultValue = "month") String range) {
        
        Map<String, Object> data = new HashMap<>();
        
        // 根据时间范围计算
        LocalDateTime startTime = getStartTime(range);
        
        // 交易手续费 (0.1%)
        BigDecimal tradeFee = orderTradeMapper.sumFeeByTime(startTime);
        if (tradeFee == null) tradeFee = BigDecimal.ZERO;
        data.put("tradeFee", tradeFee);
        data.put("tradeFeeRate", "0.1%");
        
        // 充提手续费 (0.5%)
        BigDecimal fundFee = orderFundMapper.sumFeeByTime(startTime);
        if (fundFee == null) fundFee = BigDecimal.ZERO;
        data.put("fundFee", fundFee);
        data.put("fundFeeRate", "0.5%");
        
        // 资金利差 (年化3.5%，按天数计算)
        BigDecimal fundBalance = accountFundMapper.sumAllBalance();
        if (fundBalance == null) fundBalance = BigDecimal.ZERO;
        int days = getDays(range);
        BigDecimal interestRate = new BigDecimal("0.035").divide(new BigDecimal("365"), 10, RoundingMode.HALF_UP);
        BigDecimal interestProfit = fundBalance.multiply(interestRate).multiply(new BigDecimal(days));
        data.put("interestProfit", interestProfit.setScale(2, RoundingMode.HALF_UP));
        data.put("interestRate", "年化3.5%");
        
        // 总收益
        BigDecimal totalProfit = tradeFee.add(fundFee).add(interestProfit);
        data.put("totalProfit", totalProfit.setScale(2, RoundingMode.HALF_UP));
        
        return Result.success(data);
    }

    /**
     * 资金流动趋势
     */
    @GetMapping("/cash-flow")
    public Result<List<Map<String, Object>>> getCashFlowTrend(
            @RequestParam(defaultValue = "6") int months) {
        
        List<Map<String, Object>> result = new ArrayList<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("M月");
        
        for (int i = months - 1; i >= 0; i--) {
            LocalDate monthStart = LocalDate.now().minusMonths(i).withDayOfMonth(1);
            LocalDate monthEnd = monthStart.plusMonths(1).minusDays(1);
            
            LocalDateTime start = monthStart.atStartOfDay();
            LocalDateTime end = monthEnd.atTime(23, 59, 59);
            
            Map<String, Object> item = new HashMap<>();
            item.put("month", monthStart.format(formatter));
            
            // 充值
            BigDecimal deposit = orderFundMapper.sumDepositByTime(start, end);
            item.put("deposit", deposit != null ? deposit : BigDecimal.ZERO);
            
            // 提现
            BigDecimal withdraw = orderFundMapper.sumWithdrawByTime(start, end);
            item.put("withdraw", withdraw != null ? withdraw : BigDecimal.ZERO);
            
            // 净流入
            BigDecimal netInflow = (deposit != null ? deposit : BigDecimal.ZERO)
                    .subtract(withdraw != null ? withdraw : BigDecimal.ZERO);
            item.put("netInflow", netInflow);
            
            result.add(item);
        }
        
        return Result.success(result);
    }

    /**
     * 交易分析
     */
    @GetMapping("/trade")
    public Result<Map<String, Object>> getTradeAnalysis(
            @RequestParam(defaultValue = "week") String range) {
        
        Map<String, Object> data = new HashMap<>();
        LocalDateTime startTime = getStartTime(range);
        
        // 买入统计
        BigDecimal buyAmount = orderTradeMapper.sumAmountByTypeAndTime(1, startTime);
        int buyCount = orderTradeMapper.countByTypeAndTime(1, startTime);
        data.put("buyAmount", buyAmount != null ? buyAmount : BigDecimal.ZERO);
        data.put("buyCount", buyCount);
        
        // 卖出统计
        BigDecimal sellAmount = orderTradeMapper.sumAmountByTypeAndTime(2, startTime);
        int sellCount = orderTradeMapper.countByTypeAndTime(2, startTime);
        data.put("sellAmount", sellAmount != null ? sellAmount : BigDecimal.ZERO);
        data.put("sellCount", sellCount);
        
        // 净买入
        BigDecimal netBuy = (buyAmount != null ? buyAmount : BigDecimal.ZERO)
                .subtract(sellAmount != null ? sellAmount : BigDecimal.ZERO);
        data.put("netBuy", netBuy);
        
        // 交易趋势（按天）
        List<Map<String, Object>> trend = new ArrayList<>();
        int days = "week".equals(range) ? 7 : 30;
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("M-d");
        
        for (int i = days - 1; i >= 0; i--) {
            LocalDate date = LocalDate.now().minusDays(i);
            LocalDateTime dayStart = date.atStartOfDay();
            LocalDateTime dayEnd = date.atTime(23, 59, 59);
            
            Map<String, Object> item = new HashMap<>();
            item.put("date", date.format(formatter));
            
            BigDecimal dayBuy = orderTradeMapper.sumAmountByTypeAndTimeRange(1, dayStart, dayEnd);
            BigDecimal daySell = orderTradeMapper.sumAmountByTypeAndTimeRange(2, dayStart, dayEnd);
            
            item.put("buy", dayBuy != null ? dayBuy : BigDecimal.ZERO);
            item.put("sell", daySell != null ? daySell : BigDecimal.ZERO);
            
            trend.add(item);
        }
        data.put("trend", trend);
        
        return Result.success(data);
    }

    /**
     * 币种交易分布
     */
    @GetMapping("/coin-distribution")
    public Result<List<Map<String, Object>>> getCoinDistribution(
            @RequestParam(defaultValue = "month") String range) {
        
        LocalDateTime startTime = getStartTime(range);
        List<Map<String, Object>> result = orderTradeMapper.sumAmountGroupByCoin(startTime);
        
        return Result.success(result);
    }

    /**
     * 用户增长分析
     */
    @GetMapping("/user-growth")
    public Result<Map<String, Object>> getUserGrowth(
            @RequestParam(defaultValue = "6") int months) {
        
        Map<String, Object> data = new HashMap<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("M月");
        
        // 月度趋势
        List<Map<String, Object>> trend = new ArrayList<>();
        for (int i = months - 1; i >= 0; i--) {
            LocalDate monthStart = LocalDate.now().minusMonths(i).withDayOfMonth(1);
            LocalDate monthEnd = monthStart.plusMonths(1).minusDays(1);
            
            LocalDateTime start = monthStart.atStartOfDay();
            LocalDateTime end = monthEnd.atTime(23, 59, 59);
            
            Map<String, Object> item = new HashMap<>();
            item.put("month", monthStart.format(formatter));
            
            // 新增用户
            int newUsers = userService.count(new LambdaQueryWrapper<User>()
                    .ge(User::getCreateTime, start)
                    .le(User::getCreateTime, end));
            item.put("newUsers", newUsers);
            
            // 活跃用户（有交易的）
            int activeUsers = orderTradeMapper.countDistinctUserByTime(start, end);
            item.put("activeUsers", activeUsers);
            
            trend.add(item);
        }
        data.put("trend", trend);
        
        // 当前统计
        int totalUsers = (int) userService.count();
        int monthNewUsers = userService.count(new LambdaQueryWrapper<User>()
                .ge(User::getCreateTime, LocalDate.now().withDayOfMonth(1).atStartOfDay()));
        int activeUsersToday = orderTradeMapper.countDistinctUserByTime(
                LocalDate.now().atStartOfDay(), LocalDateTime.now());
        
        data.put("totalUsers", totalUsers);
        data.put("monthNewUsers", monthNewUsers);
        data.put("activeUsersToday", activeUsersToday);
        
        return Result.success(data);
    }

    /**
     * 风险指标
     */
    @GetMapping("/risk")
    public Result<Map<String, Object>> getRiskMetrics() {
        Map<String, Object> data = new HashMap<>();
        
        // 大额交易 (>50000)
        int largeTransactions = orderFundMapper.countLargeAmount(new BigDecimal("50000"));
        data.put("largeTransactions", largeTransactions);
        data.put("largeTransactionThreshold", ">¥50,000");
        
        // 异常提现 (24小时内>3次)
        LocalDateTime yesterday = LocalDateTime.now().minusHours(24);
        int abnormalWithdrawals = orderFundMapper.countAbnormalWithdrawals(yesterday, 3);
        data.put("abnormalWithdrawals", abnormalWithdrawals);
        data.put("abnormalWithdrawalThreshold", "24h内>3次");
        
        // 待审KYC (这里简化为未实名用户)
        int pendingKyc = userService.count(new LambdaQueryWrapper<User>()
                .eq(User::getKycStatus, 0));
        data.put("pendingKyc", pendingKyc);
        
        // 冻结账户
        int frozenAccounts = userService.count(new LambdaQueryWrapper<User>()
                .eq(User::getStatus, 0));
        data.put("frozenAccounts", frozenAccounts);
        
        return Result.success(data);
    }

    /**
     * 综合健康度评分
     */
    @GetMapping("/health")
    public Result<Map<String, Object>> getHealthScore() {
        Map<String, Object> data = new HashMap<>();
        
        // 流动性评分 (在管资金/总资产)
        BigDecimal fundBalance = accountFundMapper.sumAllBalance();
        BigDecimal tradeValue = accountFundMapper.sumAllTradeValue();
        BigDecimal totalAsset = (fundBalance != null ? fundBalance : BigDecimal.ZERO)
                .add(tradeValue != null ? tradeValue : BigDecimal.ZERO);
        
        int liquidityScore = 100;
        if (totalAsset.compareTo(BigDecimal.ZERO) > 0 && fundBalance != null) {
            BigDecimal ratio = fundBalance.divide(totalAsset, 2, RoundingMode.HALF_UP);
            liquidityScore = ratio.multiply(new BigDecimal(100)).intValue();
        }
        
        // 风险评分 (基于异常交易)
        int abnormalCount = orderFundMapper.countAbnormalWithdrawals(
                LocalDateTime.now().minusHours(24), 3);
        int riskScore = Math.max(0, 100 - abnormalCount * 10);
        
        // 稳定性评分 (基于用户增长)
        int monthNewUsers = userService.count(new LambdaQueryWrapper<User>()
                .ge(User::getCreateTime, LocalDate.now().withDayOfMonth(1).atStartOfDay()));
        int stabilityScore = Math.min(100, 50 + monthNewUsers);
        
        // 综合评分
        int overallScore = (liquidityScore + riskScore + stabilityScore) / 3;
        
        data.put("overallScore", overallScore);
        data.put("liquidityScore", liquidityScore);
        data.put("riskScore", riskScore);
        data.put("stabilityScore", stabilityScore);
        
        // 评级
        String grade = overallScore >= 80 ? "优秀" : overallScore >= 60 ? "良好" : "需改进";
        data.put("grade", grade);
        
        return Result.success(data);
    }

    // ========== 工具方法 ==========

    private LocalDateTime getStartTime(String range) {
        switch (range) {
            case "day":
                return LocalDate.now().atStartOfDay();
            case "week":
                return LocalDate.now().minusWeeks(1).atStartOfDay();
            case "month":
                return LocalDate.now().withDayOfMonth(1).atStartOfDay();
            case "year":
                return LocalDate.now().withDayOfYear(1).atStartOfDay();
            default:
                return LocalDate.now().withDayOfMonth(1).atStartOfDay();
        }
    }

    private int getDays(String range) {
        switch (range) {
            case "day":
                return 1;
            case "week":
                return 7;
            case "month":
                return 30;
            case "year":
                return 365;
            default:
                return 30;
        }
    }
}
