package com.erp.finance.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.erp.finance.dto.*;
import com.erp.finance.entity.AccountsPayable;
import com.erp.finance.entity.PaymentRecord;
import com.erp.finance.service.AccountsPayableService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.*;

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

/**
 * 应付账款API（采购付款）
 */
@Slf4j
@RestController
@RequestMapping("/api/finance/ap")
@RequiredArgsConstructor
public class AccountsPayableController {

    private final AccountsPayableService apService;

    // ========== 应付账款 ==========

    /**
     * 创建应付账款（采购订单审核通过后调用）
     */
    @PostMapping("/create")
    public FinanceApiResponse<AccountsPayableResponse> create(@RequestBody AccountsPayableService.AccountsPayableCreateRequest request) {
        try {
            log.info("[API] 创建应付账款 purchaseOrderNo={}, amount={}", request.getPurchaseOrderNo(), request.getAmount());
            AccountsPayable ap = apService.create(request);
            return FinanceApiResponse.success(toApResponse(ap));
        } catch (Exception e) {
            log.error("[API] 创建应付账款失败 purchaseOrderNo={}", request.getPurchaseOrderNo(), e);
            return FinanceApiResponse.error(500, "创建应付账款失败: " + e.getMessage());
        }
    }

    /**
     * 取消应付账款（采购订单取消后调用）
     */
    @PutMapping("/{purchaseOrderNo}/cancel")
    public FinanceApiResponse<?> cancel(@PathVariable String purchaseOrderNo) {
        try {
            apService.cancel(purchaseOrderNo);
            return FinanceApiResponse.success("取消成功");
        } catch (Exception e) {
            log.error("[API] 取消应付账款失败 purchaseOrderNo={}", purchaseOrderNo, e);
            return FinanceApiResponse.error(500, e.getMessage());
        }
    }

    /**
     * 更新入库状态（采购入库完成后调用）
     */
    @PutMapping("/{purchaseOrderNo}/inbound")
    public FinanceApiResponse<?> updateInboundStatus(
            @PathVariable String purchaseOrderNo,
            @RequestParam String inboundNo,
            @RequestParam BigDecimal inboundAmount,
            @RequestParam(required = false, defaultValue = "confirm") String action) {
        try {
            apService.updateInboundStatus(purchaseOrderNo, inboundNo, inboundAmount, action);
            return FinanceApiResponse.success("入库状态更新成功");
        } catch (Exception e) {
            log.error("[API] 更新入库状态失败 purchaseOrderNo={}", purchaseOrderNo, e);
            return FinanceApiResponse.error(500, e.getMessage());
        }
    }

    /**
     * 确认付款（采购付款）
     */
    @PostMapping("/payment/confirm")
    public FinanceApiResponse<PaymentRecordResponse> confirmPayment(@RequestBody AccountsPayableService.PaymentConfirmRequest request) {
        try {
            log.info("[API] 确认付款 apNo={}, amount={}", request.getApNo(), request.getAmount());
            PaymentRecord payment = apService.confirmPayment(request);
            return FinanceApiResponse.success(toPaymentResponse(payment));
        } catch (Exception e) {
            log.error("[API] 确认付款失败 apNo={}", request.getApNo(), e);
            return FinanceApiResponse.error(500, e.getMessage());
        }
    }

    /**
     * 分页查询应付账款
     */
    @GetMapping("/page")
    public FinanceApiResponse<PageResponse<AccountsPayableResponse>> queryPage(
            @RequestParam(required = false) String apNo,
            @RequestParam(required = false) String purchaseOrderNo,
            @RequestParam(required = false) Long supplierId,
            @RequestParam(required = false) String status,
            @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") String startDate,
            @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") String endDate,
            @RequestParam(defaultValue = "1") Integer page,
            @RequestParam(defaultValue = "20") Integer pageSize) {
        AccountsPayableQueryRequest request = new AccountsPayableQueryRequest();
        request.setApNo(apNo);
        request.setPurchaseOrderNo(purchaseOrderNo);
        request.setSupplierId(supplierId);
        request.setStatus(status);
        request.setStartDate(startDate);
        request.setEndDate(endDate);
        request.setPage(page);
        request.setPageSize(pageSize);

        IPage<AccountsPayable> result = apService.query(request);
        return FinanceApiResponse.success(PageResponse.of(
                result.getTotal(),
                (int) result.getCurrent(),
                (int) result.getSize(),
                result.getRecords().stream().map(AccountsPayableController::toApResponse).toList()
        ));
    }

    /**
     * 根据应付单号查询
     */
    @GetMapping("/{apNo}")
    public FinanceApiResponse<AccountsPayableResponse> getByApNo(@PathVariable String apNo) {
        AccountsPayable ap = apService.getByApNo(apNo);
        if (ap == null) {
            return FinanceApiResponse.notFound("应付账款不存在");
        }
        return FinanceApiResponse.success(toApResponse(ap));
    }

    /**
     * 根据采购单号查询应付账款
     */
    @GetMapping("/po/{purchaseOrderNo}")
    public FinanceApiResponse<AccountsPayableResponse> getByPurchaseOrderNo(@PathVariable String purchaseOrderNo) {
        AccountsPayable ap = apService.getByPurchaseOrderNo(purchaseOrderNo);
        if (ap == null) {
            return FinanceApiResponse.notFound("应付账款不存在");
        }
        return FinanceApiResponse.success(toApResponse(ap));
    }

    /**
     * 获取未付款总额和逾期总额
     */
    @GetMapping("/stats")
    public FinanceApiResponse<Map<String, BigDecimal>> getStats() {
        BigDecimal unpaid = apService.getTotalUnpaid();
        BigDecimal overdue = apService.getOverdueAmount(LocalDate.now());
        return FinanceApiResponse.success(Map.of("totalUnpaid", unpaid, "overdueAmount", overdue));
    }

    private static AccountsPayableResponse toApResponse(AccountsPayable ap) {
        return AccountsPayableResponse.builder()
                .id(ap.getId())
                .apNo(ap.getApNo())
                .purchaseOrderNo(ap.getPurchaseOrderNo())
                .purchaseOrderId(ap.getPurchaseOrderId())
                .supplierId(ap.getSupplierId())
                .supplierName(ap.getSupplierName())
                .totalAmount(ap.getTotalAmount())
                .inboundAmount(ap.getInboundAmount())
                .paidAmount(ap.getPaidAmount())
                .unpaidAmount(ap.getUnpaidAmount())
                .currency(ap.getCurrency())
                .paymentMethod(ap.getPaymentMethod())
                .dueDate(ap.getDueDate())
                .paidDate(ap.getPaidDate())
                .status(ap.getStatus())
                .inboundStatus(ap.getInboundStatus())
                .remark(ap.getRemark())
                .createTime(ap.getCreateTime())
                .build();
    }

    private static PaymentRecordResponse toPaymentResponse(PaymentRecord p) {
        return PaymentRecordResponse.builder()
                .id(p.getId())
                .paymentNo(p.getPaymentNo())
                .apNo(p.getApNo())
                .apId(p.getApId())
                .purchaseOrderNo(p.getPurchaseOrderNo())
                .supplierId(p.getSupplierId())
                .supplierName(p.getSupplierName())
                .amount(p.getAmount())
                .paymentMethod(p.getPaymentMethod())
                .fromAccount(p.getFromAccount())
                .toAccount(p.getToAccount())
                .paymentTime(p.getPaymentTime())
                .bankFlowNo(p.getBankFlowNo())
                .status(p.getStatus())
                .purpose(p.getPurpose())
                .relatedId(p.getRelatedId())
                .relatedType(p.getRelatedType())
                .operator(p.getOperator())
                .remark(p.getRemark())
                .createTime(p.getCreateTime())
                .build();
    }
}
