package com.erp.inventory.controller;

import com.erp.common.core.model.ApiResponse;
import com.erp.inventory.entity.Stock;
import com.erp.inventory.service.StockCheckService;
import com.erp.inventory.service.impl.StockIdempotencyService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

/**
 * 库存Feign客户端控制器
 * 为order-service等远程服务提供库存操作接口
 * 
 * 对应StockClient接口定义的 endpoints:
 * - POST /api/stock/deduct  - 扣减库存（订单发货时调用）
 * - POST /api/stock/unlock  - 解锁库存（订单驳回/取消时调用）
 * - POST /api/stock/lock    - 锁定库存（订单创建/审核时预占库存）
 */
@Slf4j
@RestController
@RequestMapping("/api/stock")
@RequiredArgsConstructor
public class StockFeignController {

    private final StockCheckService stockCheckService;
    private final StockIdempotencyService idempotencyService;

    /**
     * 扣减库存（订单发货时调用）
     * 对应PHP StockService::deduct
     * <p>
     * 幂等性保证：使用 skuCode + warehouseId + relatedNo 作为幂等键
     * 重复扣减请求直接返回成功（从Redis获取已处理结果）
     */
    @PostMapping("/deduct")
    public ApiResponse<StockDeductResponse> deductStock(@RequestBody StockDeductRequest request) {
        try {
            // ========== 幂等性检查 ==========
            String idempotencyKey = idempotencyService.buildDeductKey(
                    request.getSkuCode(), request.getWarehouseId(), request.getRelatedNo());

            if (idempotencyService.isDuplicate(idempotencyKey)) {
                log.warn("[库存扣减] 重复扣减请求，已跳过: key={}", idempotencyKey);
                // 从Redis获取已处理结果直接返回
                Object cached = idempotencyService.getProcessedResult(idempotencyKey);
                if (cached instanceof StockDeductResponse) {
                    return ApiResponse.success("库存扣减成功（重复请求）", (StockDeductResponse) cached);
                }
                // 缓存数据格式不对，仍返回成功
                return ApiResponse.success("库存扣减成功（重复请求）", (StockDeductResponse) cached);
            }

            log.info("扣减库存请求: skuCode={}, warehouseId={}, quantity={}, orderId={}",
                    request.getSkuCode(), request.getWarehouseId(), request.getQuantity(), request.getRelatedNo());

            Stock stock = stockCheckService.shipStock(
                    request.getSkuCode(),
                    request.getWarehouseId(),
                    request.getQuantity(),
                    parseOrderId(request.getRelatedNo()),
                    request.getRemark()
            );

            StockDeductResponse response = new StockDeductResponse();
            response.setSkuCode(stock.getSkuCode());
            response.setWarehouseId(stock.getWarehouseId());
            response.setQuantity(stock.getQuantity());
            response.setLockedQuantity(stock.getLockedQuantity());
            response.setAvailableQuantity(stock.getAvailableQuantity());

            // 标记幂等键已处理
            idempotencyService.markProcessed(idempotencyKey, response);

            log.info("扣减库存成功: skuCode={}, warehouseId={}, remaining={}",
                    stock.getSkuCode(), stock.getWarehouseId(), stock.getQuantity());

            return ApiResponse.success("库存扣减成功", response);
        } catch (Exception e) {
            log.error("扣减库存失败: skuCode={}, warehouseId={}, error={}",
                    request.getSkuCode(), request.getWarehouseId(), e.getMessage(), e);
            return ApiResponse.error(e.getMessage());
        }
    }

    /**
     * 解锁库存（订单驳回/取消时调用）
     * 对应PHP StockService::unlockStock
     * <p>
     * 幂等性保证：使用 skuCode + warehouseId + relatedNo 作为幂等键
     */
    @PostMapping("/unlock")
    public ApiResponse<StockLockResponse> unlockStock(@RequestBody StockUnlockRequest request) {
        try {
            String idempotencyKey = idempotencyService.buildUnlockKey(
                    request.getSkuCode(), request.getWarehouseId(), request.getRelatedNo());

            if (idempotencyService.isDuplicate(idempotencyKey)) {
                log.warn("[库存解锁] 重复解锁请求，已跳过: key={}", idempotencyKey);
                Object cached = idempotencyService.getProcessedResult(idempotencyKey);
                if (cached instanceof StockLockResponse) {
                    return ApiResponse.success("库存解锁成功（重复请求）", (StockLockResponse) cached);
                }
            }

            log.info("解锁库存请求: skuCode={}, warehouseId={}, quantity={}, orderId={}",
                    request.getSkuCode(), request.getWarehouseId(), request.getQuantity(), request.getRelatedNo());

            Stock stock = stockCheckService.unlockStock(
                    request.getSkuCode(),
                    request.getWarehouseId(),
                    request.getQuantity(),
                    parseOrderId(request.getRelatedNo())
            );

            StockLockResponse response = new StockLockResponse();
            response.setSkuCode(stock.getSkuCode());
            response.setWarehouseId(stock.getWarehouseId());
            response.setQuantity(stock.getQuantity());
            response.setLockedQuantity(stock.getLockedQuantity());
            response.setAvailableQuantity(stock.getAvailableQuantity());

            idempotencyService.markProcessed(idempotencyKey, response);

            log.info("解锁库存成功: skuCode={}, warehouseId={}, locked={}",
                    stock.getSkuCode(), stock.getWarehouseId(), stock.getLockedQuantity());

            return ApiResponse.success("库存解锁成功", response);
        } catch (Exception e) {
            log.error("解锁库存失败: skuCode={}, warehouseId={}, error={}",
                    request.getSkuCode(), request.getWarehouseId(), e.getMessage(), e);
            return ApiResponse.error(e.getMessage());
        }
    }

    /**
     * 锁定库存（订单创建/审核时预占库存）
     * 对应PHP StockService::lock
     * <p>
     * 幂等性保证：使用 skuCode + warehouseId + relatedNo 作为幂等键
     */
    @PostMapping("/lock")
    public ApiResponse<StockLockResponse> lockStock(@RequestBody StockLockRequest request) {
        try {
            String idempotencyKey = idempotencyService.buildLockKey(
                    request.getSkuCode(), request.getWarehouseId(), request.getRelatedNo());

            if (idempotencyService.isDuplicate(idempotencyKey)) {
                log.warn("[库存锁定] 重复锁定请求，已跳过: key={}", idempotencyKey);
                Object cached = idempotencyService.getProcessedResult(idempotencyKey);
                if (cached instanceof StockLockResponse) {
                    return ApiResponse.success("库存锁定成功（重复请求）", (StockLockResponse) cached);
                }
            }

            log.info("锁定库存请求: skuCode={}, warehouseId={}, quantity={}, orderId={}",
                    request.getSkuCode(), request.getWarehouseId(), request.getQuantity(), request.getRelatedNo());

            Stock stock = stockCheckService.lockStock(
                    request.getSkuCode(),
                    request.getWarehouseId(),
                    request.getQuantity(),
                    parseOrderId(request.getRelatedNo())
            );

            StockLockResponse response = new StockLockResponse();
            response.setSkuCode(stock.getSkuCode());
            response.setWarehouseId(stock.getWarehouseId());
            response.setQuantity(stock.getQuantity());
            response.setLockedQuantity(stock.getLockedQuantity());
            response.setAvailableQuantity(stock.getAvailableQuantity());

            idempotencyService.markProcessed(idempotencyKey, response);

            log.info("锁定库存成功: skuCode={}, warehouseId={}, locked={}",
                    stock.getSkuCode(), stock.getWarehouseId(), stock.getLockedQuantity());

            return ApiResponse.success("库存锁定成功", response);
        } catch (Exception e) {
            log.error("锁定库存失败: skuCode={}, warehouseId={}, error={}",
                    request.getSkuCode(), request.getWarehouseId(), e.getMessage(), e);
            return ApiResponse.error(e.getMessage());
        }
    }

    /**
     * 从relatedNo中解析orderId
     * relatedNo格式可能是 "ORDER_123" 或直接是 "123"
     */
    private Long parseOrderId(String relatedNo) {
        if (relatedNo == null || relatedNo.isEmpty()) {
            return null;
        }
        try {
            // 如果是 "ORDER_xxx" 格式，提取数字部分
            if (relatedNo.contains("_")) {
                String numStr = relatedNo.substring(relatedNo.lastIndexOf("_") + 1);
                return Long.parseLong(numStr);
            }
            return Long.parseLong(relatedNo);
        } catch (NumberFormatException e) {
            log.warn("无法解析orderId from relatedNo: {}", relatedNo);
            return null;
        }
    }

    // ==================== 请求/响应DTO ====================

    @lombok.Data
    public static class StockDeductRequest {
        private String skuCode;
        private Long warehouseId;
        private Integer quantity;
        private String relatedNo;
        private String remark;
    }

    @lombok.Data
    public static class StockUnlockRequest {
        private String skuCode;
        private Long warehouseId;
        private Integer quantity;
        private String relatedNo;
        private String remark;
    }

    @lombok.Data
    public static class StockLockRequest {
        private String skuCode;
        private Long warehouseId;
        private Integer quantity;
        private String relatedNo;
        private String remark;
    }

    @lombok.Data
    @lombok.NoArgsConstructor
    @lombok.AllArgsConstructor
    public static class StockDeductResponse {
        private String skuCode;
        private Long warehouseId;
        private Integer quantity;
        private Integer lockedQuantity;
        private Integer availableQuantity;
    }

    @lombok.Data
    @lombok.NoArgsConstructor
    @lombok.AllArgsConstructor
    public static class StockLockResponse {
        private String skuCode;
        private Long warehouseId;
        private Integer quantity;
        private Integer lockedQuantity;
        private Integer availableQuantity;
    }
}
