package shop.alien.dining.controller;

import io.swagger.annotations.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import shop.alien.entity.result.R;
import shop.alien.entity.store.vo.TableDiningStatusVO;
import shop.alien.entity.store.vo.*;
import shop.alien.dining.service.DiningService;
import shop.alien.dining.util.TokenUtil;

import java.util.List;

/**
 * 点餐控制器
 *
 * @author system
 * @since 2025-01-XX
 */
@Slf4j
@Api(tags = {"小程序-点餐管理"})
@CrossOrigin
@RestController
@RequestMapping("/store/dining")
@RequiredArgsConstructor
public class DiningController {

    private final DiningService diningService;

    @ApiOperation(value = "查询餐桌是否处于就餐中", notes = "免登录可调用，用于前端判断是否跳过选择用餐人数。就餐中(status=1)、加餐(status=3) 均视为就餐状态，且 diner_count 有值 时 inDining=true")
    @GetMapping("/table-dining-status")
    public R<TableDiningStatusVO> getTableDiningStatus(
            @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId) {
        log.info("DiningController.getTableDiningStatus?tableId={}", tableId);
        try {
            TableDiningStatusVO vo = diningService.getTableDiningStatus(tableId);
            return R.data(vo);
        } catch (Exception e) {
            log.error("查询餐桌就餐状态失败: {}", e.getMessage(), e);
            return R.fail("查询餐桌就餐状态失败: " + e.getMessage());
        }
    }

    @ApiOperation(value = "获取点餐页面信息", notes = "首客选桌时传就餐人数，餐桌置为就餐中并保存人数；后续用户选同一桌可不传就餐人数，将使用表中已保存人数")
    @GetMapping("/page-info")
    public R<DiningPageInfoVO> getDiningPageInfo(
            @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId,
            @ApiParam(value = "就餐人数（首客必传；餐桌已就餐中时可省略，将使用已保存人数）") @RequestParam(required = false) Integer dinerCount) {
        log.info("DiningController.getDiningPageInfo?tableId={}, dinerCount={}", tableId, dinerCount);
        try {
            // 从 token 获取用户信息
            Integer userId = TokenUtil.getCurrentUserId();
            if (userId == null) {
                return R.fail("用户未登录");
            }
            DiningPageInfoVO vo = diningService.getDiningPageInfo(tableId, dinerCount);
            return R.data(vo);
        } catch (Exception e) {
            log.error("获取点餐页面信息失败: {}", e.getMessage(), e);
            return R.fail("获取点餐页面信息失败: " + e.getMessage());
        }
    }

    @ApiOperation(value = "搜索菜品", notes = "模糊搜索菜品，关键词限10字")
    @GetMapping("/search")
    public R<List<CuisineListVO>> searchCuisines(
            @ApiParam(value = "门店ID", required = true) @RequestParam Integer storeId,
            @ApiParam(value = "搜索关键词", required = false) @RequestParam(required = false) String keyword,
            @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId) {
        log.info("DiningController.searchCuisines?storeId={}, keyword={}, tableId={}", storeId, keyword, tableId);
        try {
            // 从 token 获取用户信息
            Integer userId = TokenUtil.getCurrentUserId();
            if (userId == null) {
                return R.fail("用户未登录");
            }
            // 限制关键词长度
            if (StringUtils.hasText(keyword) && keyword.length() > 10) {
                keyword = keyword.substring(0, 10);
            }
            List<CuisineListVO> list = diningService.searchCuisines(storeId, keyword, tableId);
            return R.data(list);
        } catch (Exception e) {
            log.error("搜索菜品失败: {}", e.getMessage(), e);
            return R.fail("搜索菜品失败: " + e.getMessage());
        }
    }

    @ApiOperation(value = "根据分类获取菜品列表", notes = "分页获取菜品列表，默认每页12条")
    @GetMapping("/cuisines")
    public R<List<CuisineListVO>> getCuisinesByCategory(
            @ApiParam(value = "门店ID", required = true) @RequestParam Integer storeId,
            @ApiParam(value = "分类ID", required = false) @RequestParam(required = false) Integer categoryId,
            @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId,
            @ApiParam(value = "页码", required = false) @RequestParam(defaultValue = "1") Integer page,
            @ApiParam(value = "每页数量", required = false) @RequestParam(defaultValue = "12") Integer size) {
        log.info("DiningController.getCuisinesByCategory?storeId={}, categoryId={}, tableId={}, page={}, size={}", storeId, categoryId, tableId, page, size);
        try {
            // 从 token 获取用户信息
            Integer userId = TokenUtil.getCurrentUserId();
            if (userId == null) {
                return R.fail("用户未登录");
            }
            List<CuisineListVO> list = diningService.getCuisinesByCategory(storeId, categoryId, tableId, page, size);
            return R.data(list);
        } catch (Exception e) {
            log.error("获取菜品列表失败: {}", e.getMessage(), e);
            return R.fail("获取菜品列表失败: " + e.getMessage());
        }
    }

    @ApiOperation(value = "获取菜品详情", notes = "获取菜品详细信息，包含图片列表、月售数量等")
    @GetMapping("/cuisine/{cuisineId}")
    public R<CuisineDetailVO> getCuisineDetail(
            @ApiParam(value = "菜品ID", required = true) @PathVariable Integer cuisineId,
            @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId) {
        log.info("DiningController.getCuisineDetail?cuisineId={}, tableId={}", cuisineId, tableId);
        try {
            CuisineDetailVO vo = diningService.getCuisineDetail(cuisineId, tableId);
            
            return R.data(vo);
        } catch (Exception e) {
            log.error("获取菜品详情失败: {}", e.getMessage(), e);
            return R.fail("获取菜品详情失败: " + e.getMessage());
        }
    }

    @ApiOperation(value = "获取可领取的优惠券列表", notes = "获取用户可领取的优惠券")
    @GetMapping("/coupons/available")
    public R<List<AvailableCouponVO>> getAvailableCoupons(
            @ApiParam(value = "门店ID", required = true) @RequestParam Integer storeId) {
        log.info("DiningController.getAvailableCoupons?storeId={}", storeId);
        try {
            // 从 token 获取用户信息
            Integer userId = TokenUtil.getCurrentUserId();
            if (userId == null) {
                return R.fail("用户未登录");
            }
            List<AvailableCouponVO> list = diningService.getAvailableCoupons(storeId, userId);
            return R.data(list);
        } catch (Exception e) {
            log.error("获取可领取优惠券列表失败: {}", e.getMessage(), e);
            return R.fail("获取可领取优惠券列表失败: " + e.getMessage());
        }
    }

    @ApiOperation(value = "领取优惠券", notes = "用户领取优惠券")
    @PostMapping("/coupon/receive")
    public R<Boolean> receiveCoupon(
            @ApiParam(value = "优惠券ID", required = true) @RequestParam Integer couponId) {
        log.info("DiningController.receiveCoupon?couponId={}", couponId);
        try {
            // 从 token 获取用户信息
            Integer userId = TokenUtil.getCurrentUserId();
            if (userId == null) {
                return R.fail("用户未登录");
            }
            boolean result = diningService.receiveCoupon(couponId, userId);
            return R.data(result);
        } catch (Exception e) {
            log.error("领取优惠券失败: {}", e.getMessage(), e);
            return R.fail("领取优惠券失败: " + e.getMessage());
        }
    }

    @ApiOperation(value = "获取订单确认页面信息", notes = "获取订单确认页面的所有信息")
    @GetMapping("/order/confirm")
    public R<OrderConfirmVO> getOrderConfirmInfo(
            @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId,
            @ApiParam(value = "就餐人数", required = true) @RequestParam Integer dinerCount) {
        log.info("DiningController.getOrderConfirmInfo?tableId={}, dinerCount={}", tableId, dinerCount);
        try {
            // 从 token 获取用户信息
            Integer userId = TokenUtil.getCurrentUserId();
            if (userId == null) {
                return R.fail("用户未登录");
            }
            OrderConfirmVO vo = diningService.getOrderConfirmInfo(tableId, dinerCount, userId);
            return R.data(vo);
        } catch (Exception e) {
            log.error("获取订单确认页面信息失败: {}", e.getMessage(), e);
            return R.fail("获取订单确认页面信息失败: " + e.getMessage());
        }
    }

    @ApiOperation(value = "锁定订单", notes = "锁定订单，防止多人同时下单")
    @PostMapping("/order/lock")
    public R<Boolean> lockOrder(
            @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId) {
        log.info("DiningController.lockOrder?tableId={}", tableId);
        try {
            // 从 token 获取用户信息
            Integer userId = TokenUtil.getCurrentUserId();
            if (userId == null) {
                return R.fail("用户未登录");
            }
            boolean result = diningService.lockOrder(tableId, userId);
            if (!result) {
                return R.fail("订单已被其他用户锁定，无法下单");
            }
            return R.data(true);
        } catch (Exception e) {
            log.error("锁定订单失败: {}", e.getMessage(), e);
            return R.fail("锁定订单失败: " + e.getMessage());
        }
    }

    @ApiOperation(value = "解锁订单", notes = "解锁订单")
    @PostMapping("/order/unlock")
    public R<Boolean> unlockOrder(
            @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId) {
        log.info("DiningController.unlockOrder?tableId={}", tableId);
        try {
            // 从 token 获取用户信息
            Integer userId = TokenUtil.getCurrentUserId();
            if (userId == null) {
                return R.fail("用户未登录");
            }
            diningService.unlockOrder(tableId, userId);
            return R.data(true);
        } catch (Exception e) {
            log.error("解锁订单失败: {}", e.getMessage(), e);
            return R.fail("解锁订单失败: " + e.getMessage());
        }
    }

    @ApiOperation(value = "检查订单锁定状态", notes = "检查订单是否被锁定")
    @GetMapping("/order/check-lock")
    public R<Integer> checkOrderLock(
            @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId) {
        log.info("DiningController.checkOrderLock?tableId={}", tableId);
        try {
            // 从 token 获取用户信息
            Integer userId = TokenUtil.getCurrentUserId();
            if (userId == null) {
                return R.fail("用户未登录");
            }
            Integer lockUserId = diningService.checkOrderLock(tableId);
            return R.data(lockUserId);
        } catch (Exception e) {
            log.error("检查订单锁定状态失败: {}", e.getMessage(), e);
            return R.fail("检查订单锁定状态失败: " + e.getMessage());
        }
    }

    @ApiOperation(value = "获取订单结算确认页面信息", notes = "获取订单结算确认页面的所有信息")
    @GetMapping("/order/settlement")
    public R<shop.alien.entity.store.vo.OrderSettlementVO> getOrderSettlementInfo(
            @ApiParam(value = "订单ID", required = true) @RequestParam Integer orderId) {
        log.info("DiningController.getOrderSettlementInfo?orderId={}", orderId);
        try {
            // 从 token 获取用户信息
            Integer userId = TokenUtil.getCurrentUserId();
            if (userId == null) {
                return R.fail("用户未登录");
            }
            shop.alien.entity.store.vo.OrderSettlementVO vo = diningService.getOrderSettlementInfo(orderId, userId);
            return R.data(vo);
        } catch (Exception e) {
            log.error("获取订单结算确认页面信息失败: {}", e.getMessage(), e);
            return R.fail("获取订单结算确认页面信息失败: " + e.getMessage());
        }
    }

    @ApiOperation(value = "锁定订单结算", notes = "锁定订单结算，防止多人同时结算")
    @PostMapping("/order/settlement/lock")
    public R<Boolean> lockSettlement(
            @ApiParam(value = "订单ID", required = true) @RequestParam Integer orderId) {
        log.info("DiningController.lockSettlement?orderId={}", orderId);
        try {
            // 从 token 获取用户信息
            Integer userId = TokenUtil.getCurrentUserId();
            if (userId == null) {
                return R.fail("用户未登录");
            }
            boolean result = diningService.lockSettlement(orderId, userId);
            if (!result) {
                return R.fail("订单已被其他用户锁定，无法结算");
            }
            return R.data(true);
        } catch (Exception e) {
            log.error("锁定订单结算失败: {}", e.getMessage(), e);
            return R.fail("锁定订单结算失败: " + e.getMessage());
        }
    }

    @ApiOperation(value = "解锁订单结算", notes = "解锁订单结算")
    @PostMapping("/order/settlement/unlock")
    public R<Boolean> unlockSettlement(
            @ApiParam(value = "订单ID", required = true) @RequestParam Integer orderId) {
        log.info("DiningController.unlockSettlement?orderId={}", orderId);
        try {
            // 从 token 获取用户信息
            Integer userId = TokenUtil.getCurrentUserId();
            if (userId == null) {
                return R.fail("用户未登录");
            }
            diningService.unlockSettlement(orderId, userId);
            return R.data(true);
        } catch (Exception e) {
            log.error("解锁订单结算失败: {}", e.getMessage(), e);
            return R.fail("解锁订单结算失败: " + e.getMessage());
        }
    }
}
