package com.stdproject.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.stdproject.common.OperationLog;
import com.stdproject.common.PageRequest;
import com.stdproject.common.Result;
import com.stdproject.entity.AppDictionary;
import com.stdproject.service.IAppDictionaryService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.List;

/**
 * <p>
 * 应用-数据字典表 前端控制器
 * </p>
 *
 * @author StdProject
 * @since 2023-12-07
 */
@Tag(name = "数据字典管理", description = "数据字典添加、数据字典修改、数据字典删除、数据字典查询等功能")
@RestController
@RequestMapping("/app-dictionary")
public class AppDictionaryController {

    @Autowired
    private IAppDictionaryService appDictionaryService;

    @Operation(summary = "分页查询数据字典列表")
    @PostMapping("/page")
    @OperationLog(type = "06", module = "数据字典管理", description = "分页查询数据字典列表")
    public Result<IPage<AppDictionary>> page(@RequestBody @Valid PageRequest pageRequest) {
        Page<AppDictionary> page = new Page<>(pageRequest.getCurrent(), pageRequest.getSize());
        QueryWrapper<AppDictionary> queryWrapper = new QueryWrapper<>();
        
        // 关键字搜索
        if (StringUtils.hasText(pageRequest.getKeyword())) {
            queryWrapper.and(wrapper -> wrapper
                .like("dictname", pageRequest.getKeyword())
                .or().like("dictcode", pageRequest.getKeyword())
                .or().like("dictdata", pageRequest.getKeyword())
            );
        }
        
        // 排序
        if (StringUtils.hasText(pageRequest.getOrderBy())) {
            if ("asc".equalsIgnoreCase(pageRequest.getOrderDirection())) {
                queryWrapper.orderByAsc(pageRequest.getOrderBy());
            } else {
                queryWrapper.orderByDesc(pageRequest.getOrderBy());
            }
        } else {
            queryWrapper.orderByAsc("dictcode", "orderno");
        }
        
        IPage<AppDictionary> result = appDictionaryService.page(page, queryWrapper);
        return Result.success(result);
    }

    @Operation(summary = "查询所有数据字典列表")
    @GetMapping("/list")
    @OperationLog(type = "06", module = "数据字典管理", description = "查询所有数据字典列表")
    public Result<List<AppDictionary>> list() {
        QueryWrapper<AppDictionary> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByAsc("dictcode", "orderno");
        
        List<AppDictionary> dictionaries = appDictionaryService.list(queryWrapper);
        return Result.success(dictionaries);
    }

    @Operation(summary = "根据ID查询数据字典详情")
    @GetMapping("/{id}")
    @OperationLog(type = "06", module = "数据字典管理", description = "查询数据字典详情")
    public Result<AppDictionary> getById(@Parameter(description = "字典ID") @PathVariable String id) {
        AppDictionary dictionary = appDictionaryService.getById(id);
        return Result.success(dictionary);
    }

    @Operation(summary = "根据字典编码查询字典项列表")
    @GetMapping("/code/{dictCode}")
    @OperationLog(type = "06", module = "数据字典管理", description = "根据字典编码查询字典项列表")
    public Result<List<AppDictionary>> getByDictCode(@Parameter(description = "字典编码") @PathVariable String dictCode) {
        QueryWrapper<AppDictionary> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("dictcode", dictCode);
        queryWrapper.orderByAsc("orderno");
        
        List<AppDictionary> dictionaries = appDictionaryService.list(queryWrapper);
        return Result.success(dictionaries);
    }

    @Operation(summary = "根据字典编码和字典值查询字典项")
    @GetMapping("/code/{dictCode}/data/{dictData}")
    @OperationLog(type = "06", module = "数据字典管理", description = "根据字典编码和字典数据查询字典项")
    public Result<AppDictionary> getByCodeAndData(
            @Parameter(description = "字典编码") @PathVariable String dictCode,
            @Parameter(description = "字典数据") @PathVariable String dictData) {
        QueryWrapper<AppDictionary> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("dictcode", dictCode);
        queryWrapper.eq("dictdata", dictData);
        
        AppDictionary dictionary = appDictionaryService.getOne(queryWrapper);
        return Result.success(dictionary);
    }

    @Operation(summary = "新增数据字典")
    @PostMapping
    @OperationLog(type = "01", module = "数据字典管理", description = "新增数据字典")
    public Result<String> save(@RequestBody @Valid AppDictionary appDictionary) {
        // 检查同一字典编码下的字典值是否已存在
        QueryWrapper<AppDictionary> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("dictcode", appDictionary.getDictcode());
        queryWrapper.eq("dictdata", appDictionary.getDictdata());
        AppDictionary existDictionary = appDictionaryService.getOne(queryWrapper);
        if (existDictionary != null) {
            return Result.error("该字典编码下的字典值已存在");
        }
        
        // 设置默认值
        if (appDictionary.getOrderno() == null) {
            // 获取同一字典编码下的最大序号
            QueryWrapper<AppDictionary> orderQuery = new QueryWrapper<>();
            orderQuery.eq("dictcode", appDictionary.getDictcode());
            orderQuery.orderByDesc("orderno");
            orderQuery.last("LIMIT 1");
            AppDictionary lastDict = appDictionaryService.getOne(orderQuery);
            appDictionary.setOrderno(lastDict != null ? lastDict.getOrderno() + 1 : 1);
        }
        
        appDictionary.setLastmodifydate(LocalDateTime.now());
        boolean success = appDictionaryService.save(appDictionary);
        return success ? Result.success("新增成功") : Result.error("新增失败");
    }

    @Operation(summary = "修改数据字典")
    @PutMapping
    @OperationLog(type = "02", module = "数据字典管理", description = "修改数据字典")
    public Result<String> update(@RequestBody @Valid AppDictionary appDictionary) {
        // 检查字典是否存在
        AppDictionary existDictionary = appDictionaryService.getById(appDictionary.getId());
        if (existDictionary == null) {
            return Result.error("数据字典不存在");
        }
        
        // 如果修改了字典编码或字典值，检查新的组合是否已被其他字典项使用
        if (!existDictionary.getDictcode().equals(appDictionary.getDictcode()) ||
            !existDictionary.getDictdata().equals(appDictionary.getDictdata())) {
            QueryWrapper<AppDictionary> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("dictcode", appDictionary.getDictcode());
            queryWrapper.eq("dictdata", appDictionary.getDictdata());
            queryWrapper.ne("id", appDictionary.getId());
            AppDictionary dictWithSameCodeValue = appDictionaryService.getOne(queryWrapper);
            if (dictWithSameCodeValue != null) {
                return Result.error("该字典编码下的字典数据已被其他字典项使用");
            }
        }
        
        appDictionary.setLastmodifydate(LocalDateTime.now());
        boolean success = appDictionaryService.updateById(appDictionary);
        return success ? Result.success("修改成功") : Result.error("修改失败");
    }

    @Operation(summary = "删除数据字典")
    @DeleteMapping("/{id}")
    @OperationLog(type = "03", module = "数据字典管理", description = "删除数据字典")
    public Result<String> delete(@Parameter(description = "字典ID") @PathVariable String id) {
        boolean success = appDictionaryService.removeById(id);
        return success ? Result.success("删除成功") : Result.error("删除失败");
    }

    @Operation(summary = "批量删除数据字典")
    @DeleteMapping("/batch")
    @OperationLog(type = "03", module = "数据字典管理", description = "批量删除数据字典")
    public Result<String> deleteBatch(@RequestBody List<String> ids) {
        boolean success = appDictionaryService.removeByIds(ids);
        return success ? Result.success("批量删除成功") : Result.error("批量删除失败");
    }

    @Operation(summary = "根据字典编码删除所有字典项")
    @DeleteMapping("/code/{dictCode}")
    @OperationLog(type = "03", module = "数据字典管理", description = "根据字典编码删除所有字典项")
    public Result<String> deleteByDictCode(@Parameter(description = "字典编码") @PathVariable String dictCode) {
        QueryWrapper<AppDictionary> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("dictcode", dictCode);
        
        boolean success = appDictionaryService.remove(queryWrapper);
        return success ? Result.success("删除成功") : Result.error("删除失败");
    }

    @Operation(summary = "根据字典名称获取字典数据")
    @GetMapping("/name/{dictName}")
    @OperationLog(type = "06", module = "数据字典管理", description = "根据字典名称获取字典数据")
    public Result<String> getDictDataByName(@Parameter(description = "字典名称") @PathVariable String dictName) {
        QueryWrapper<AppDictionary> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("dictname", dictName);
        AppDictionary dictionary = appDictionaryService.getOne(queryWrapper);
        
        if (dictionary != null) {
            return Result.success(dictionary.getDictdata());
        }
        return Result.error("未找到对应的字典数据");
    }

    @Operation(summary = "获取所有字典编码列表")
    @GetMapping("/codes")
    @OperationLog(type = "06", module = "数据字典管理", description = "获取所有字典编码列表")
    public Result<List<String>> getDictCodes() {
        QueryWrapper<AppDictionary> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("DISTINCT dictcode");
        queryWrapper.orderByAsc("dictcode");
        
        List<AppDictionary> dictionaries = appDictionaryService.list(queryWrapper);
        List<String> dictCodes = dictionaries.stream()
            .map(AppDictionary::getDictcode)
            .distinct()
            .collect(java.util.stream.Collectors.toList());
        
        return Result.success(dictCodes);
    }

    @Operation(summary = "调整字典项顺序")
    @PutMapping("/reorder")
    @OperationLog(type = "02", module = "数据字典管理", description = "调整字典项顺序")
    public Result<String> reorder(@RequestBody List<DictOrderRequest> orderRequests) {
        for (DictOrderRequest request : orderRequests) {
            AppDictionary dictionary = appDictionaryService.getById(request.getId());
            if (dictionary != null) {
                dictionary.setOrderno(request.getOrderno());
                dictionary.setLastmodifydate(LocalDateTime.now());
                appDictionaryService.updateById(dictionary);
            }
        }
        return Result.success("顺序调整成功");
    }

    @Operation(summary = "根据字典编码分组查询字典项")
    @GetMapping("/grouped")
    @OperationLog(type = "06", module = "数据字典管理", description = "根据字典编码分组查询字典项")
    public Result<java.util.Map<String, List<AppDictionary>>> getGroupedDictionaries() {
        QueryWrapper<AppDictionary> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByAsc("dictcode", "orderno");
        
        List<AppDictionary> allDictionaries = appDictionaryService.list(queryWrapper);
        java.util.Map<String, List<AppDictionary>> groupedDict = allDictionaries.stream()
            .collect(java.util.stream.Collectors.groupingBy(AppDictionary::getDictcode));
        
        return Result.success(groupedDict);
    }

    /**
     * 字典排序请求
     */
    public static class DictOrderRequest {
        private String id;
        private Integer orderno;

        public String getId() { return id; }
        public void setId(String id) { this.id = id; }
        public Integer getOrderno() { return orderno; }
        public void setOrderno(Integer orderno) { this.orderno = orderno; }
    }
}