package com.gpf.pethospital.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.gpf.pethospital.common.ApiResponse;
import com.gpf.pethospital.entity.Appointment;
import com.gpf.pethospital.entity.Order;
import com.gpf.pethospital.entity.Pet;
import com.gpf.pethospital.entity.PrescriptionItem;
import com.gpf.pethospital.entity.User;
import com.gpf.pethospital.entity.Visit;
import com.gpf.pethospital.service.AppointmentService;
import com.gpf.pethospital.service.DrugService;
import com.gpf.pethospital.service.OrderService;
import com.gpf.pethospital.service.PetService;
import com.gpf.pethospital.service.PrescriptionItemService;
import com.gpf.pethospital.service.UserService;
import com.gpf.pethospital.service.VisitService;
// import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.Map;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/admin/stats")
public class StatsController {
    private final OrderService orderService;
    private final AppointmentService appointmentService;
    private final VisitService visitService;
    private final PetService petService;
    private final UserService userService;
    private final DrugService drugService;
    private final PrescriptionItemService prescriptionItemService;

    public StatsController(OrderService orderService,
                           AppointmentService appointmentService,
                           VisitService visitService,
                           PetService petService,
                           UserService userService,
                           DrugService drugService,
                           PrescriptionItemService prescriptionItemService) {
        this.orderService = orderService;
        this.appointmentService = appointmentService;
        this.visitService = visitService;
        this.petService = petService;
        this.userService = userService;
        this.drugService = drugService;
        this.prescriptionItemService = prescriptionItemService;
    }

    // @PreAuthorize("hasRole('ADMIN')")
    @GetMapping
    public ApiResponse<?> summary() {
        Map<String, Object> data = new HashMap<>();
        
        // 今日预约数
        LocalDate today = LocalDate.now();
        long todayAppointments = appointmentService.count(
            new LambdaQueryWrapper<Appointment>()
                .eq(Appointment::getAppointmentDate, today)
                .ne(Appointment::getStatus, "CANCELLED")
        );
        data.put("appointments", todayAppointments);
        
        // 今日待就诊数（预约状态为 CONFIRMED 的今日预约）
        long pendingVisits = appointmentService.count(
            new LambdaQueryWrapper<Appointment>()
                .eq(Appointment::getAppointmentDate, today)
                .eq(Appointment::getStatus, "CONFIRMED")
        );
        data.put("visits", pendingVisits);
        
        // 药品库存总数
        QueryWrapper<com.gpf.pethospital.entity.Drug> drugWrapper = new QueryWrapper<>();
        drugWrapper.select("SUM(stock) AS totalStock");
        List<Map<String, Object>> drugResult = drugService.listMaps(drugWrapper);
        Long drugStock = 0L;
        if (!drugResult.isEmpty() && drugResult.get(0) != null && drugResult.get(0).get("totalStock") != null) {
            drugStock = Long.valueOf(drugResult.get(0).get("totalStock").toString());
        }
        data.put("drugs", drugStock);
        
        // 今日收入
        LocalDateTime todayStart = today.atStartOfDay();
        LocalDateTime todayEnd = today.plusDays(1).atStartOfDay();
        QueryWrapper<Order> orderWrapper = new QueryWrapper<>();
        orderWrapper.select("SUM(amount) AS total");
        orderWrapper.ge("create_time", todayStart);
        orderWrapper.lt("create_time", todayEnd);
        List<Map<String, Object>> result = orderService.listMaps(orderWrapper);
        BigDecimal todayRevenue = BigDecimal.ZERO;
        if (!result.isEmpty()) {
            Map<String, Object> row = result.get(0);
            if (row != null && row.get("total") != null) {
                todayRevenue = new BigDecimal(row.get("total").toString());
            }
        }
        data.put("revenue", todayRevenue);
        
        // 保留原有统计数据
        data.put("orders", orderService.count());
        data.put("pets", petService.count());
        data.put("customers", userService.count(new LambdaQueryWrapper<User>().eq(User::getRole, "CUSTOMER")));
        
        QueryWrapper<Order> totalWrapper = new QueryWrapper<>();
        totalWrapper.select("SUM(amount) AS total");
        List<Map<String, Object>> totalResult = orderService.listMaps(totalWrapper);
        BigDecimal total = BigDecimal.ZERO;
        if (!totalResult.isEmpty()) {
            Map<String, Object> row = totalResult.get(0);
            if (row != null && row.get("total") != null) {
                total = new BigDecimal(row.get("total").toString());
            }
        }
        data.put("orderAmountTotal", total);
        
        return ApiResponse.success(data);
    }
    
    // @PreAuthorize("hasRole('ADMIN')")
    @GetMapping("/trends")
    public ApiResponse<?> trends(@RequestParam(defaultValue = "week") String period) {
        Map<String, Object> data = new HashMap<>();
        LocalDate now = LocalDate.now();
        LocalDate startDate;
        DateTimeFormatter formatter;
        int days;
        
        switch (period) {
            case "month":
                startDate = now.minusDays(30);
                formatter = DateTimeFormatter.ofPattern("MM-dd");
                days = 30;
                break;
            case "year":
                startDate = now.minusMonths(12);
                formatter = DateTimeFormatter.ofPattern("yyyy-MM");
                days = 12;
                break;
            default: // week
                startDate = now.minusDays(6);
                formatter = DateTimeFormatter.ofPattern("MM-dd");
                days = 7;
                break;
        }
        
        List<String> labels = new ArrayList<>();
        List<Integer> values = new ArrayList<>();
        
        if ("year".equals(period)) {
            // 按月统计
            for (int i = 0; i < 12; i++) {
                LocalDate monthStart = startDate.plusMonths(i);
                LocalDateTime monthStartTime = monthStart.atStartOfDay();
                LocalDateTime monthEndTime = monthStart.plusMonths(1).atStartOfDay();
                
                long count = visitService.count(
                    new LambdaQueryWrapper<Visit>()
                        .ge(Visit::getCreateTime, monthStartTime)
                        .lt(Visit::getCreateTime, monthEndTime)
                );
                
                labels.add(monthStart.format(formatter));
                values.add((int) count);
            }
        } else {
            // 按天统计
            for (int i = 0; i < days; i++) {
                LocalDate date = startDate.plusDays(i);
                LocalDateTime dayStart = date.atStartOfDay();
                LocalDateTime dayEnd = date.plusDays(1).atStartOfDay();
                
                long count = visitService.count(
                    new LambdaQueryWrapper<Visit>()
                        .ge(Visit::getCreateTime, dayStart)
                        .lt(Visit::getCreateTime, dayEnd)
                );
                
                labels.add(date.format(formatter));
                values.add((int) count);
            }
        }
        
        data.put("labels", labels);
        data.put("values", values);
        data.put("total", values.stream().mapToInt(Integer::intValue).sum());
        
        // 计算环比
        if (values.size() >= 2) {
            int current = values.get(values.size() - 1);
            int previous = values.get(values.size() - 2);
            double growthRate = previous > 0 ? ((double) (current - previous) / previous * 100) : 0;
            data.put("growthRate", Math.round(growthRate * 10) / 10.0);
        } else {
            data.put("growthRate", 0);
        }
        
        // 平均日接诊
        double avg = values.isEmpty() ? 0 : values.stream().mapToInt(Integer::intValue).average().orElse(0);
        data.put("average", Math.round(avg * 10) / 10.0);
        
        return ApiResponse.success(data);
    }

    @GetMapping("/report/revenue")
    public ApiResponse<?> revenueReport(@RequestParam(defaultValue = "month") String period,
                                        @RequestParam(required = false) String startDate,
                                        @RequestParam(required = false) String endDate) {
        DateRange range = resolveDateRange(period, startDate, endDate);
        List<Order> paidOrders = orderService.list(
            new LambdaQueryWrapper<Order>()
                .eq(Order::getStatus, "PAID")
                .ge(Order::getCreateTime, range.start())
                .lt(Order::getCreateTime, range.end())
        );

        Map<LocalDate, BigDecimal> amountByDay = new HashMap<>();
        BigDecimal totalAmount = BigDecimal.ZERO;
        for (Order order : paidOrders) {
            BigDecimal amount = order.getAmount() == null ? BigDecimal.ZERO : order.getAmount();
            totalAmount = totalAmount.add(amount);
            if (order.getCreateTime() != null) {
                amountByDay.merge(order.getCreateTime().toLocalDate(), amount, BigDecimal::add);
            }
        }

        List<Map<String, Object>> trend = amountByDay.entrySet().stream()
            .sorted(Map.Entry.comparingByKey())
            .map(entry -> {
                Map<String, Object> point = new HashMap<>();
                point.put("date", entry.getKey().toString());
                point.put("amount", entry.getValue());
                return point;
            })
            .collect(Collectors.toList());

        DateRange previous = range.shiftBack();
        BigDecimal previousTotalAmount = sumPaidOrderAmount(previous.start(), previous.end());
        double growthRate = BigDecimal.ZERO.compareTo(previousTotalAmount) == 0
            ? 0D
            : totalAmount.subtract(previousTotalAmount)
                .multiply(BigDecimal.valueOf(100))
                .divide(previousTotalAmount, 2, java.math.RoundingMode.HALF_UP)
                .doubleValue();

        Map<String, Object> data = new HashMap<>();
        data.put("period", period);
        data.put("startDate", range.start().toLocalDate().toString());
        data.put("endDate", range.end().minusDays(1).toLocalDate().toString());
        data.put("totalAmount", totalAmount);
        data.put("orderCount", paidOrders.size());
        data.put("averageAmount", paidOrders.isEmpty()
            ? BigDecimal.ZERO
            : totalAmount.divide(BigDecimal.valueOf(paidOrders.size()), 2, java.math.RoundingMode.HALF_UP));
        data.put("growthRate", growthRate);
        data.put("trend", trend);
        return ApiResponse.success(data);
    }

    @GetMapping("/report/revenue-sources")
    public ApiResponse<?> revenueSources(@RequestParam(defaultValue = "month") String period,
                                         @RequestParam(required = false) String startDate,
                                         @RequestParam(required = false) String endDate) {
        DateRange range = resolveDateRange(period, startDate, endDate);
        QueryWrapper<Order> wrapper = new QueryWrapper<>();
        wrapper.select("payment_method AS paymentMethod", "COUNT(*) AS orderCount", "COALESCE(SUM(amount), 0) AS totalAmount");
        wrapper.eq("status", "PAID");
        wrapper.ge("create_time", range.start());
        wrapper.lt("create_time", range.end());
        wrapper.groupBy("payment_method");
        wrapper.orderByDesc("totalAmount");

        List<Map<String, Object>> rows = orderService.listMaps(wrapper);
        BigDecimal totalAmount = rows.stream()
            .map(row -> toBigDecimal(getMapValue(row, "totalAmount", "totalamount", "TOTALAMOUNT")))
            .reduce(BigDecimal.ZERO, BigDecimal::add);

        List<Map<String, Object>> sources = new ArrayList<>();
        for (Map<String, Object> row : rows) {
            BigDecimal amount = toBigDecimal(getMapValue(row, "totalAmount", "totalamount", "TOTALAMOUNT"));
            Map<String, Object> item = new HashMap<>();
            item.put("paymentMethod", normalizePaymentMethod(String.valueOf(getMapValue(row, "paymentMethod", "payment_method", "PAYMENTMETHOD"))));
            item.put("orderCount", toLong(getMapValue(row, "orderCount", "ordercount", "ORDERCOUNT")));
            item.put("totalAmount", amount);
            item.put("ratio", BigDecimal.ZERO.compareTo(totalAmount) == 0
                ? BigDecimal.ZERO
                : amount.multiply(BigDecimal.valueOf(100)).divide(totalAmount, 2, java.math.RoundingMode.HALF_UP));
            sources.add(item);
        }

        Map<String, Object> data = new HashMap<>();
        data.put("period", period);
        data.put("startDate", range.start().toLocalDate().toString());
        data.put("endDate", range.end().minusDays(1).toLocalDate().toString());
        data.put("totalAmount", totalAmount);
        data.put("sources", sources);
        return ApiResponse.success(data);
    }

    @GetMapping("/report/drug-sales")
    public ApiResponse<?> drugSales(@RequestParam(defaultValue = "month") String period,
                                    @RequestParam(required = false) String startDate,
                                    @RequestParam(required = false) String endDate,
                                    @RequestParam(defaultValue = "10") int limit) {
        DateRange range = resolveDateRange(period, startDate, endDate);
        QueryWrapper<PrescriptionItem> wrapper = new QueryWrapper<>();
        wrapper.select("drug_id AS drugId", "drug_name AS drugName", "COALESCE(SUM(quantity), 0) AS totalQuantity", "COALESCE(SUM(subtotal), 0) AS totalAmount");
        wrapper.ge("create_time", range.start());
        wrapper.lt("create_time", range.end());
        wrapper.groupBy("drug_id", "drug_name");
        wrapper.orderByDesc("totalQuantity");
        wrapper.orderByDesc("totalAmount");
        wrapper.last("LIMIT " + safeLimit(limit, 100));

        List<Map<String, Object>> rows = prescriptionItemService.listMaps(wrapper);
        List<Map<String, Object>> ranking = new ArrayList<>();
        int rank = 1;
        for (Map<String, Object> row : rows) {
            Map<String, Object> item = new HashMap<>();
            item.put("rank", rank++);
            item.put("drugId", toLong(getMapValue(row, "drugId", "drug_id", "DRUGID")));
            item.put("drugName", normalizeDrugName(getMapValue(row, "drugName", "drug_name", "DRUGNAME")));
            item.put("totalQuantity", toLong(getMapValue(row, "totalQuantity", "totalquantity", "TOTALQUANTITY")));
            item.put("totalAmount", toBigDecimal(getMapValue(row, "totalAmount", "totalamount", "TOTALAMOUNT")));
            ranking.add(item);
        }

        Map<String, Object> data = new HashMap<>();
        data.put("period", period);
        data.put("startDate", range.start().toLocalDate().toString());
        data.put("endDate", range.end().minusDays(1).toLocalDate().toString());
        data.put("ranking", ranking);
        return ApiResponse.success(data);
    }

    @GetMapping("/report/doctor-performance")
    public ApiResponse<?> doctorPerformance(@RequestParam(defaultValue = "month") String period,
                                            @RequestParam(required = false) String startDate,
                                            @RequestParam(required = false) String endDate,
                                            @RequestParam(defaultValue = "10") int limit) {
        DateRange range = resolveDateRange(period, startDate, endDate);
        QueryWrapper<Visit> wrapper = new QueryWrapper<>();
        wrapper.select("doctor_id AS doctorId", "COUNT(*) AS visitCount", "COALESCE(SUM(total_amount), 0) AS totalAmount", "COALESCE(AVG(total_amount), 0) AS averageAmount");
        wrapper.ge("create_time", range.start());
        wrapper.lt("create_time", range.end());
        wrapper.isNotNull("doctor_id");
        wrapper.groupBy("doctor_id");
        wrapper.orderByDesc("totalAmount");
        wrapper.last("LIMIT " + safeLimit(limit, 100));

        List<Map<String, Object>> rows = visitService.listMaps(wrapper);
        Set<Long> doctorIds = rows.stream()
            .map(row -> toLong(getMapValue(row, "doctorId", "doctor_id", "DOCTORID")))
            .filter(id -> id > 0)
            .collect(Collectors.toSet());
        Map<Long, String> doctorNameMap = userService.listByIds(doctorIds).stream()
            .collect(Collectors.toMap(User::getId, User::getUsername, (left, right) -> left));

        List<Map<String, Object>> ranking = new ArrayList<>();
        int rank = 1;
        for (Map<String, Object> row : rows) {
            Long doctorId = toLong(getMapValue(row, "doctorId", "doctor_id", "DOCTORID"));
            Map<String, Object> item = new HashMap<>();
            item.put("rank", rank++);
            item.put("doctorId", doctorId);
            item.put("doctorName", doctorNameMap.getOrDefault(doctorId, "医生#" + doctorId));
            item.put("visitCount", toLong(getMapValue(row, "visitCount", "visitcount", "VISITCOUNT")));
            item.put("totalAmount", toBigDecimal(getMapValue(row, "totalAmount", "totalamount", "TOTALAMOUNT")));
            item.put("averageAmount", toBigDecimal(getMapValue(row, "averageAmount", "averageamount", "AVERAGEAMOUNT")));
            ranking.add(item);
        }

        Map<String, Object> data = new HashMap<>();
        data.put("period", period);
        data.put("startDate", range.start().toLocalDate().toString());
        data.put("endDate", range.end().minusDays(1).toLocalDate().toString());
        data.put("ranking", ranking);
        return ApiResponse.success(data);
    }

    @GetMapping("/report/department-performance")
    public ApiResponse<?> departmentPerformance(@RequestParam(defaultValue = "month") String period,
                                                @RequestParam(required = false) String startDate,
                                                @RequestParam(required = false) String endDate) {
        DateRange range = resolveDateRange(period, startDate, endDate);

        QueryWrapper<Appointment> appointmentWrapper = new QueryWrapper<>();
        appointmentWrapper.select("department", "COUNT(*) AS appointmentCount");
        appointmentWrapper.ge("create_time", range.start());
        appointmentWrapper.lt("create_time", range.end());
        appointmentWrapper.groupBy("department");
        List<Map<String, Object>> appointmentRows = appointmentService.listMaps(appointmentWrapper);

        Map<String, Long> appointmentCountMap = new HashMap<>();
        for (Map<String, Object> row : appointmentRows) {
            String department = normalizeDepartment(getMapValue(row, "department", "DEPARTMENT"));
            appointmentCountMap.put(department, toLong(getMapValue(row, "appointmentCount", "appointmentcount", "APPOINTMENTCOUNT")));
        }

        List<Visit> visits = visitService.list(
            new LambdaQueryWrapper<Visit>()
                .ge(Visit::getCreateTime, range.start())
                .lt(Visit::getCreateTime, range.end())
                .isNotNull(Visit::getAppointmentId)
        );

        Set<Long> appointmentIds = visits.stream()
            .map(Visit::getAppointmentId)
            .filter(id -> id != null && id > 0)
            .collect(Collectors.toSet());

        Map<Long, Appointment> appointmentMap = appointmentIds.isEmpty()
            ? new HashMap<>()
            : appointmentService.listByIds(appointmentIds).stream()
                .collect(Collectors.toMap(Appointment::getId, appointment -> appointment, (left, right) -> left));

        Map<String, Long> visitCountMap = new HashMap<>();
        Map<String, BigDecimal> revenueMap = new HashMap<>();
        for (Visit visit : visits) {
            Appointment appointment = appointmentMap.get(visit.getAppointmentId());
            String department = normalizeDepartment(appointment == null ? null : appointment.getDepartment());
            visitCountMap.merge(department, 1L, Long::sum);
            revenueMap.merge(department, visit.getTotalAmount() == null ? BigDecimal.ZERO : visit.getTotalAmount(), BigDecimal::add);
        }

        Set<String> departments = new HashSet<>();
        departments.addAll(appointmentCountMap.keySet());
        departments.addAll(visitCountMap.keySet());

        List<Map<String, Object>> departmentsData = departments.stream()
            .map(department -> {
                Map<String, Object> row = new HashMap<>();
                row.put("department", department);
                row.put("appointmentCount", appointmentCountMap.getOrDefault(department, 0L));
                row.put("visitCount", visitCountMap.getOrDefault(department, 0L));
                row.put("totalAmount", revenueMap.getOrDefault(department, BigDecimal.ZERO));
                return row;
            })
            .sorted((left, right) -> toBigDecimal(right.get("totalAmount")).compareTo(toBigDecimal(left.get("totalAmount"))))
            .collect(Collectors.toList());

        Map<String, Object> data = new HashMap<>();
        data.put("period", period);
        data.put("startDate", range.start().toLocalDate().toString());
        data.put("endDate", range.end().minusDays(1).toLocalDate().toString());
        data.put("departments", departmentsData);
        return ApiResponse.success(data);
    }
    
    // @PreAuthorize("hasRole('ADMIN')")
    @GetMapping("/today-todos")
    public ApiResponse<?> todayTodos() {
        LocalDate today = LocalDate.now();
        
        // 查询今日待就诊的预约
        List<Appointment> appointments = appointmentService.list(
            new LambdaQueryWrapper<Appointment>()
                .eq(Appointment::getAppointmentDate, today)
                .eq(Appointment::getStatus, "CONFIRMED")
                .orderByAsc(Appointment::getTimeSlot)
        );
        
        List<Map<String, Object>> todoList = appointments.stream().map(appointment -> {
            Map<String, Object> todo = new HashMap<>();
            
            // 获取客户信息
            User customer = userService.getById(appointment.getCustomerId());
            // 获取宠物信息
            Pet pet = petService.getById(appointment.getPetId());
            
            todo.put("id", appointment.getId());
            todo.put("time", appointment.getTimeSlot());
            todo.put("customer", customer != null ? customer.getUsername() : "未知客户");
            todo.put("pet", pet != null ? pet.getName() + "(" + pet.getBreed() + ")" : "未知宠物");
            todo.put("service", appointment.getDepartment() != null ? appointment.getDepartment() : "常规就诊");
            todo.put("status", "待就诊");
            todo.put("action", "接诊");
            
            return todo;
        }).collect(Collectors.toList());
        
        return ApiResponse.success(todoList);
    }

    private DateRange resolveDateRange(String period, String startDate, String endDate) {
        if (hasText(startDate) && hasText(endDate)) {
            LocalDate start = LocalDate.parse(startDate);
            LocalDate end = LocalDate.parse(endDate);
            if (end.isBefore(start)) {
                LocalDate temp = start;
                start = end;
                end = temp;
            }
            return new DateRange(start.atStartOfDay(), end.plusDays(1).atStartOfDay());
        }

        LocalDate today = LocalDate.now();
        LocalDate start;
        LocalDate end = today.plusDays(1);
        switch (period) {
            case "day":
                start = today;
                break;
            case "week":
                start = today.minusDays(6);
                break;
            case "year":
                start = today.minusMonths(11).withDayOfMonth(1);
                end = today.plusMonths(1).withDayOfMonth(1);
                break;
            case "month":
            default:
                start = today.minusDays(29);
                break;
        }
        return new DateRange(start.atStartOfDay(), end.atStartOfDay());
    }

    private BigDecimal sumPaidOrderAmount(LocalDateTime start, LocalDateTime end) {
        QueryWrapper<Order> wrapper = new QueryWrapper<>();
        wrapper.select("COALESCE(SUM(amount), 0) AS totalAmount");
        wrapper.eq("status", "PAID");
        wrapper.ge("create_time", start);
        wrapper.lt("create_time", end);
        List<Map<String, Object>> rows = orderService.listMaps(wrapper);
        if (rows.isEmpty()) {
            return BigDecimal.ZERO;
        }
        return toBigDecimal(getMapValue(rows.get(0), "totalAmount", "totalamount", "TOTALAMOUNT"));
    }

    private boolean hasText(String value) {
        return value != null && !value.isBlank();
    }

    private int safeLimit(int value, int maxLimit) {
        if (value <= 0) {
            return 10;
        }
        return Math.min(value, maxLimit);
    }

    private BigDecimal toBigDecimal(Object value) {
        if (value == null) {
            return BigDecimal.ZERO;
        }
        if (value instanceof BigDecimal) {
            return (BigDecimal) value;
        }
        try {
            return new BigDecimal(value.toString());
        } catch (NumberFormatException ex) {
            return BigDecimal.ZERO;
        }
    }

    private long toLong(Object value) {
        if (value == null) {
            return 0L;
        }
        if (value instanceof Number) {
            return ((Number) value).longValue();
        }
        try {
            return Long.parseLong(value.toString());
        } catch (NumberFormatException ex) {
            return 0L;
        }
    }

    private Object getMapValue(Map<String, Object> row, String... keys) {
        for (String key : keys) {
            if (row.containsKey(key)) {
                return row.get(key);
            }
        }
        for (String key : keys) {
            for (Map.Entry<String, Object> entry : row.entrySet()) {
                if (entry.getKey().equalsIgnoreCase(key)) {
                    return entry.getValue();
                }
            }
        }
        return null;
    }

    private String normalizeDepartment(Object value) {
        String department = value == null ? "" : value.toString().trim();
        return department.isEmpty() ? "未分配科室" : department;
    }

    private String normalizePaymentMethod(String value) {
        if (value == null || value.isBlank()) {
            return "未知支付方式";
        }
        switch (value) {
            case "ALIPAY":
                return "支付宝";
            case "WECHAT":
                return "微信支付";
            case "OFFLINE":
                return "线下支付";
            default:
                return value;
        }
    }

    private String normalizeDrugName(Object value) {
        String name = value == null ? "" : value.toString().trim();
        return name.isEmpty() ? "未知药品" : name;
    }

    private record DateRange(LocalDateTime start, LocalDateTime end) {
        private DateRange shiftBack() {
            long days = Math.max(1, ChronoUnit.DAYS.between(start.toLocalDate(), end.toLocalDate()));
            return new DateRange(start.minusDays(days), start);
        }
    }
}
