package com.ylx.web.controller.massage;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ylx.common.annotation.Log;
import com.ylx.common.core.controller.BaseController;
import com.ylx.common.core.domain.R;
import com.ylx.common.core.domain.model.LoginUser;
import com.ylx.common.enums.BusinessType;
import com.ylx.common.exception.ServiceException;
import com.ylx.common.utils.StringUtils;
import com.ylx.common.utils.poi.ExcelUtil;
import com.ylx.massage.domain.TJs;
import com.ylx.massage.domain.TOrder;
import com.ylx.massage.domain.vo.OrderAllocationResultVo;
import com.ylx.massage.domain.vo.OrderVerificationVo;
import com.ylx.massage.domain.vo.TechnicianAvailabilityVo;
import com.ylx.massage.enums.Enumproject;
import com.ylx.massage.enums.OrderStatusEnum;
import com.ylx.massage.enums.OrderStatusEnumVo;
import com.ylx.massage.domain.OrderAllocationLog;
import com.ylx.massage.service.TJsService;
import com.ylx.massage.service.TOrderService;
import com.ylx.massage.service.OrderAllocationLogService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;


import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 订单表 前端控制器
 */
@RestController
@Slf4j
@Api(tags = {"订单管理"})
@RequestMapping("api/order/v1")
public class TOrderController extends BaseController {
    @Resource
    private TOrderService orderService;

    @Resource
    private OrderAllocationLogService allocationLogService;

    @Resource
    private TJsService jsService;


    /**
     * 下单
     *
     * @param order
     * @return R<TOrder>
     */
    //@Log(title = "新增订单", businessType = BusinessType.INSERT)
    @ApiOperation("下单")
    @RequestMapping(value = "wx/add", method = RequestMethod.POST)
    public R<TOrder> add(@RequestBody TOrder order) {
        try {
            return R.ok(orderService.addOrder(order));
        } catch (ServiceException s) {
            log.error(s.toString());
            return R.fail(s.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            return R.fail("系统异常");
        }
    }

    /**
     * 优惠卷核销
     *
     * @param order
     * @return
     */
    @Log(title = "优惠卷核销", businessType = BusinessType.UPDATE)
    @ApiOperation("优惠卷核销")
    @RequestMapping(value = "wx/verification", method = RequestMethod.POST)
    public R<OrderVerificationVo> verification(@RequestBody TOrder order) {
        try {
            return R.ok(orderService.verification(order));
        } catch (ServiceException s) {
            log.error(s.toString());
            return R.fail(s.getMessage());
        } catch (Exception e) {
            StackTraceElement stackTraceElement = e.getStackTrace()[0];
            log.error("系统出错，错误信息:" + e + " at " + stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName() + ":" + stackTraceElement.getLineNumber());
            return R.fail("系统异常");
        }
    }

    /**
     * 转单
     *
     * @param order
     * @return R<TOrder>
     */
    @Log(title = "转单", businessType = BusinessType.INSERT)
    @ApiOperation("转单")
    @RequestMapping(value = "wx/transferOrder", method = RequestMethod.POST)
    public R<TOrder> transferOrder(@RequestBody TOrder order) {
        try {
            return R.ok(orderService.transferOrder(order));
        } catch (ServiceException s) {
            log.error(s.toString());
            return R.fail(s.getMessage());
        } catch (Exception e) {
            StackTraceElement stackTraceElement = e.getStackTrace()[0];
            log.error("系统出错，错误信息:" + e + " at " + stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName() + ":" + stackTraceElement.getLineNumber());
            return R.fail("系统异常");
        }
    }

    /**
     * 支付订单
     *
     * @param order
     * @return R
     */
    @ApiOperation("支付订单")
    @Log(title = "支付订单", businessType = BusinessType.UPDATE)
    @RequestMapping(value = "wx/pay", method = RequestMethod.POST)
    public R pay(@RequestBody TOrder order) {
        try {
            log.info("支付订单接口前端传递的参数:{}", JSON.toJSONString(order));
            return orderService.payOrder(order);
        } catch (ServiceException s) {
            log.error(s.toString());
            return R.fail(s.getMessage());
        } catch (Exception e) {
            StackTraceElement stackTraceElement = e.getStackTrace()[0];
            log.error("系统出错，错误信息:" + e + " at " + stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName() + ":" + stackTraceElement.getLineNumber());
            return R.fail("系统异常");
        }
    }


    /**
     * 退单申请
     *
     * 业务流程：
     * 1. 用户在订单详情页点击"取消订单"按钮
     * 2. 填写退单原因
     * 3. 提交申请
     * 4. 系统创建退单申请记录，状态为待审核
     * 5. 等待客服审核
     *
     *
     * @param order 订单对象
     * @return R
     */
    //@Log(title = "取消订单申请", businessType = BusinessType.UPDATE)
    @ApiOperation("退单申请")
    @RequestMapping(value = "wx/applyCancle", method = RequestMethod.POST)
    public R applyCancle(@RequestBody JSONObject jsonObject) {
        try {
            log.info("收到退单申请请求，订单ID：{}，退单原因：{}", jsonObject.getString("cId"), jsonObject.getString("cancelReason"));
            // 调用服务层处理退单申请
            orderService.applyCancle(jsonObject.getString("cId"), jsonObject.getString("cancelReason"));
            // 返回成功提示
            return R.ok("您的申请已提交，客服审核中，请注意接听客服电话：19936963696");
        } catch (ServiceException s) {
            log.error("退单申请失败：{}", s.getMessage());
            return R.fail(s.getMessage());
        } catch (Exception e) {
            log.error("退单申请系统异常", e);
            return R.fail("系统异常，请稍后重试");
        }
    }

    /**
     * 取消退单申请（用户操作的接口）
     *
     * 业务流程：
     * 1. 用户在订单详情页点击"取消退单申请"按钮
     * 2. 系统校验订单状态和退单申请状态
     * 3. 取消退单申请，将申请状态标记为已取消
     * 4. 恢复订单到申请前的原始状态
     * 5. 返回成功提示
     *
     * @param order 订单对象，需要包含cId（订单ID）
     * @return R 操作结果
     */
    @ApiOperation("取消退单申请")
    @RequestMapping(value = "wx/cancelApplyCancle", method = RequestMethod.POST)
    public R cancelApplyCancle(@RequestBody TOrder order) {
        try {
            log.info("收到取消退单申请请求，订单ID：{}", order.getcId());
            // 调用服务层处理取消退单申请
            orderService.cancelApplyCancle(order);
            // 返回成功提示
            return R.ok("已成功取消退单申请，订单已恢复到原状态");
        } catch (ServiceException s) {
            log.error("取消退单申请失败：{}", s.getMessage());
            return R.fail(s.getMessage());
        } catch (Exception e) {
            log.error("取消退单申请系统异常", e);
            return R.fail("系统异常，请稍后重试");
        }
    }

    /**
     * 取消订单（用户操作的接口）
     *
     * @param order
     * @return R
     */
    @Log(title = "取消订单", businessType = BusinessType.UPDATE)
    @ApiOperation("取消订单")
    @RequestMapping(value = "wx/cancle", method = RequestMethod.POST)
    public R cancle(@RequestBody TOrder order) {
        try {
            return R.ok(orderService.cancle(order));
        } catch (ServiceException s) {
            log.error(s.toString());
            return R.fail(s.getMessage());
        } catch (Exception e) {
            StackTraceElement stackTraceElement = e.getStackTrace()[0];
            log.error("系统出错，错误信息:" + e + " at " + stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName() + ":" + stackTraceElement.getLineNumber());
            return R.fail("系统异常");
        }
    }

    /**
     * 拒绝订单
     *
     * @param order
     * @return
     */
    @Log(title = "拒绝订单", businessType = BusinessType.UPDATE)
    @ApiOperation("拒绝订单")
    @RequestMapping(value = "wx/jujue", method = RequestMethod.POST)
    public R jujue(@RequestBody TOrder order) {
        try {
            return R.ok(orderService.jujue(order));
        } catch (ServiceException s) {
            log.error(s.toString());
            return R.fail(s.getMessage());
        } catch (Exception e) {
            StackTraceElement stackTraceElement = e.getStackTrace()[0];
            log.error("系统出错，错误信息:" + e + " at " + stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName() + ":" + stackTraceElement.getLineNumber());
            return R.fail("系统异常");
        }
    }


    /**
     * 接受订单（技师端操作的接口）
     *
     * @param order
     * @return R
     */
    @Log(title = "接受订单", businessType = BusinessType.UPDATE)
    @ApiOperation("接受订单")
    @RequestMapping(value = "wx/takingOrders", method = RequestMethod.POST)
    public R takingOrders(@RequestBody TOrder order) {
        try {
            orderService.takingOrders(order);
            return R.ok();
        } catch (ServiceException s) {
            log.error(s.toString());
            return R.fail(s.getMessage());
        } catch (Exception e) {
            StackTraceElement stackTraceElement = e.getStackTrace()[0];
            log.error("系统出错，错误信息:" + e + " at " + stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName() + ":" + stackTraceElement.getLineNumber());
            return R.fail("系统异常");
        }
    }


    /**
     * 出发（技师端操作的接口）
     *
     * @param order
     * @return R
     */
    @Log(title = "出发", businessType = BusinessType.UPDATE)
    @ApiOperation("出发")
    @RequestMapping(value = "wx/depart", method = RequestMethod.POST)
    public R depart(@RequestBody TOrder order) {
        try {
            orderService.depart(order);
            return R.ok();
        } catch (ServiceException s) {
            log.error(s.toString());
            return R.fail(s.getMessage());
        } catch (Exception e) {
            StackTraceElement stackTraceElement = e.getStackTrace()[0];
            log.error("系统出错，错误信息:" + e + " at " + stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName() + ":" + stackTraceElement.getLineNumber());
            return R.fail("系统异常");
        }
    }

    /**
     * 到达订单位置（技师端操作的接口）
     *
     * @param order
     * @return R
     */
    @Log(title = "到达订单位置", businessType = BusinessType.UPDATE)
    @ApiOperation("到达订单位置")
    @RequestMapping(value = "wx/reach", method = RequestMethod.POST)
    public R reach(@RequestBody TOrder order) {
        try {
            log.info("到达订单位置，order对象的值：{}", JSON.toJSONString(order));

            LambdaQueryWrapper<TOrder> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(TOrder::getcId, order.getcId()).eq(TOrder::getnStatus, OrderStatusEnum.DEPART.getCode());
            order.setnStatus(OrderStatusEnum.ARRIVED.getCode());
            order.setReachTime(LocalDateTime.now());
            order.setArrivalLatitude(Optional.ofNullable(order.getArrivalLatitude()).orElse(BigDecimal.ZERO));
            order.setArrivalLongitude(Optional.ofNullable(order.getArrivalLongitude()).orElse(BigDecimal.ZERO));
            order.setArrivalPhoto(Optional.ofNullable(order.getArrivalPhoto()).orElse(StringUtils.EMPTY));
            return R.ok(orderService.update(order, wrapper));
        } catch (ServiceException s) {
            log.error(s.toString());
            return R.fail(s.getMessage());
        } catch (Exception e) {
            StackTraceElement stackTraceElement = e.getStackTrace()[0];
            log.error("系统出错，错误信息:" + e + " at " + stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName() + ":" + stackTraceElement.getLineNumber());
            return R.fail("系统异常");
        }
    }

    /**
     * 开始服务（技师端操作的接口）
     *
     * @param order
     * @return R
     */
    @Log(title = "开始服务", businessType = BusinessType.UPDATE)
    @ApiOperation("开始服务")
    @RequestMapping(value = "wx/service", method = RequestMethod.POST)
    public R service(@RequestBody TOrder order) {
        try {
            LambdaQueryWrapper<TOrder> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(TOrder::getcId, order.getcId()).eq(TOrder::getnStatus, OrderStatusEnum.ARRIVED.getCode());
            // 设置订单状态：服务中
            order.setnStatus(OrderStatusEnum.SERVICE.getCode());
            order.setStartTime(LocalDateTime.now());
            return R.ok(orderService.update(order, wrapper));
        } catch (ServiceException s) {
            log.error(s.toString());
            return R.fail(s.getMessage());
        } catch (Exception e) {
            StackTraceElement stackTraceElement = e.getStackTrace()[0];
            log.error("系统出错，错误信息:" + e + " at " + stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName() + ":" + stackTraceElement.getLineNumber());
            return R.fail("系统异常");
        }
    }

    /**
     * 确认订单（技师端的操作接口）
     *
     * @param order
     * @return R
     */
    //@Log(title = "确认服务完成", businessType = BusinessType.UPDATE)
    @ApiOperation("确认服务完成")
    @RequestMapping(value = "wx/confirm", method = RequestMethod.POST)
    public R confirm(@RequestBody TOrder order) {
        try {
            return R.ok(orderService.confirm(order));
        } catch (ServiceException s) {
            log.error(s.toString());
            return R.fail(s.getMessage());
        } catch (Exception e) {
            StackTraceElement stackTraceElement = e.getStackTrace()[0];
            log.error("系统出错，错误信息:" + e + " at " + stackTraceElement.getClassName() + "."
                    + stackTraceElement.getMethodName() + ":" + stackTraceElement.getLineNumber());
            return R.fail("系统异常");
        }
    }

    /**
     * 获取订单信息（H5端 用户端）
     *
     * @param page
     * @param param
     * @return R
     */
    @Log(title = "微信获取订单信息", businessType = BusinessType.OTHER)
    @ApiOperation("获取订单信息")
    @RequestMapping(value = "wx/getOrder", method = RequestMethod.GET)
    public R getOrder(Page<TOrder> page, TOrder param) {
        try {
            Page<TOrder> all = orderService.getAll(page, param);
            return R.ok(all);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    @Log(title = "技师端-获取待接单数量", businessType = BusinessType.OTHER)
    @ApiOperation("技师端-获取待接单数量")
    @RequestMapping(value = "wx/waitOrder", method = RequestMethod.GET)
    public R waitOrder(@RequestParam String cJsId) {
        List<TOrder> list = orderService.list(new LambdaQueryWrapper<TOrder>().
                eq(TOrder::getnStatus, OrderStatusEnum.WAIT_JD.getCode()).
                eq(TOrder::getcJsId, cJsId));
        return R.ok(list.size());
    }


    /**
     * PC获取订单信息（PC端）
     *
     * @param page
     * @param order
     * @return R
     */
    @Log(title = "PC获取订单信息", businessType = BusinessType.OTHER)
    @ApiOperation("PC获取订单信息")
    @RequestMapping(value = "pc/getOrder", method = RequestMethod.GET)
    public R getPcOrder(Page<TOrder> page, TOrder order) {
        try {
            LoginUser loginUser = this.getLoginUser();
            log.info("登录用户信息：{}", JSON.toJSONString(loginUser));
            order.setDeptId(loginUser.getDeptId().toString());
            Page<TOrder> all = orderService.getAll(page, order);
            return R.ok(all);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    @Log(title = "微信获取订单信息", businessType = BusinessType.EXPORT)
    @ApiOperation("导出")
    @PostMapping(value = "wx/export")
    public void export(HttpServletResponse response, Page<TOrder> page, TOrder param) {
        Page<TOrder> all = orderService.getAll(page, param);
        ExcelUtil<TOrder> util = new ExcelUtil<>(TOrder.class);
        util.exportExcel(response, all.getRecords(), "订单");
    }

    /**
     * 分页查询订单数据
     *
     * @param page
     * @param order
     * @return R
     */
    @ApiOperation("分页查询订单数据")
    @RequestMapping(value = "/select", method = RequestMethod.GET)
    public R selectSp(Page<TOrder> page, TOrder order) {
        LambdaQueryWrapper<TOrder> tOrderLambdaQueryWrapper = new LambdaQueryWrapper<>();
        tOrderLambdaQueryWrapper.eq(StringUtils.isNotBlank(order.getcJsId()), TOrder::getcJsId, order.getcJsId()).
                eq(StringUtils.isNotBlank(order.getcOpenId()), TOrder::getcOpenId, order.getcOpenId()).
                eq(null != order.getnStatus(), TOrder::getnStatus, order.getnStatus());
        // 获取查询返回结果
        Page<TOrder> pageSelect = orderService.page(page, tOrderLambdaQueryWrapper);
        return R.ok(pageSelect);
    }


    /**
     * 更新订单数据
     *
     * @param borrow
     * @return R 操作结果
     */
    @ApiOperation("更新订单数据")
    @Log(title = "更新订单数据", businessType = BusinessType.OTHER)
    @RequestMapping(value = "/update", method = RequestMethod.POST)
    public R update(@RequestBody TOrder borrow) {
        try {
            return R.ok(orderService.updateAddressById(borrow));
        } catch (ServiceException s) {
            log.error(s.toString());
            return R.fail(s.getMessage());
        } catch (Exception e) {
            StackTraceElement stackTraceElement = e.getStackTrace()[0];
            log.error("系统出错，错误信息:" + e + " at " + stackTraceElement.getClassName() + "."
                    + stackTraceElement.getMethodName() + ":" + stackTraceElement.getLineNumber());
            return R.fail("系统异常");
        }
    }

    /**
     * 根据订单ID删除订单数据
     *
     * @param borrow
     * @return R 操作结果
     */
    @ApiOperation("删除数据")
    @RequestMapping(value = "/del", method = RequestMethod.POST)
    public R del(@RequestBody TOrder borrow) {
        try {
            log.info("删除订单ID：{}", borrow.getcId());
            return R.ok(orderService.removeById(borrow));
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    /**
     * 根据订单ID查询订单详情
     *
     * @param borrow
     * @return R<TOrder> 订单详情
     */
    @ApiOperation("根据订单ID查询订单详情")
    @RequestMapping(value = "/getByid", method = RequestMethod.POST)
    public R<TOrder> getByid(@RequestBody TOrder borrow) {
        try {
            return R.ok(orderService.getById(borrow.getcId()));
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取订单状态
     *
     * @return R
     */
    @ApiOperation("订单状态")
    @RequestMapping(value = "/getStatus", method = RequestMethod.GET)
    public R getStatus() {
        List<Enumproject> statusEnum = OrderStatusEnumVo.getStatusEnum();
        return R.ok(statusEnum);
    }

    /**
     * 分页查询订单分配操作记录
     *
     * @param page    分页参数
     * @param orderNo 订单号
     * @return R 分页结果
     */
    @Log(title = "分页查询订单分配操作记录", businessType = BusinessType.OTHER)
    @ApiOperation("分页查询订单分配操作记录")
    @RequestMapping(value = "/allocationLogs/page", method = RequestMethod.GET)
    public R getAllocationLogsPage(Page<OrderAllocationLog> page, @RequestParam String orderNo) {
        try {
            // 构建查询条件
            LambdaQueryWrapper<OrderAllocationLog> wrapper = new LambdaQueryWrapper<>();
            // 订单号条件
            wrapper.eq(StringUtils.isNotBlank(orderNo), OrderAllocationLog::getOrderNo, orderNo);
            // 按创建时间倒序排列
            wrapper.orderByDesc(OrderAllocationLog::getCreateTime);

            // 分页查询
            Page<OrderAllocationLog> resultPage = allocationLogService.page(page, wrapper);

            // 转换为VO列表
            List<OrderAllocationResultVo> voList = resultPage.getRecords().stream()
                    .map(log -> {
                        // 转换为VO
                        OrderAllocationResultVo vo = new OrderAllocationResultVo();
                        BeanUtils.copyProperties(log, vo);
                        //根据newTechnicianId查询新技师电话
                        if (StringUtils.isNotBlank(vo.getNewTechnicianId())) {
                            TJs technician = jsService.getById(log.getNewTechnicianId());
                            if (technician != null) {
                                vo.setNewTechnicianPhone(technician.getcPhone());
                            }
                        }
                        return vo;
                    }).collect(Collectors.toList());

            // 创建新的分页对象，包装转换后的VO列表
            Page<OrderAllocationResultVo> voPage = new Page<>(page.getCurrent(), page.getSize(), resultPage.getTotal());
            voPage.setRecords(voList);
            voPage.setPages(resultPage.getPages());

            return R.ok(voPage);
        } catch (Exception e) {
            log.error("分页查询订单分配记录失败 - 错误信息：{}", e.getMessage(), e);
            return R.fail("分页查询分配记录失败：" + e.getMessage());
        }
    }

    /**
     * 获取技师当天可预约时间
     *
     * @param technicianId 技师ID
     * @param date 查询日期（格式：yyyy-MM-dd），可选，不传则查询当天
     * @return R
     */
    //@Log(title = "获取技师当天可预约时间", businessType = BusinessType.OTHER)
    @ApiOperation("获取技师当天可预约时间")
    @RequestMapping(value = "wx/getTechnicianAvailability", method = RequestMethod.GET)
    public R<TechnicianAvailabilityVo> getTechnicianAvailability(@RequestParam String technicianId, @RequestParam(required = false) String date) {
        try {
            log.info("获取技师当天可预约时间，技师ID：{}，查询日期：{}", technicianId, date);
            TechnicianAvailabilityVo availability = orderService.getTechnicianAvailability(technicianId, date);
            return R.ok(availability);
        } catch (ServiceException s) {
            log.error(s.toString());
            return R.fail(s.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            return R.fail("系统异常");
        }
    }
}
