package com.erp.reconciliation.controller;

import com.erp.reconciliation.dto.*;
import com.erp.reconciliation.entity.ReconciliationBill;
import com.erp.reconciliation.entity.ReconciliationDifference;
import com.erp.reconciliation.entity.ReconciliationTask;
import com.erp.reconciliation.service.ReconciliationService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;
import com.erp.common.core.model.PageResponse;
import java.util.Map;
import com.erp.common.core.model.ApiResponse;

/**
 * 对账管理控制器
 * 提供对账相关的RESTful API
 * 
 * @author ERP Migration
 */
@Slf4j
@RestController
@RequestMapping("/api/reconciliation")
@RequiredArgsConstructor
@CrossOrigin(origins = "*")
public class ReconciliationController {

    private final ReconciliationService reconciliationService;

    // ==================== 对账账单管理（CRUD） ====================

    /**
     * 获取对账单详情
     */
    @GetMapping("/bill/{id}")
    public ResponseEntity<ApiResponse<ReconciliationBillDTO>> getBillById(@PathVariable Long id) {
        ReconciliationBill bill = reconciliationService.getBillById(id);
        if (bill == null) {
            return ResponseEntity.status(404)
                    .body(ApiResponse.notFound("对账单不存在"));
        }
        return ResponseEntity.ok(ApiResponse.success(toBillDTO(bill)));
    }

    /**
     * 根据对账单号查询
     */
    @GetMapping("/bill/no/{billNo}")
    public ResponseEntity<ApiResponse<ReconciliationBillDTO>> getBillByBillNo(@PathVariable String billNo) {
        ReconciliationBill bill = reconciliationService.getBillByBillNo(billNo);
        if (bill == null) {
            return ResponseEntity.status(404)
                    .body(ApiResponse.notFound("对账单不存在"));
        }
        return ResponseEntity.ok(ApiResponse.success(toBillDTO(bill)));
    }

    /**
     * 分页查询对账单
     */
    @GetMapping("/bill/list")
    public ResponseEntity<ApiResponse<PageResponse<ReconciliationBillDTO>>> queryBills(
            @RequestParam(required = false) String billNo,
            @RequestParam(required = false) String platform,
            @RequestParam(required = false) Long shopId,
            @RequestParam(required = false) String reconciliationStatus,
            @RequestParam(required = false) String resultStatus,
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate,
            @RequestParam(defaultValue = "1") Integer pageNum,
            @RequestParam(defaultValue = "10") Integer pageSize) {

        ReconciliationQueryRequest request = ReconciliationQueryRequest.builder()
                .billNo(billNo)
                .platform(platform)
                .shopId(shopId)
                .reconciliationStatus(reconciliationStatus)
                .resultStatus(resultStatus)
                .startDate(startDate)
                .endDate(endDate)
                .pageNum(pageNum)
                .pageSize(pageSize)
                .build();

        PageResponse<ReconciliationBillDTO> result = reconciliationService.queryBills(request);
        return ResponseEntity.ok(ApiResponse.success(result));
    }

    /**
     * 创建对账单
     */
    @PostMapping("/bill")
    public ResponseEntity<ApiResponse<ReconciliationBillDTO>> createBill(@RequestBody Map<String, Object> request) {
        ReconciliationBill bill = mapToBill(request);
        ReconciliationBill created = reconciliationService.createBill(bill);
        return ResponseEntity.ok(ApiResponse.success("对账单创建成功", toBillDTO(created)));
    }

    /**
     * 更新对账单
     */
    @PutMapping("/bill/{id}")
    public ResponseEntity<ApiResponse<ReconciliationBillDTO>> updateBill(
            @PathVariable Long id,
            @RequestBody Map<String, Object> request) {
        ReconciliationBill existing = reconciliationService.getBillById(id);
        if (existing == null) {
            return ResponseEntity.status(404)
                    .body(ApiResponse.notFound("对账单不存在"));
        }

        ReconciliationBill bill = mapToBill(request);
        bill.setId(id);
        ReconciliationBill updated = reconciliationService.updateBill(bill);
        return ResponseEntity.ok(ApiResponse.success("对账单更新成功", toBillDTO(updated)));
    }

    /**
     * 删除对账单
     */
    @DeleteMapping("/bill/{id}")
    public ResponseEntity<ApiResponse<Void>> deleteBill(@PathVariable Long id) {
        try {
            reconciliationService.deleteBill(id);
            return ResponseEntity.ok(ApiResponse.success("对账单删除成功", null));
        } catch (IllegalArgumentException e) {
            return ResponseEntity.status(404)
                    .body(ApiResponse.notFound(e.getMessage()));
        }
    }

    /**
     * 确认对账单
     */
    @PostMapping("/bill/{id}/confirm")
    public ResponseEntity<ApiResponse<Void>> confirmBill(
            @PathVariable Long id,
            @RequestBody Map<String, Object> request) {
        Long userId = request.get("userId") != null ? Long.parseLong(request.get("userId").toString()) : null;
        String userName = (String) request.get("userName");

        try {
            reconciliationService.confirmBill(id, userId, userName);
            return ResponseEntity.ok(ApiResponse.success("对账单已确认", null));
        } catch (IllegalArgumentException e) {
            return ResponseEntity.status(404)
                    .body(ApiResponse.notFound(e.getMessage()));
        } catch (IllegalStateException e) {
            return ResponseEntity.badRequest()
                    .body(ApiResponse.badRequest(e.getMessage()));
        }
    }

    // ==================== 执行对账核对 ====================

    /**
     * 执行对账核对
     */
    @PostMapping("/bill/{id}/reconcile")
    public ResponseEntity<ApiResponse<ReconciliationBillDTO>> performReconciliation(@PathVariable Long id) {
        try {
            ReconciliationBill bill = reconciliationService.performReconciliation(id);
            return ResponseEntity.ok(ApiResponse.success("对账执行完成", toBillDTO(bill)));
        } catch (IllegalArgumentException e) {
            return ResponseEntity.status(404)
                    .body(ApiResponse.notFound(e.getMessage()));
        } catch (Exception e) {
            return ResponseEntity.badRequest()
                    .body(ApiResponse.badRequest(e.getMessage()));
        }
    }

    /**
     * 批量执行对账
     */
    @PostMapping("/bill/reconcile/batch")
    public ResponseEntity<ApiResponse<Map<String, Object>>> batchReconciliation(
            @RequestBody Map<String, Object> request) {
        @SuppressWarnings("unchecked")
        List<Long> billIds = (List<Long>) request.get("billIds");

        if (billIds == null || billIds.isEmpty()) {
            return ResponseEntity.badRequest()
                    .body(ApiResponse.badRequest("请选择要对账的账单"));
        }

        List<ReconciliationBill> results = reconciliationService.batchReconciliation(billIds);
        return ResponseEntity.ok(ApiResponse.success("批量对账完成",
                Map.of("total", billIds.size(), "success", results.size(), "results", results)));
    }

    /**
     * 创建并执行对账
     */
    @PostMapping("/bill/create-and-reconcile")
    public ResponseEntity<ApiResponse<ReconciliationBillDTO>> createAndReconcile(
            @RequestBody Map<String, Object> request) {
        String platform = (String) request.get("platform");
        Long shopId = request.get("shopId") != null ? Long.parseLong(request.get("shopId").toString()) : null;
        String periodType = (String) request.get("periodType");
        LocalDate periodStart = request.get("periodStart") != null
                ? LocalDate.parse(request.get("periodStart").toString()) : null;
        LocalDate periodEnd = request.get("periodEnd") != null
                ? LocalDate.parse(request.get("periodEnd").toString()) : null;

        ReconciliationBill bill = reconciliationService.createAndReconcile(
                platform, shopId, periodType, periodStart, periodEnd);
        return ResponseEntity.ok(ApiResponse.success("对账执行完成", toBillDTO(bill)));
    }

    // ==================== 一致性检查 ====================

    /**
     * 订单金额一致性检查
     */
    @GetMapping("/check/order-amount")
    public ResponseEntity<ApiResponse<List<Map<String, Object>>>> checkOrderAmountConsistency(
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate) {
        List<Map<String, Object>> issues = reconciliationService.checkOrderAmountConsistency(startDate, endDate);
        return ResponseEntity.ok(ApiResponse.success(issues));
    }

    /**
     * 订单-库存一致性检查
     */
    @GetMapping("/check/order-stock")
    public ResponseEntity<ApiResponse<List<Map<String, Object>>>> checkOrderStockConsistency() {
        List<Map<String, Object>> issues = reconciliationService.checkOrderStockConsistency();
        return ResponseEntity.ok(ApiResponse.success(issues));
    }

    /**
     * 运单-物流轨迹一致性检查
     */
    @GetMapping("/check/waybill")
    public ResponseEntity<ApiResponse<List<Map<String, Object>>>> checkWaybillConsistency() {
        List<Map<String, Object>> issues = reconciliationService.checkWaybillConsistency();
        return ResponseEntity.ok(ApiResponse.success(issues));
    }

    /**
     * 执行全面一致性检查
     */
    @GetMapping("/check/full")
    public ResponseEntity<ApiResponse<Map<String, Object>>> fullConsistencyCheck() {
        Map<String, Object> results = reconciliationService.fullConsistencyCheck();
        return ResponseEntity.ok(ApiResponse.success(results));
    }

    // ==================== 差异处理 ====================

    /**
     * 分页查询差异记录
     */
    @GetMapping("/difference/list")
    public ResponseEntity<ApiResponse<PageResponse<ReconciliationDifferenceDTO>>> queryDifferences(
            @RequestParam(required = false) Long billId,
            @RequestParam(required = false) String billNo,
            @RequestParam(required = false) String differenceType,
            @RequestParam(required = false) String handleStatus,
            @RequestParam(required = false) String platform,
            @RequestParam(required = false) Long shopId,
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate,
            @RequestParam(defaultValue = "1") Integer pageNum,
            @RequestParam(defaultValue = "10") Integer pageSize) {

        ReconciliationQueryRequest request = ReconciliationQueryRequest.builder()
                .billId(billId)
                .billNo(billNo)
                .differenceType(differenceType)
                .handleStatus(handleStatus)
                .platform(platform)
                .shopId(shopId)
                .startDate(startDate)
                .endDate(endDate)
                .pageNum(pageNum)
                .pageSize(pageSize)
                .build();

        PageResponse<ReconciliationDifferenceDTO> result = reconciliationService.queryDifferences(request);
        return ResponseEntity.ok(ApiResponse.success(result));
    }

    /**
     * 获取差异详情
     */
    @GetMapping("/difference/{id}")
    public ResponseEntity<ApiResponse<ReconciliationDifferenceDTO>> getDifferenceById(@PathVariable Long id) {
        ReconciliationDifference diff = reconciliationService.getDifferenceById(id);
        if (diff == null) {
            return ResponseEntity.status(404)
                    .body(ApiResponse.notFound("差异记录不存在"));
        }
        return ResponseEntity.ok(ApiResponse.success(toDifferenceDTO(diff)));
    }

    /**
     * 处理差异
     */
    @PostMapping("/difference/{id}/handle")
    public ResponseEntity<ApiResponse<Void>> handleDifference(
            @PathVariable Long id,
            @RequestBody Map<String, Object> request) {
        String handleMethod = (String) request.get("handleMethod");
        String handleRemark = (String) request.get("handleRemark");
        Long userId = request.get("userId") != null ? Long.parseLong(request.get("userId").toString()) : null;
        String userName = (String) request.get("userName");

        try {
            reconciliationService.handleDifference(id, handleMethod, handleRemark, userId, userName);
            return ResponseEntity.ok(ApiResponse.success("差异处理成功", null));
        } catch (IllegalArgumentException e) {
            return ResponseEntity.status(404)
                    .body(ApiResponse.notFound(e.getMessage()));
        }
    }

    /**
     * 批量处理差异
     */
    @PostMapping("/difference/handle/batch")
    public ResponseEntity<ApiResponse<Map<String, Object>>> batchHandleDifferences(
            @RequestBody Map<String, Object> request) {
        @SuppressWarnings("unchecked")
        List<Long> ids = (List<Long>) request.get("ids");
        String handleMethod = (String) request.get("handleMethod");
        String handleRemark = (String) request.get("handleRemark");
        Long userId = request.get("userId") != null ? Long.parseLong(request.get("userId").toString()) : null;
        String userName = (String) request.get("userName");

        if (ids == null || ids.isEmpty()) {
            return ResponseEntity.badRequest()
                    .body(ApiResponse.badRequest("请选择要处理的差异"));
        }

        int count = reconciliationService.batchHandleDifferences(ids, handleMethod, handleRemark, userId, userName);
        return ResponseEntity.ok(ApiResponse.success("批量处理完成",
                Map.of("total", ids.size(), "success", count)));
    }

    /**
     * 获取待处理差异统计
     */
    @GetMapping("/difference/pending-stats")
    public ResponseEntity<ApiResponse<Map<String, Long>>> getPendingDifferenceStats() {
        Map<String, Long> stats = reconciliationService.getPendingDifferenceStats();
        return ResponseEntity.ok(ApiResponse.success(stats));
    }

    // ==================== 对账任务 ====================

    /**
     * 分页查询对账任务
     */
    @GetMapping("/task/list")
    public ResponseEntity<ApiResponse<PageResponse<ReconciliationTaskDTO>>> queryTasks(
            @RequestParam(required = false) String taskType,
            @RequestParam(required = false) String taskStatus,
            @RequestParam(required = false) String platform,
            @RequestParam(required = false) Long shopId,
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate,
            @RequestParam(defaultValue = "1") Integer pageNum,
            @RequestParam(defaultValue = "10") Integer pageSize) {

        ReconciliationQueryRequest request = ReconciliationQueryRequest.builder()
                .taskType(taskType)
                .taskStatus(taskStatus)
                .platform(platform)
                .shopId(shopId)
                .startDate(startDate)
                .endDate(endDate)
                .pageNum(pageNum)
                .pageSize(pageSize)
                .build();

        PageResponse<ReconciliationTaskDTO> result = reconciliationService.queryTasks(request);
        return ResponseEntity.ok(ApiResponse.success(result));
    }

    /**
     * 获取任务详情
     */
    @GetMapping("/task/{id}")
    public ResponseEntity<ApiResponse<ReconciliationTaskDTO>> getTaskById(@PathVariable Long id) {
        ReconciliationTask task = reconciliationService.getTaskById(id);
        if (task == null) {
            return ResponseEntity.status(404)
                    .body(ApiResponse.notFound("任务不存在"));
        }
        return ResponseEntity.ok(ApiResponse.success(toTaskDTO(task)));
    }

    /**
     * 取消任务
     */
    @PostMapping("/task/{id}/cancel")
    public ResponseEntity<ApiResponse<Void>> cancelTask(@PathVariable Long id) {
        try {
            reconciliationService.cancelTask(id);
            return ResponseEntity.ok(ApiResponse.success("任务已取消", null));
        } catch (IllegalArgumentException e) {
            return ResponseEntity.status(404)
                    .body(ApiResponse.notFound(e.getMessage()));
        } catch (IllegalStateException e) {
            return ResponseEntity.badRequest()
                    .body(ApiResponse.badRequest(e.getMessage()));
        }
    }

    // ==================== 统计报表 ====================

    /**
     * 获取对账统计数据
     */
    @GetMapping("/statistics")
    public ResponseEntity<ApiResponse<ReconciliationStatisticsDTO>> getStatistics(
            @RequestParam(required = false) String platform,
            @RequestParam(required = false) Long shopId,
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate) {

        ReconciliationQueryRequest request = ReconciliationQueryRequest.builder()
                .platform(platform)
                .shopId(shopId)
                .startDate(startDate)
                .endDate(endDate)
                .build();

        ReconciliationStatisticsDTO stats = reconciliationService.getStatistics(request);
        return ResponseEntity.ok(ApiResponse.success(stats));
    }

    /**
     * 获取平台维度统计
     */
    @GetMapping("/statistics/platform/{platform}")
    public ResponseEntity<ApiResponse<ReconciliationStatisticsDTO.PlatformStatistics>> getPlatformStatistics(
            @PathVariable String platform,
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate) {

        ReconciliationStatisticsDTO.PlatformStatistics stats = 
                reconciliationService.getPlatformStatistics(platform, startDate, endDate);
        return ResponseEntity.ok(ApiResponse.success(stats));
    }

    /**
     * 获取店铺维度统计
     */
    @GetMapping("/statistics/shop/{shopId}")
    public ResponseEntity<ApiResponse<ReconciliationStatisticsDTO.ShopStatistics>> getShopStatistics(
            @PathVariable Long shopId,
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate) {

        ReconciliationStatisticsDTO.ShopStatistics stats = 
                reconciliationService.getShopStatistics(shopId, startDate, endDate);
        return ResponseEntity.ok(ApiResponse.success(stats));
    }

    /**
     * 获取差异趋势
     */
    @GetMapping("/statistics/difference-trend")
    public ResponseEntity<ApiResponse<List<Map<String, Object>>>> getDifferenceTrend(
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate) {

        List<Map<String, Object>> trend = reconciliationService.getDifferenceTrend(startDate, endDate);
        return ResponseEntity.ok(ApiResponse.success(trend));
    }

    // ==================== 辅助方法 ====================

    private ReconciliationBillDTO toBillDTO(ReconciliationBill bill) {
        if (bill == null) return null;
        
        BigDecimal matchRate = BigDecimal.ZERO;
        if (bill.getPlatformOrderCount() != null && bill.getPlatformOrderCount() > 0 && bill.getMatchedCount() != null) {
            matchRate = BigDecimal.valueOf(bill.getMatchedCount())
                    .divide(BigDecimal.valueOf(bill.getPlatformOrderCount()), 4, BigDecimal.ROUND_HALF_UP)
                    .multiply(BigDecimal.valueOf(100));
        }
        
        return ReconciliationBillDTO.builder()
                .id(bill.getId())
                .billNo(bill.getBillNo())
                .batchNo(bill.getBatchNo())
                .platform(bill.getPlatform())
                .shopId(bill.getShopId())
                .shopName(bill.getShopName())
                .periodType(bill.getPeriodType())
                .periodStart(bill.getPeriodStart())
                .periodEnd(bill.getPeriodEnd())
                .platformOrderCount(bill.getPlatformOrderCount())
                .platformTotalAmount(bill.getPlatformTotalAmount())
                .internalOrderCount(bill.getInternalOrderCount())
                .internalTotalAmount(bill.getInternalTotalAmount())
                .differenceAmount(bill.getDifferenceAmount())
                .matchedCount(bill.getMatchedCount())
                .matchedAmount(bill.getMatchedAmount())
                .differenceCount(bill.getDifferenceCount())
                .reconciliationStatus(bill.getReconciliationStatus())
                .resultStatus(bill.getResultStatus())
                .reconciliationStartTime(bill.getReconciliationStartTime())
                .reconciliationEndTime(bill.getReconciliationEndTime())
                .confirmTime(bill.getConfirmTime())
                .confirmUserId(bill.getConfirmUserId())
                .confirmUserName(bill.getConfirmUserName())
                .matchRate(matchRate)
                .remark(bill.getRemark())
                .createdAt(bill.getCreatedAt())
                .updatedAt(bill.getUpdatedAt())
                .build();
    }

    private ReconciliationDifferenceDTO toDifferenceDTO(ReconciliationDifference diff) {
        if (diff == null) return null;
        
        return ReconciliationDifferenceDTO.builder()
                .id(diff.getId())
                .billId(diff.getBillId())
                .billNo(diff.getBillNo())
                .differenceType(diff.getDifferenceType())
                .platformOrderSn(diff.getPlatformOrderSn())
                .internalOrderId(diff.getInternalOrderId())
                .internalOrderSn(diff.getInternalOrderSn())
                .platformOrderAmount(diff.getPlatformOrderAmount())
                .internalOrderAmount(diff.getInternalOrderAmount())
                .differenceAmount(diff.getDifferenceAmount())
                .platformOrderStatus(diff.getPlatformOrderStatus())
                .internalOrderStatus(diff.getInternalOrderStatus())
                .differenceReason(diff.getDifferenceReason())
                .handleStatus(diff.getHandleStatus())
                .handleMethod(diff.getHandleMethod())
                .handleUserId(diff.getHandleUserId())
                .handleUserName(diff.getHandleUserName())
                .handleTime(diff.getHandleTime())
                .handleRemark(diff.getHandleRemark())
                .remark(diff.getRemark())
                .createdAt(diff.getCreatedAt())
                .updatedAt(diff.getUpdatedAt())
                .build();
    }

    private ReconciliationTaskDTO toTaskDTO(ReconciliationTask task) {
        if (task == null) return null;
        
        return ReconciliationTaskDTO.builder()
                .id(task.getId())
                .taskNo(task.getTaskNo())
                .taskType(task.getTaskType())
                .billId(task.getBillId())
                .billNo(task.getBillNo())
                .platform(task.getPlatform())
                .shopId(task.getShopId())
                .shopName(task.getShopName())
                .taskStatus(task.getTaskStatus())
                .progress(task.getProgress())
                .currentStep(task.getCurrentStep())
                .startTime(task.getStartTime())
                .endTime(task.getEndTime())
                .durationSeconds(task.getDurationSeconds())
                .resultMessage(task.getResultMessage())
                .errorDetail(task.getErrorDetail())
                .triggerUserId(task.getTriggerUserId())
                .triggerUserName(task.getTriggerUserName())
                .remark(task.getRemark())
                .createdAt(task.getCreatedAt())
                .build();
    }

    private ReconciliationBill mapToBill(Map<String, Object> request) {
        return ReconciliationBill.builder()
                .billNo((String) request.get("billNo"))
                .batchNo((String) request.get("batchNo"))
                .platform((String) request.get("platform"))
                .shopId(request.get("shopId") != null ? Long.parseLong(request.get("shopId").toString()) : null)
                .shopName((String) request.get("shopName"))
                .periodType((String) request.get("periodType"))
                .periodStart(request.get("periodStart") != null ? 
                        LocalDate.parse(request.get("periodStart").toString()).atStartOfDay() : null)
                .periodEnd(request.get("periodEnd") != null ? 
                        LocalDate.parse(request.get("periodEnd").toString()).atTime(23, 59, 59) : null)
                .reconciliationStatus((String) request.get("reconciliationStatus"))
                .resultStatus((String) request.get("resultStatus"))
                .remark((String) request.get("remark"))
                .build();
    }
}
