package com.greenorange.promotion.controller.course;


import com.greenorange.promotion.annotation.RequiresPermission;
import com.greenorange.promotion.common.BaseResponse;
import com.greenorange.promotion.common.ErrorCode;
import com.greenorange.promotion.common.ResultUtils;
import com.greenorange.promotion.constant.UserConstant;
import com.greenorange.promotion.exception.BusinessException;
import com.greenorange.promotion.model.dto.CommonStringRequest;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * 轮播图 控制器
 */
@RestController
@RequestMapping("banner")
@Slf4j
@Tag(name = "轮播图模块")
@Transactional
public class BannerController {

    @Resource
    private RedisTemplate<String, String> redisTemplate;


    private static final String BANNER_KEY = "banners:list";

    private static final String TOMBSTONE = "\u0000__DEL__\u0000"; // 删除占位符，极低冲突



    /**
     * web端管理员添加轮播图
     * @param commonStringRequest 图片view值
     * @return 是否添加成功
     */
    @PostMapping("add")
    @Operation(summary = "web端管理员添加轮播图", description = "参数：图片view值，权限：管理员，方法名：addBanner")
    @RequiresPermission(mustRole = UserConstant.ADMIN_ROLE)
    public BaseResponse<Boolean> addBanner(@Valid @RequestBody CommonStringRequest commonStringRequest) {
        String view = commonStringRequest.getTemplateString();
        redisTemplate.opsForList().rightPush(BANNER_KEY, view);
        return ResultUtils.success(true);
    }


    /**
     * 删除轮播图（根据索引）
     * @param index 索引
     * @return 是否添加成功
     */
    @PostMapping("del")
    @Operation(summary = "删除轮播图（根据索引）", description = "参数：图片view值，权限：管理员，方法名：delBanner")
    @RequiresPermission(mustRole = UserConstant.ADMIN_ROLE)
    public BaseResponse<Boolean> delBanner(@RequestParam long index) {
        long len = getLenOrThrow();
        long idx = normalizeIndex(index, len);
        try {
            // 先把该位置设置为占位符
            redisTemplate.opsForList().set(BANNER_KEY, idx, TOMBSTONE);
            // 再删除第一个占位符
            Long removed = redisTemplate.opsForList().remove(BANNER_KEY, 1, TOMBSTONE);
            boolean ok = removed != null && removed > 0;
            log.info("按索引删除轮播图：index={}, removed={}", idx, ok);
            return ResultUtils.success(ok);
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "索引越界或参数错误");
        }
    }


    /**
     * 修改轮播图（根据索引）
     * @param index 索引
     * @param newView 新的图片view值
     * @return 是否添加成功
     */
    @PostMapping("modify")
    @Operation(summary = "修改轮播图（根据索引）", description = "参数：图片view值，权限：管理员，方法名：delBanner")
    @RequiresPermission(mustRole = UserConstant.ADMIN_ROLE)
    public BaseResponse<Boolean> modifyBanner(@RequestParam long index, @RequestParam String newView) {
        long len = getLenOrThrow();
        long idx = normalizeIndex(index, len); // 支持 -1
        try {
            redisTemplate.opsForList().set(BANNER_KEY, idx, newView);
            log.info("更新轮播图：index={} -> {}", idx, newView);
            return ResultUtils.success(true);
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "索引越界或参数错误");
        }
    }


    /**
     * web端获取所有轮播图（按添加顺序）
     */
    @GetMapping("web/list")
    @Operation(summary = "web端获取所有轮播图（按添加顺序）", description = "按添加顺序返回")
    @RequiresPermission(mustRole = UserConstant.ADMIN_ROLE)
    public BaseResponse<List<String>> webListBanners() {
        List<String> banners = redisTemplate.opsForList().range(BANNER_KEY, 0, -1);
        return ResultUtils.success(banners);
    }


    /**
     * 小程序端获取所有轮播图（按添加顺序）
     */
    @GetMapping("mini/list")
    @Operation(summary = "小程序端获取所有轮播图（按添加顺序）", description = "按添加顺序返回")
    @RequiresPermission(mustRole = UserConstant.DEFAULT_ROLE)
    public BaseResponse<List<String>> miniListBanners() {
        List<String> banners = redisTemplate.opsForList().range(BANNER_KEY, 0, -1);
        return ResultUtils.success(banners);
    }



    /* ===== 工具方法 ===== */

    /** 获取列表长度，不存在或为空时抛错 */
    private long getLenOrThrow() {
        Long len = redisTemplate.opsForList().size(BANNER_KEY);
        if (len == null || len == 0) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "轮播图列表为空");
        }
        return len;
    }

    /** 归一化索引（支持负索引），并做范围校验 */
    private long normalizeIndex(long index, long len) {
        long idx = index < 0 ? len + index : index; // -1 -> len-1
        if (idx < 0 || idx >= len) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "索引越界：" + index);
        }
        return idx;
    }

}
