package com.nbport.zgwl.manifest.service;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.nbport.zgwl.common.PageResult;
import com.nbport.zgwl.exception.ServiceException;
import com.nbport.zgwl.manifest.dto.ContractTemplateDto;
import com.nbport.zgwl.manifest.dto.ContractTemplateQueryDto;
import com.nbport.zgwl.manifest.dto.TemplateOrgOptionDto;
import com.nbport.zgwl.manifest.handler.ContractTemplateDataHandler;
import com.nbport.zgwl.manifest.mapper.ContractTemplateMapper;
import com.nbport.zgwl.manifest.utils.ManifestCodeUtils;
import com.nbport.zgwl.manifest.utils.ManifestJsonUtils;
import com.nbport.zgwl.manifest.utils.ManifestManageConstants;
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.List;

/**
 * 模板管理 Service 实现
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ContractTemplateServiceImpl implements ContractTemplateService {

    private final ContractTemplateMapper contractTemplateMapper;

    private final ContractTemplateDataHandler contractTemplateDataHandler;

    /** 分页查询模板列表 */
    @Override
    public PageResult<ContractTemplateDto> queryTemplateList(ContractTemplateQueryDto queryDto) {
        Page<ContractTemplateDto> page = new Page<>(queryDto.getPageNo(), queryDto.getPageSize());
        Page<ContractTemplateDto> resultPage = (Page<ContractTemplateDto>) contractTemplateMapper.selectTemplatePage(page, queryDto);
        PageResult<ContractTemplateDto> pageResult = new PageResult<>(resultPage);
        contractTemplateDataHandler.fillUiFields(pageResult.getData());
        return pageResult;
    }

    /** 已发布的模板列表 */
    @Override
    public List<ContractTemplateDto> queryPublishedTemplates() {
        List<ContractTemplateDto> templates = contractTemplateMapper.selectPublishedTemplates();
        contractTemplateDataHandler.fillUiFields(templates);
        return templates;
    }

    /** 获取模板详情（含发布范围、变量映射的解析结果） */
    @Override
    public ContractTemplateDto getTemplateDetail(Long id) {
        ContractTemplateDto template = contractTemplateMapper.selectTemplateById(id);
        if (template == null) {
            throw new ServiceException("模板不存在");
        }
        contractTemplateDataHandler.fillUiFields(template);
        return template;
    }

    /** 新增模板（自动生成模板编号、保存 JSON 字段） */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ContractTemplateDto createTemplate(ContractTemplateDto template) {
        contractTemplateDataHandler.normalizeBeforeSave(template);
        contractTemplateDataHandler.fillOrgNamesByIds(template, queryOrgOptions());
        contractTemplateDataHandler.validateForSave(template);

        LocalDateTime now = LocalDateTime.now();
        template.setId(contractTemplateMapper.selectTemplateSeqNextVal());
        template.setTemplateCode(ManifestCodeUtils.buildTemplateCode(template.getContractType()));
        template.setCreateBy(ManifestManageConstants.DEFAULT_OPERATOR);
        template.setCreatedTime(now);
        template.setUpdatedBy(ManifestManageConstants.DEFAULT_OPERATOR);
        template.setUpdatedTime(now);
        template.setDelFlag(ManifestManageConstants.DEL_FLAG_NORMAL);
        saveJsonFields(template);

        contractTemplateMapper.insertTemplate(template);
        return getTemplateDetail(template.getId());
    }

    /** 修改模板（保留原有的 templateCode、创建人、创建时间不变） */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ContractTemplateDto updateTemplate(ContractTemplateDto template) {
        if (template.getId() == null) {
            throw new ServiceException("修改模板时 id 不能为空");
        }

        ContractTemplateDto dbTemplate = contractTemplateMapper.selectTemplateById(template.getId());
        if (dbTemplate == null) {
            throw new ServiceException("模板不存在");
        }

        contractTemplateDataHandler.normalizeBeforeSave(template);
        contractTemplateDataHandler.fillOrgNamesByIds(template, queryOrgOptions());
        contractTemplateDataHandler.validateForSave(template);

        template.setTemplateCode(dbTemplate.getTemplateCode());
        template.setCreateBy(dbTemplate.getCreateBy());
        template.setCreatedTime(dbTemplate.getCreatedTime());
        template.setUpdatedBy(ManifestManageConstants.DEFAULT_OPERATOR);
        template.setUpdatedTime(LocalDateTime.now());
        template.setDelFlag(dbTemplate.getDelFlag());
        saveJsonFields(template);

        contractTemplateMapper.updateTemplate(template);
        return getTemplateDetail(template.getId());
    }

    /** 切换模板状态（draft / published / disabled） */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ContractTemplateDto changeTemplateStatus(Long id, String status) {
        if (!ManifestManageConstants.STATUS_DRAFT.equals(status)
                && !ManifestManageConstants.STATUS_PUBLISHED.equals(status)
                && !ManifestManageConstants.STATUS_DISABLED.equals(status)) {
            throw new ServiceException("模板状态不合法");
        }

        ContractTemplateDto dbTemplate = contractTemplateMapper.selectTemplateById(id);
        if (dbTemplate == null) {
            throw new ServiceException("模板不存在");
        }

        contractTemplateMapper.updateTemplateStatus(
                id,
                status,
                ManifestManageConstants.DEFAULT_OPERATOR,
                LocalDateTime.now()
        );
        return getTemplateDetail(id);
    }

    /** 获取发布范围组织选项（当前为假数据，内网联调时替换为真实组织接口） */
    @Override
    public List<TemplateOrgOptionDto> queryOrgOptions() {
        return List.of(
                new TemplateOrgOptionDto("ORG001", "浙港物流平台有限公司"),
                new TemplateOrgOptionDto("ORG002", "宁波舟山港集团有限公司"),
                new TemplateOrgOptionDto("ORG003", "浙江省海港投资运营集团有限公司"),
                new TemplateOrgOptionDto("ORG004", "宁波港东南物流集团有限公司")
        );
    }

    /** 将 JSON 字段转为文本存入数据库 */
    private void saveJsonFields(ContractTemplateDto template) {
        template.setPublishOrgIdsJson(ManifestJsonUtils.toJson(template.getPublishOrgIds()));
        template.setPublishOrgNamesJson(ManifestJsonUtils.toJson(template.getPublishOrgNames()));
        template.setVariableMappingsJson(ManifestJsonUtils.toJson(template.getVariableMappings()));
    }
}
