package com.ycwl.basic.controller.mobile;

import com.github.pagehelper.PageInfo;
import com.ycwl.basic.constant.BaseContextHandler;
import com.ycwl.basic.mapper.SourceMapper;
import com.ycwl.basic.mapper.VideoMapper;
import com.ycwl.basic.model.pc.source.entity.MemberSourceEntity;
import com.ycwl.basic.model.pc.source.req.SourceReqQuery;
import com.ycwl.basic.model.pc.task.entity.TaskEntity;
import com.ycwl.basic.model.pc.video.entity.MemberVideoEntity;
import com.ycwl.basic.model.pc.video.entity.VideoEntity;
import com.ycwl.basic.pricing.enums.ProductType;
import com.ycwl.basic.repository.TemplateRepository;
import com.ycwl.basic.repository.VideoRepository;
import com.ycwl.basic.repository.VideoTaskRepository;
import com.ycwl.basic.service.pc.OrderService;
import com.ycwl.basic.utils.ApiResponse;
import com.ycwl.basic.pricing.dto.*;
import com.ycwl.basic.pricing.service.IPriceCalculationService;
import com.ycwl.basic.service.pc.FaceService;
import com.ycwl.basic.service.PriceCacheService;
import com.ycwl.basic.model.pc.face.resp.FaceRespVO;
import com.ycwl.basic.dto.MobileOrderRequest;
import com.ycwl.basic.order.service.IOrderService;
import com.ycwl.basic.order.dto.OrderV2DetailResponse;
import com.ycwl.basic.order.dto.OrderV2ListResponse;
import com.ycwl.basic.order.dto.OrderV2PageRequest;
import com.ycwl.basic.order.dto.PaymentParamsRequest;
import com.ycwl.basic.order.dto.PaymentParamsResponse;
import com.ycwl.basic.order.dto.PaymentCallbackResponse;
import com.ycwl.basic.order.exception.DuplicatePurchaseException;
import com.ycwl.basic.order.factory.DuplicatePurchaseCheckerFactory;
import com.ycwl.basic.order.strategy.DuplicateCheckContext;
import com.ycwl.basic.order.strategy.IDuplicatePurchaseChecker;
import com.ycwl.basic.product.capability.DuplicateCheckStrategy;
import com.ycwl.basic.product.service.IProductTypeCapabilityService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import jakarta.servlet.http.HttpServletRequest;

import java.util.List;

/**
 * 移动端订单控制器V2
 * 包含价格查询和订单管理功能
 */
@Slf4j
@RestController
@RequestMapping("/api/mobile/order/v2")
@RequiredArgsConstructor
public class AppOrderV2Controller {
    
    private final IPriceCalculationService priceCalculationService;
    private final FaceService faceService;
    private final PriceCacheService priceCacheService;
    private final IOrderService orderService;
    private final OrderService oldOrderService;
    private final SourceMapper sourceMapper;
    private final VideoMapper videoMapper;
    private final VideoTaskRepository videoTaskRepository;
    private final TemplateRepository templateRepository;
    private final VideoRepository videoRepository;
    private final RedisTemplate<String, Object> redisTemplate;
    private final IProductTypeCapabilityService productTypeCapabilityService;
    private final DuplicatePurchaseCheckerFactory duplicatePurchaseCheckerFactory;

    /**
     * 移动端价格计算
     * 集成Redis缓存机制，提升查询性能
     */
    @PostMapping("/calculate")
    public ApiResponse<PriceCalculationResult> calculatePrice(@RequestBody MobilePriceCalculationRequest request) {
        // 获取当前登录用户ID
        String currentUserIdStr = BaseContextHandler.getUserId();
        if (currentUserIdStr == null) {
            log.warn("移动端价格计算：用户未登录");
            return ApiResponse.fail("用户未登录");
        }
        
        Long currentUserId = Long.valueOf(currentUserIdStr);
        log.info("移动端价格计算请求: userId={}, faceId={}, products={}", 
                currentUserId, request.getFaceId(), request.getProducts().size());
        
        // 验证faceId参数
        if (request.getFaceId() == null) {
            log.warn("移动端价格计算：faceId参数缺失");
//            return ApiResponse.fail("faceId参数不能为空");
            // 兼容：兼容旧版本
            ProductItem productItem = request.getProducts().getFirst();
            switch (productItem.getProductType()) {
                case VLOG_VIDEO -> {
                    VideoEntity video = videoRepository.getVideo(Long.valueOf(productItem.getProductId()));
                    request.setFaceId(video.getFaceId());
                }
                case RECORDING_SET, PHOTO_SET, AI_CAM_PHOTO_SET -> request.setFaceId(Long.valueOf(productItem.getProductId()));
                case PHOTO -> {
                    MemberSourceEntity ms = sourceMapper.getMemberSourceByMemberAndSourceId(currentUserId, Long.valueOf(productItem.getProductId()));
                    if (ms != null) {
                        request.setFaceId(ms.getFaceId());
                    }
                }
            }
        }
        
        // 查询人脸信息进行权限验证
        ApiResponse<FaceRespVO> faceResponse = faceService.getById(request.getFaceId());
        if (!faceResponse.isSuccess() || faceResponse.getData() == null) {
            log.warn("移动端价格计算：人脸信息不存在, faceId={}", request.getFaceId());
            return ApiResponse.fail("人脸信息不存在");
        }
        
        FaceRespVO face = faceResponse.getData();
        Long scenicId = face.getScenicId();

        request.getProducts().forEach(product -> {
            // 获取商品的重复检查策略
            DuplicateCheckStrategy strategy = productTypeCapabilityService
                    .getDuplicateCheckStrategy(product.getProductType().name());

            boolean hasPurchasedFlag;

            switch (product.getProductType()) {
                case VLOG_VIDEO:
                    List<MemberVideoEntity> videoEntities = videoMapper.listRelationByFaceAndTemplate(face.getId(), Long.valueOf(product.getProductId()));
                    if (videoEntities != null && !videoEntities.isEmpty()) {
                        product.setQuantity(videoTaskRepository.getTaskLensNum(videoEntities.getFirst().getTaskId()));
                    } else {
                        product.setQuantity(1);
                    }
                    break;
                case RECORDING_SET:
                case PHOTO_SET:
                    SourceReqQuery sourceReqQuery = new SourceReqQuery();
                    sourceReqQuery.setMemberId(currentUserId);
                    sourceReqQuery.setType(product.getProductType() == ProductType.RECORDING_SET ? 1 : 2);
                    sourceReqQuery.setFaceId(face.getId());
                    Integer count = sourceMapper.countUser(sourceReqQuery);
                    product.setQuantity(count);
                    break;
                case AI_CAM_PHOTO_SET:
                    SourceReqQuery aiPhotoSetReqQuery = new SourceReqQuery();
                    aiPhotoSetReqQuery.setMemberId(currentUserId);
                    aiPhotoSetReqQuery.setType(13);
                    aiPhotoSetReqQuery.setFaceId(face.getId());
                    Integer _count = sourceMapper.countUser(aiPhotoSetReqQuery);
                    product.setQuantity(_count);
                    break;
                case PHOTO:
                    product.setQuantity(1);
                    break;
                default:
                    log.warn("未知的商品类型，跳过重复购买检查: productType={}", product.getProductType());
                    break;
            }

            // 使用 DuplicatePurchaseChecker 检查是否已购买
            hasPurchasedFlag = checkIfPurchased(strategy, currentUserId, String.valueOf(scenicId),
                    product.getProductType().name(), product.getProductId(), face.getId());

            // 设置是否已购买标识
            product.setHasPurchased(hasPurchasedFlag);
        });

        // 转换为标准价格计算请求
        PriceCalculationRequest standardRequest = request.toStandardRequest(currentUserId, scenicId);
        
        // 执行价格计算
        PriceCalculationResult result = priceCalculationService.calculatePrice(standardRequest);

        // 设置是否已购买标识（基于请求中的商品 hasPurchased 判断）
        // 只要有一个商品 hasPurchased = true，则整体 isPurchased = true
        boolean isPurchased = request.getProducts().stream()
                .anyMatch(product -> Boolean.TRUE.equals(product.getHasPurchased()));
        result.setIsPurchased(isPurchased);

        // 将计算结果缓存到Redis
        String cacheKey = priceCacheService.cachePriceResult(currentUserId, scenicId, request.getProducts(), result);
        
        log.info("移动端价格计算完成: userId={}, scenicId={}, originalAmount={}, finalAmount={}, cacheKey={}", 
                currentUserId, scenicId, result.getOriginalAmount(), result.getFinalAmount(), cacheKey);
        
        return ApiResponse.success(result);
    }
    
    /**
     * 移动端下单接口
     * 验证价格缓存有效性，确保5分钟内使用缓存价格下单
     */
    @PostMapping("/add")
    public ApiResponse<String> addOrder(@RequestBody MobileOrderRequest request) {
        // 获取当前登录用户ID
        String currentUserIdStr = BaseContextHandler.getUserId();
        if (currentUserIdStr == null) {
            log.warn("移动端下单：用户未登录");
            return ApiResponse.fail("用户未登录");
        }
        
        Long currentUserId = Long.valueOf(currentUserIdStr);
        log.info("移动端下单请求: userId={}, faceId={}, products={}, expectedFinalAmount={}", 
                currentUserId, request.getFaceId(), request.getProducts().size(), request.getExpectedFinalAmount());
        
        // 验证必填参数
        if (request.getFaceId() == null) {
            log.warn("移动端下单：faceId参数缺失");
            return ApiResponse.fail("faceId参数不能为空");
        }
        
        if (request.getProducts() == null || request.getProducts().isEmpty()) {
            log.warn("移动端下单：商品列表为空");
            return ApiResponse.fail("商品列表不能为空");
        }
        
        if (request.getExpectedFinalAmount() == null) {
            log.warn("移动端下单：预期价格参数缺失");
            return ApiResponse.fail("预期价格不能为空");
        }
        
        // 查询人脸信息进行权限验证
        ApiResponse<FaceRespVO> faceResponse = faceService.getById(request.getFaceId());
        if (!faceResponse.isSuccess() || faceResponse.getData() == null) {
            log.warn("移动端下单：人脸信息不存在, faceId={}", request.getFaceId());
            return ApiResponse.fail("人脸信息不存在");
        }
        
        FaceRespVO face = faceResponse.getData();
        Long scenicId = face.getScenicId();
        
        // 验证并消费价格缓存（一次性使用）
        PriceCalculationResult cachedResult = priceCacheService.validateAndConsumePriceCache(
                currentUserId, scenicId, request.getProducts());
        
        if (cachedResult == null) {
            log.warn("移动端下单：价格缓存已过期或不存在, userId={}, scenicId={}", currentUserId, scenicId);
            return ApiResponse.fail("请重新下单！");
        }
        
        // 验证价格是否匹配
        if (cachedResult.getFinalAmount().compareTo(request.getExpectedFinalAmount()) != 0) {
            log.warn("移动端下单：价格不匹配, cached={}, expected={}, userId={}, scenicId={}", 
                    cachedResult.getFinalAmount(), request.getExpectedFinalAmount(), currentUserId, scenicId);
            return ApiResponse.fail("价格信息变化，请退出后重新查询价格！");
        }
        
        // 验证原价是否匹配（可选）
        if (request.getExpectedOriginalAmount() != null && 
            cachedResult.getOriginalAmount().compareTo(request.getExpectedOriginalAmount()) != 0) {
            log.warn("移动端下单：原价不匹配, cached={}, expected={}, userId={}, scenicId={}", 
                    cachedResult.getOriginalAmount(), request.getExpectedOriginalAmount(), currentUserId, scenicId);
            return ApiResponse.fail("原价信息不匹配，请重新查询价格后再下单");
        }
        
        log.info("价格缓存验证通过: userId={}, scenicId={}, finalAmount={}", 
                currentUserId, scenicId, cachedResult.getFinalAmount());

        // 使用旧版创建订单逻辑
        try {
            Long orderId = oldOrderService.createOrderCompact(currentUserId, request, cachedResult);
            return ApiResponse.success(String.valueOf(orderId));
        } catch (Exception e) {
            log.warn("移动端下单：订单创建失败, userId={}, scenicId={}, error={}", currentUserId, scenicId, e.getMessage(), e);
            return ApiResponse.fail("订单创建失败，请稍后重试");
        }

        // 创建订单
//        try {
//            Long orderId = orderService.createOrder(request, currentUserId, scenicId, cachedResult);
//
//            log.info("移动端订单创建成功: orderId={}, userId={}, scenicId={}, finalAmount={}",
//                    orderId, currentUserId, scenicId, cachedResult.getFinalAmount());
//
//            return ApiResponse.success(orderId.toString());
//
//        } catch (Exception e) {
//            log.error("订单创建失败: userId={}, scenicId={}, error={}", currentUserId, scenicId, e.getMessage(), e);
//            return ApiResponse.fail("订单创建失败，请稍后重试");
//        }
    }
    
    // ====== 新增移动端订单查询功能 ======
    
    /**
     * 用户分页查询自己的订单列表
     */
    @PostMapping("/page")
    public ApiResponse<PageInfo<OrderV2ListResponse>> pageUserOrders(@RequestBody OrderV2PageRequest request) {
        String currentUserIdStr = BaseContextHandler.getUserId();
        if (currentUserIdStr == null) {
            log.warn("用户未登录");
            return ApiResponse.fail("用户未登录");
        }
        
        Long currentUserId = Long.valueOf(currentUserIdStr);
        request.setMemberId(currentUserId); // 设置当前用户ID，确保只查询自己的订单
        
        log.info("用户查询订单列表: userId={}, request={}", currentUserId, request);
        
        try {
            PageInfo<OrderV2ListResponse> pageInfo = orderService.pageOrdersByUser(request);
            return ApiResponse.success(pageInfo);
        } catch (Exception e) {
            log.error("查询用户订单列表失败: userId={}", currentUserId, e);
            return ApiResponse.fail("查询失败：" + e.getMessage());
        }
    }
    
    /**
     * 查询订单详情
     */
    @GetMapping("/detail/{orderId}")
    public ApiResponse<OrderV2DetailResponse> getUserOrderDetail(@PathVariable("orderId") Long orderId) {
        log.info("查询订单详情: orderId={}", orderId);

        try {
            OrderV2DetailResponse detail = orderService.getOrderDetail(orderId);
            if (detail == null) {
                return ApiResponse.fail("订单不存在");
            }

            return ApiResponse.success(detail);
        } catch (Exception e) {
            log.error("查询订单详情失败: orderId={}", orderId, e);
            return ApiResponse.fail("查询失败：" + e.getMessage());
        }
    }
    
    // ====== 支付相关接口 ======
    
    /**
     * 获取订单支付参数
     * 用于小程序调起支付
     */
    @PostMapping("/{orderId}/payment-params")
    public ApiResponse<PaymentParamsResponse> getPaymentParams(
            @PathVariable("orderId") Long orderId,
            @RequestBody PaymentParamsRequest request) {
        
        String currentUserIdStr = BaseContextHandler.getUserId();
        if (currentUserIdStr == null) {
            log.warn("用户未登录");
            return ApiResponse.fail("用户未登录");
        }
        
        Long currentUserId = Long.valueOf(currentUserIdStr);
        
        log.info("获取支付参数: userId={}, orderId={}", currentUserId, orderId);

        return oldOrderService.getPaymentParams(orderId, currentUserId, request);

//
//        try {
//            PaymentParamsResponse response = orderService.getPaymentParams(orderId, currentUserId, request);
//            return ApiResponse.success(response);
//        } catch (Exception e) {
//            log.error("获取支付参数失败: userId={}, orderId={}", currentUserId, orderId, e);
//            return ApiResponse.fail(e.getMessage());
//        }
    }
    
    /**
     * 支付回调处理接口
     * 供第三方支付平台回调使用
     */
    @PostMapping("/payment/callback/{scenicId}")
    public String handlePaymentCallback(
            @PathVariable("scenicId") Long scenicId,
            HttpServletRequest request) {
        
        log.info("接收支付回调: scenicId={}", scenicId);
        
        try {
            PaymentCallbackResponse response = orderService.handlePaymentCallback(scenicId, request);
            
            if (response.isSuccess()) {
                log.info("支付回调处理成功: scenicId={}, orderId={}, statusChangeType={}", 
                        scenicId, response.getOrderId(), response.getStatusChangeType());
                return "SUCCESS"; // 返回给第三方支付平台的成功标识
            } else {
                log.error("支付回调处理失败: scenicId={}, message={}", scenicId, response.getMessage());
                return "FAIL"; // 返回给第三方支付平台的失败标识
            }
        } catch (Exception e) {
            log.error("支付回调异常: scenicId={}", scenicId, e);
            return "FAIL";
        }
    }

    @GetMapping("/downloadable/{orderId}")
    public ApiResponse<Boolean> getDownloadableOrder(@PathVariable("orderId") Long orderId) {
        return ApiResponse.success(!redisTemplate.hasKey("order_content_not_downloadable_" + orderId));
    }

    /**
     * 检查商品是否已购买
     * 使用 DuplicatePurchaseChecker 通过异常捕获判断
     *
     * @param strategy 重复检查策略
     * @param userId 用户ID
     * @param scenicId 景区ID
     * @param productType 商品类型
     * @param productId 商品ID
     * @param faceId 人脸ID
     * @return true-已购买, false-未购买
     */
    private boolean checkIfPurchased(DuplicateCheckStrategy strategy, Long userId, String scenicId,
                                     String productType, String productId, Long faceId) {
        // NO_CHECK 策略表示允许重复购买，直接返回 false
        if (strategy == DuplicateCheckStrategy.NO_CHECK) {
            return false;
        }

        try {
            // 获取对应的检查器
            IDuplicatePurchaseChecker checker = duplicatePurchaseCheckerFactory.getChecker(strategy);

            // 构建检查上下文
            DuplicateCheckContext context = new DuplicateCheckContext();
            context.setUserId(String.valueOf(userId));
            context.setScenicId(scenicId);
            context.setProductType(productType);
            context.setProductId(productId);
            context.addParam("faceId", faceId);

            // 执行检查，如果抛出异常则表示已购买
            checker.check(context);

            // 没有抛出异常，表示未购买
            return false;

        } catch (DuplicatePurchaseException e) {
            // 捕获到重复购买异常，表示已购买
            log.debug("检测到已购买: userId={}, scenicId={}, productType={}, productId={}",
                    userId, scenicId, productType, productId);
            return true;

        } catch (Exception e) {
            // 其他异常，记录日志并返回 false（保守处理）
            log.warn("检查是否已购买时发生异常: userId={}, scenicId={}, productType={}, productId={}, error={}",
                    userId, scenicId, productType, productId, e.getMessage(), e);
            return false;
        }
    }
}
