package com.erp.tenant.controller.finance;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.erp.common.core.model.ApiResponse;
import com.erp.common.core.model.PageResponse;
import com.erp.tenant.config.TenantContext;
import com.erp.tenant.dto.finance.FinancePageResponse;
import com.erp.tenant.dto.finance.FinancePageResponse.FinanceItemDTO;
import com.erp.tenant.entity.finance.FinanceRecord;
import com.erp.tenant.entity.finance.Reconciliation;
import com.erp.tenant.service.finance.FinanceService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.time.format.DateTimeFormatter;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 租户端财务控制器
 * 功能：收款/付款/对账
 */
@Slf4j
@RestController
@RequestMapping("/api/tenant/finance")
@RequiredArgsConstructor
public class FinanceController {

    private final FinanceService financeService;
    private static final DateTimeFormatter DT_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    /**
     * 财务记录列表（收款/付款）
     * GET /api/tenant/finance/records
     */
    @GetMapping("/records")
    public ApiResponse<PageResponse<FinanceItemDTO>> getFinanceList(
            @RequestParam(required = false) String type,
            @RequestParam(required = false) Integer status,
            @RequestParam(required = false) String startDate,
            @RequestParam(required = false) String endDate,
            @RequestParam(defaultValue = "1") Integer page,
            @RequestParam(defaultValue = "20") Integer pageSize) {

        Long tenantId = TenantContext.getCurrentTenantId();
        if (tenantId == null) {
            return ApiResponse.<PageResponse<FinanceItemDTO>>error(401, "未获取到租户信息");
        }

        IPage<FinanceRecord> recordPage = financeService.getFinancePage(
                tenantId, type, status, startDate, endDate, page, pageSize);

        var items = recordPage.getRecords().stream()
                .map(this::toFinanceItemDTO)
                .collect(Collectors.toList());

        FinancePageResponse.FinanceSummary summary = financeService.getFinanceSummary(tenantId, startDate, endDate);

        PageResponse<FinanceItemDTO> response = PageResponse.<FinanceItemDTO>builder()
                .list(items)
                .total(recordPage.getTotal())
                .page(recordPage.getCurrent())
                .pageSize(recordPage.getSize())
                .totalPages(recordPage.getPages())
                .build();

        return ApiResponse.success(response);
    }

    /**
     * 财务汇总
     * GET /api/tenant/finance/summary
     */
    @GetMapping("/summary")
    public ApiResponse<FinancePageResponse.FinanceSummary> getFinanceSummary(
            @RequestParam(required = false) String startDate,
            @RequestParam(required = false) String endDate) {

        Long tenantId = TenantContext.getCurrentTenantId();
        if (tenantId == null) {
            return ApiResponse.error(401, "未获取到租户信息");
        }

        FinancePageResponse.FinanceSummary summary = financeService.getFinanceSummary(tenantId, startDate, endDate);
        return ApiResponse.success(summary);
    }

    /**
     * 财务详情
     * GET /api/tenant/finance/records/{id}
     */
    @GetMapping("/records/{id}")
    public ApiResponse<FinanceItemDTO> getFinanceDetail(@PathVariable Long id) {
        Long tenantId = TenantContext.getCurrentTenantId();
        if (tenantId == null) {
            return ApiResponse.<FinanceItemDTO>error(401, "未获取到租户信息");
        }

        FinanceRecord record = financeService.getFinanceDetail(tenantId, id);
        if (record == null) {
            return ApiResponse.<FinanceItemDTO>error(404, "记录不存在");
        }
        return ApiResponse.success(toFinanceItemDTO(record));
    }

    /**
     * 确认收款/付款
     * POST /api/tenant/finance/records/{id}/confirm
     */
    @PostMapping("/records/{id}/confirm")
    public ApiResponse<?> confirmRecord(@PathVariable Long id,
                                        @RequestBody(required = false) Map<String, String> body) {
        Long tenantId = TenantContext.getCurrentTenantId();
        Long operatorId = 0L;
        String remark = body != null ? body.get("remark") : null;

        boolean success = financeService.confirmRecord(tenantId, id, operatorId, remark);
        if (!success) {
            return ApiResponse.error(400, "确认失败");
        }
        return ApiResponse.success("确认成功", null);
    }

    /**
     * 取消记录
     * POST /api/tenant/finance/records/{id}/cancel
     */
    @PostMapping("/records/{id}/cancel")
    public ApiResponse<?> cancelRecord(@PathVariable Long id,
                                        @RequestBody(required = false) Map<String, String> body) {
        Long tenantId = TenantContext.getCurrentTenantId();
        Long operatorId = 0L;
        String remark = body != null ? body.get("remark") : null;

        boolean success = financeService.cancelRecord(tenantId, id, operatorId, remark);
        if (!success) {
            return ApiResponse.error(400, "取消失败");
        }
        return ApiResponse.success("取消成功", null);
    }

    /**
     * 对账单列表
     * GET /api/tenant/finance/reconciliations
     */
    @GetMapping("/reconciliations")
    public ApiResponse<PageResponse<Map<String, Object>>> getReconciliationList(
            @RequestParam(required = false) Integer status,
            @RequestParam(required = false) String keyword,
            @RequestParam(defaultValue = "1") Integer page,
            @RequestParam(defaultValue = "20") Integer pageSize) {

        Long tenantId = TenantContext.getCurrentTenantId();
        if (tenantId == null) {
            return ApiResponse.<PageResponse<Map<String, Object>>>error(401, "未获取到租户信息");
        }

        IPage<Reconciliation> page_ = financeService.getReconciliationPage(
                tenantId, status, keyword, page, pageSize);

        var items = page_.getRecords().stream().map(r -> {
            java.util.HashMap<String, Object> m = new java.util.HashMap<>();
            m.put("id", r.getId());
            m.put("reconcileNo", r.getReconcileNo() != null ? r.getReconcileNo() : "");
            m.put("counterpartyName", r.getCounterpartyName() != null ? r.getCounterpartyName() : "");
            m.put("periodStart", r.getPeriodStart() != null ? r.getPeriodStart().format(DT_FORMAT) : "");
            m.put("periodEnd", r.getPeriodEnd() != null ? r.getPeriodEnd().format(DT_FORMAT) : "");
            m.put("ourAmount", r.getOurAmount() != null ? r.getOurAmount() : BigDecimal.ZERO);
            m.put("counterpartyAmount", r.getCounterpartyAmount() != null ? r.getCounterpartyAmount() : BigDecimal.ZERO);
            m.put("diffAmount", r.getDiffAmount() != null ? r.getDiffAmount() : BigDecimal.ZERO);
            m.put("status", r.getStatus() != null ? r.getStatus() : 0);
            m.put("statusText", r.getStatusText() != null ? r.getStatusText() : "");
            m.put("remark", r.getRemark() != null ? r.getRemark() : "");
            return m;
        }).collect(Collectors.<Map<String, Object>>toList());

        PageResponse<Map<String, Object>> response = PageResponse.<Map<String, Object>>builder()
                .list(items)
                .total(page_.getTotal())
                .page(page_.getCurrent())
                .pageSize(page_.getSize())
                .totalPages(page_.getPages())
                .build();

        return ApiResponse.success(response);
    }

    private FinanceItemDTO toFinanceItemDTO(FinanceRecord record) {
        return FinanceItemDTO.builder()
                .id(record.getId())
                .recordNo(record.getRecordNo() != null ? record.getRecordNo() : "")
                .type(record.getType() != null ? record.getType() : "")
                .typeText(record.getTypeText() != null ? record.getTypeText() : "")
                .sourceType(record.getSourceType() != null ? record.getSourceType() : "")
                .sourceNo(record.getSourceNo() != null ? record.getSourceNo() : "")
                .amount(record.getAmount() != null ? record.getAmount() : BigDecimal.ZERO)
                .verifiedAmount(record.getVerifiedAmount() != null ? record.getVerifiedAmount() : BigDecimal.ZERO)
                .discountAmount(record.getDiscountAmount() != null ? record.getDiscountAmount() : BigDecimal.ZERO)
                .counterpartyName(record.getCounterpartyName() != null ? record.getCounterpartyName() : "")
                .paymentMethod(record.getPaymentMethod() != null ? record.getPaymentMethod() : "")
                .paymentSerial(record.getPaymentSerial() != null ? record.getPaymentSerial() : "")
                .paymentTime(record.getPaymentTime() != null ? record.getPaymentTime().format(DT_FORMAT) : null)
                .status(record.getStatus() != null ? record.getStatus() : 0)
                .statusText(record.getStatusText() != null ? record.getStatusText() : "")
                .summary(record.getSummary() != null ? record.getSummary() : "")
                .remark(record.getRemark() != null ? record.getRemark() : "")
                .createdAt(record.getCreatedAt() != null ? record.getCreatedAt().format(DT_FORMAT) : null)
                .build();
    }
}
