package com.pangu.application.service.impl;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pangu.application.domain.dto.ApplicationDTO;
import com.pangu.application.domain.entity.ApiDict;
import com.pangu.application.domain.entity.AppApi;
import com.pangu.application.domain.entity.Application;
import com.pangu.application.domain.vo.ApplicationVO;
import com.pangu.application.mapper.ApiDictMapper;
import com.pangu.application.mapper.AppApiMapper;
import com.pangu.application.mapper.ApplicationMapper;
import com.pangu.application.service.IApplicationService;
import com.pangu.common.core.exception.ServiceException;
import com.pangu.common.core.page.TableDataInfo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * 应用服务实现
 * 
 * @author pangu
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ApplicationServiceImpl extends ServiceImpl<ApplicationMapper, Application> implements IApplicationService {

    private final ApplicationMapper applicationMapper;
    private final AppApiMapper appApiMapper;
    private final ApiDictMapper apiDictMapper;

    @Override
    public TableDataInfo selectApplicationList(ApplicationDTO applicationDTO) {
        Page<ApplicationVO> page = new Page<>(
            applicationDTO.getPageNum() != null ? applicationDTO.getPageNum() : 1,
            applicationDTO.getPageSize() != null ? applicationDTO.getPageSize() : 10
        );
        List<ApplicationVO> list = applicationMapper.selectApplicationVOList(page, applicationDTO);
        return new TableDataInfo(list, page.getTotal());
    }

    @Override
    public ApplicationVO getApplicationById(Long appId) {
        return applicationMapper.selectApplicationVOById(appId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ApplicationVO insertApplication(ApplicationDTO applicationDTO) {
        // 生成应用编码
        String appCode = generateAppCode();
        
        // 生成应用密钥
        String appSecret = generateAppSecret();
        
        // 构建应用对象
        Application application = buildApplication(applicationDTO);
        application.setAppCode(appCode);
        application.setAppSecret(appSecret);
        application.setStatus("0");
        
        // 保存应用
        int result = applicationMapper.insert(application);
        if (result <= 0) {
            throw new ServiceException("新增应用失败");
        }
        
        // 保存接口授权
        saveAppApis(application.getAppId(), applicationDTO.getApiIds());
        
        log.info("新增应用成功, appId={}, appCode={}", application.getAppId(), appCode);
        
        // 返回应用信息（包含密钥）
        ApplicationVO vo = new ApplicationVO();
        vo.setAppId(application.getAppId());
        vo.setAppCode(appCode);
        vo.setAppName(application.getAppName());
        vo.setAppSecret(appSecret);
        return vo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateApplication(ApplicationDTO applicationDTO) {
        // 构建应用对象
        Application application = buildApplication(applicationDTO);
        application.setAppId(applicationDTO.getAppId());
        
        // 更新应用
        int result = applicationMapper.updateById(application);
        if (result <= 0) {
            throw new ServiceException("修改应用失败");
        }
        
        // 更新接口授权
        appApiMapper.deleteByAppId(application.getAppId());
        saveAppApis(application.getAppId(), applicationDTO.getApiIds());
        
        log.info("修改应用成功, appId={}, appName={}", application.getAppId(), application.getAppName());
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteApplication(Long appId) {
        // 软删除应用
        Application application = new Application();
        application.setAppId(appId);
        application.setDelFlag("1");
        int result = applicationMapper.updateById(application);
        
        // 删除接口授权
        appApiMapper.deleteByAppId(appId);
        
        log.info("删除应用成功, appId={}", appId);
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String resetSecret(Long appId) {
        // 生成新密钥
        String newSecret = generateAppSecret();
        
        // 更新密钥
        Application application = new Application();
        application.setAppId(appId);
        application.setAppSecret(newSecret);
        int result = applicationMapper.updateById(application);
        
        if (result <= 0) {
            throw new ServiceException("重置密钥失败");
        }
        
        log.info("重置应用密钥成功, appId={}", appId);
        return newSecret;
    }

    @Override
    public List<ApiDict> getApiList() {
        LambdaQueryWrapper<ApiDict> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ApiDict::getStatus, "0");
        wrapper.orderByAsc(ApiDict::getSortOrder);
        return apiDictMapper.selectList(wrapper);
    }

    @Override
    public boolean checkAppCodeUnique(String appCode, Long appId) {
        int count = applicationMapper.countByAppCode(appCode, appId);
        return count == 0;
    }

    /**
     * 生成应用编码
     * 格式：YY + 6位序号
     */
    private String generateAppCode() {
        int seq = applicationMapper.getNextCodeSeq();
        return String.format("YY%06d", seq);
    }

    /**
     * 生成应用密钥
     * 32位随机字符串
     */
    private String generateAppSecret() {
        return RandomUtil.randomString(32);
    }

    /**
     * 构建应用对象
     */
    private Application buildApplication(ApplicationDTO dto) {
        Application application = new Application();
        application.setAppName(dto.getAppName());
        application.setContactPerson(dto.getContactPerson());
        application.setContactPhone(dto.getContactPhone());
        application.setRemark(dto.getRemark());
        return application;
    }

    /**
     * 保存接口授权
     */
    private void saveAppApis(Long appId, List<Long> apiIds) {
        if (apiIds == null || apiIds.isEmpty()) {
            return;
        }
        
        List<AppApi> list = new ArrayList<>();
        LocalDateTime now = LocalDateTime.now();
        for (Long apiId : apiIds) {
            AppApi appApi = new AppApi();
            appApi.setAppId(appId);
            appApi.setApiId(apiId);
            appApi.setCreateTime(now);
            list.add(appApi);
        }
        
        appApiMapper.batchInsert(list);
    }
}
