package quant.rich.emoney.controller.manage;

import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.fasterxml.jackson.databind.ObjectMapper;

import lombok.extern.slf4j.Slf4j;
import quant.rich.emoney.controller.common.UpdateBoolServiceController;
import quant.rich.emoney.entity.sqlite.Plan;
import quant.rich.emoney.enums.PlanType;
import quant.rich.emoney.exception.PageNotFoundException;
import quant.rich.emoney.exception.RException;
import quant.rich.emoney.interfaces.IQueryableEnum;
import quant.rich.emoney.pojo.dto.LayPageReq;
import quant.rich.emoney.pojo.dto.LayPageResp;
import quant.rich.emoney.pojo.dto.R;
import quant.rich.emoney.service.sqlite.PlanService;

@Slf4j
@Controller
@RequestMapping("/admin/v1/manage/plan")
public class PlanControllerV1 extends UpdateBoolServiceController<Plan> {
    
    @Autowired
    PlanService planService;
    
    @Autowired
    ObjectMapper objectMapper;
    
    @GetMapping({"", "/", "/index"})
    public String index() {
        return "/admin/v1/manage/plan/index";
    }
	
	@GetMapping("/list")
	@ResponseBody
	public LayPageResp<?> list(LayPageReq<Plan> pageReq) {
	    return super.list(pageReq);
	}
	
	@GetMapping("/getOne")
	@ResponseBody
	public R<?> getOne(String planId) {
	    return super.getOne(planId);
	}
	
	/**
	 * 通用编辑接口，跳转对应模式的编辑页
	 * @param planId
	 * @param ra
	 * @return
	 */
	@GetMapping("/edit")
	public String edit(Integer planId, RedirectAttributes ra) {
	    Plan plan = null;
	    if (planId != null) {
	        plan = planService.getById(planId);
	    }
	    if (plan == null) {
	        plan = new Plan();
	    }
	    if (plan.getPlanId() != null) {
	        ra.addAttribute("planId", plan.getPlanId());
	    }
	    if (plan.getPlanType() == null || plan.getPlanType() == PlanType.SINGLE_INDEX) {
	        return "redirect:editSingleIndex";
	    }
        else if (plan.getPlanType() == PlanType.MULTI_INDEX) {
            return "redirect:editMultiIndex";
        }
        else if (plan.getPlanType() == PlanType.STOCK_STRATEGY) {
            return "redirect:editStockStrategy";
        }
	    throw new PageNotFoundException();
    }
	
	@GetMapping("/edit{planTypeString}")
	public String editPlanType(@PathVariable String planTypeString, Integer planId) {
	    Optional<PlanType> optional = tryParseEnum(PlanType.class, planTypeString);
	    if (optional.isEmpty()) {
	        throw new PageNotFoundException();
	    }
	    Plan plan = null;
	    if (planId != null) {
	        plan = planService.getById(planId);
	    }
	    if (plan == null) {
	        plan = new Plan();
	    }
	    String planJsonString = "{}";
	    try {
	        planJsonString = objectMapper.writeValueAsString(plan);
	    }
	    catch (Exception e) {}
	    request.setAttribute("plan", plan);
        request.setAttribute("planType", optional.get().toString());
        request.setAttribute("planJsonString", planJsonString);
	    return "/admin/v1/manage/plan/edit" + planTypeString;
	}
	
	@PostMapping("/save")
	@ResponseBody
	public R<?> save(@RequestBody Plan plan) {
	    return super.save(plan);
	}
	
	@PostMapping("/delete")
	@ResponseBody
	public R<?> delete(String planId) {
	    return super.delete(planId);
	}
	
	@PostMapping("/batchOp")
    @ResponseBody
    public R<?> batchOp(
            @RequestParam(value="ids[]", required=true)
            String[] ids, PlanBatchOp op) {
        if (Objects.isNull(ids) || ids.length == 0) {
            throw RException.badRequest("提供的计划 ID 不能为空");
        }
        List<String> idArray = Arrays.asList(ids);
        
        if (op == null) {
            // op 为空是删除
        	throw RException.badRequest("操作类型不能为空");
        }
        else if (PlanBatchOp.DELETE == op) {
            return R.judge(
                    planService.removeBatchByIds(idArray));
        }
        
        LambdaUpdateWrapper<Plan> uw = new LambdaUpdateWrapper<>();
        uw.in(Plan::getPlanId, idArray);
        
        switch (op) {
        case ENABLE:
        	uw.set(Plan::getEnabled, true);
        	break;
        case DISABLE:
            uw.set(Plan::getEnabled, false);
            break;
        case ENABLE_OPEN_DAY_CHECK:
            uw.set(Plan::getOpenDayCheck, true);
            break;
        case DISABLE_OPEN_DAY_CHECK:
            uw.set(Plan::getOpenDayCheck, false);
            break;
    	default:
        	throw RException.badRequest("未知操作");
        }
        return R.judge(() -> planService.update(uw));
    }
	
	private static enum PlanBatchOp implements IQueryableEnum {
		DELETE("删除"),
		ENABLE("启用"),
		DISABLE("停用"),
		ENABLE_OPEN_DAY_CHECK("开启交易日校验"),
		DISABLE_OPEN_DAY_CHECK("关闭交易日校验");
	    
	    private String note;
	    
	    private PlanBatchOp(String note) {
	        this.note = note;
	    }

        @Override
        public String getNote() {
            return note;
        }
	}
	
	/**
	 * 将大驼峰转换为大写+下划线分隔形式
	 * @param s
	 * @return
	 */
	public static String toUpperSnake(String s) {
        if (s == null) return null;
        s = s.trim();
        if (s.isEmpty()) return s;

        // 先把空格/连字符这类统一成下划线（可按需扩展）
        s = s.replace('-', '_').replace(' ', '_');

        // 1) fooBar / foo1Bar -> foo_Bar / foo1_Bar
        s = s.replaceAll("([a-z0-9])([A-Z])", "$1_$2");
        // 2) HTTPServer -> HTTP_Server（在 "P" 和 "S" 之间插）
        s = s.replaceAll("([A-Z]+)([A-Z][a-z])", "$1_$2");

        // 合并多余下划线
        s = s.replaceAll("_+", "_");
        // 去掉首尾下划线
        s = s.replaceAll("^_+|_+$", "");

        return s.toUpperCase(Locale.ROOT);
    }
	
	public static <E extends Enum<E>> Optional<E> tryParseEnum(Class<E> enumClass, String input) {
        if (enumClass == null || input == null) return Optional.empty();

        String raw = input.trim();
        if (raw.isEmpty()) return Optional.empty();

        // 1) 直接按原样尝试（允许用户本来就传了正确的常量名）
        E e = tryValueOf(enumClass, raw);
        if (e != null) return Optional.of(e);

        // 2) 尝试 UPPER_SNAKE_CASE
        String upperSnake = toUpperSnake(raw);
        e = tryValueOf(enumClass, upperSnake);
        if (e != null) return Optional.of(e);

        // 3) 兜底：忽略大小写匹配（成本 O(n)，但很稳）
        for (E constant : enumClass.getEnumConstants()) {
            if (constant.name().equalsIgnoreCase(raw) || constant.name().equalsIgnoreCase(upperSnake)) {
                return Optional.of(constant);
            }
        }
        return Optional.empty();
    }

    private static <E extends Enum<E>> E tryValueOf(Class<E> enumClass, String name) {
        try {
            return Enum.valueOf(enumClass, name);
        } catch (IllegalArgumentException ex) {
            return null;
        }
    }

}
