package com.ruoyi.web.modules.farming.service.impl;

import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.web.modules.farming.domain.BizTechResource;
import com.ruoyi.web.modules.farming.mapper.BizTechResourceMapper;
import com.ruoyi.web.modules.farming.service.IBizTechResourceService;
import com.ruoyi.web.modules.farming.support.TechResourceAccountAssigner;
import com.ruoyi.web.modules.farming.support.TechResourceMultiValueCodec;
import com.ruoyi.web.modules.farming.support.TechResourcePublishStatusResolver;
import com.ruoyi.web.modules.farming.support.TechResourceReferenceChecker;
import com.ruoyi.web.modules.farming.support.TechResourceRules;
import com.ruoyi.web.modules.farming.support.TechResourceCourseTopicValidator;
import com.ruoyi.web.modules.farming.support.TechResourceTypeValidator;
import com.ruoyi.web.modules.farming.support.TechResourceValidation;

/**
 * 畜牧科技资源服务实现。
 */
@Service
public class BizTechResourceServiceImpl implements IBizTechResourceService
{
    @Autowired
    private BizTechResourceMapper bizTechResourceMapper;

    @Autowired
    private TechResourceReferenceChecker referenceChecker;

    @Autowired
    private TechResourceAccountAssigner accountAssigner;

    @Autowired
    private TechResourceTypeValidator techResourceTypeValidator;

    @Autowired
    private TechResourceCourseTopicValidator techResourceCourseTopicValidator;

    @Override
    public BizTechResource selectBizTechResourceById(Long id)
    {
        BizTechResource row = bizTechResourceMapper.selectBizTechResourceById(id);
        enrichRow(row);
        return row;
    }

    @Override
    public List<BizTechResource> selectBizTechResourceList(BizTechResource query)
    {
        // 列表入参校验与类型校验须在 Controller 中、startPage() 之前完成（避免 PageHelper 分页错位）
        List<BizTechResource> list = bizTechResourceMapper.selectBizTechResourceList(query);
        if (list != null)
        {
            for (BizTechResource row : list)
            {
                enrichRow(row);
            }
        }
        return list;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertBizTechResource(BizTechResource row)
    {
        techResourceTypeValidator.assertAllowed(row.getResourceType());
        assertCourseTopicIfVideo(row);
        TechResourceValidation.validateRowForSave(row);
        row.setPublishStatus(TechResourceRules.PUBLISH_STATUS_DRAFT);
        row.setPublishTime(null);
        row.setOfflineTime(null);
        row.setAccountAssigned(TechResourceRules.ACCOUNT_ASSIGNED_NO);
        row.setSysUserId(null);
        row.setAssignedLoginName(null);
        row.setDelFlag(TechResourceRules.DEL_FLAG_NORMAL);
        applyDefaultExpertRating(row);
        return bizTechResourceMapper.insertBizTechResource(row);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateBizTechResource(BizTechResource row)
    {
        if (row.getId() == null)
        {
            throw new ServiceException("主键不能为空");
        }
        BizTechResource db = requireRow(row.getId());
        TechResourceValidation.validateForUpdate(db);
        TechResourceValidation.validateResourceTypeUnchanged(db, row);
        row.setResourceType(db.getResourceType());
        assertCourseTopicIfVideo(row);
        TechResourceValidation.validateRowForSave(row);

        String oldPhoto = db.getPhotoFilePath();
        String oldCover = db.getCoverFilePath();
        String oldVideo = db.getVideoFilePath();

        row.setPublishStatus(db.getPublishStatus());
        row.setPublishTime(db.getPublishTime());
        row.setOfflineTime(db.getOfflineTime());
        row.setAccountAssigned(db.getAccountAssigned());
        row.setSysUserId(db.getSysUserId());
        row.setAssignedLoginName(db.getAssignedLoginName());
        row.setDelFlag(db.getDelFlag());

        int n = bizTechResourceMapper.updateBizTechResource(row);
        if (n > 0)
        {
            deleteIfReplaced(oldPhoto, row.getPhotoFilePath());
            deleteIfReplaced(oldCover, row.getCoverFilePath());
            deleteIfReplaced(oldVideo, row.getVideoFilePath());
        }
        return n;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteBizTechResourceByIds(Long[] ids, String updateBy)
    {
        if (ids == null || ids.length == 0)
        {
            return 0;
        }
        List<Long> cleaned = new ArrayList<>();
        for (Long id : ids)
        {
            if (id != null)
            {
                cleaned.add(id);
            }
        }
        if (cleaned.isEmpty())
        {
            return 0;
        }
        for (Long id : cleaned)
        {
            BizTechResource row = bizTechResourceMapper.selectBizTechResourceByIdAny(id);
            if (row == null || TechResourceRules.DEL_FLAG_DELETED.equals(row.getDelFlag()))
            {
                continue;
            }
            TechResourceValidation.validateForDelete(row);
            if (referenceChecker.hasReference(id))
            {
                throw new ServiceException("存在关联业务，无法删除");
            }
            accountAssigner.deleteLinkedAccount(row);
            deleteDiskFile(row.getPhotoFilePath());
            deleteDiskFile(row.getCoverFilePath());
            deleteDiskFile(row.getVideoFilePath());
        }
        return bizTechResourceMapper.logicDeleteBizTechResourceByIds(
                cleaned.toArray(new Long[0]), updateBy);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int publish(Long id)
    {
        BizTechResource row = requireRow(id);
        TechResourceValidation.validateForPublish(row);
        TechResourceMultiValueCodec.decodeLists(row);
        assertCourseTopicIfVideo(row);
        TechResourceValidation.validateRowForSave(row);
        row.setPublishStatus(TechResourceRules.PUBLISH_STATUS_PUBLISHED);
        row.setPublishTime(new Date());
        row.setOfflineTime(null);
        int n = bizTechResourceMapper.updateBizTechResource(row);
        enrichRow(row);
        return n;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int offline(Long id)
    {
        BizTechResource row = requireRow(id);
        TechResourceValidation.validateForOffline(row);
        Date publishTime = row.getPublishTime();
        row.setPublishStatus(TechResourceRules.PUBLISH_STATUS_DRAFT);
        row.setOfflineTime(new Date());
        row.setPublishTime(publishTime);
        int n = bizTechResourceMapper.updateBizTechResource(row);
        enrichRow(row);
        return n;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int assignAccount(Long id, String operator)
    {
        BizTechResource row = requireRow(id);
        TechResourceValidation.validateForAssignAccount(row);
        SysUser user = accountAssigner.createAccount(row, operator);
        row.setAccountAssigned(TechResourceRules.ACCOUNT_ASSIGNED_YES);
        row.setSysUserId(user.getUserId());
        row.setAssignedLoginName(user.getUserName());
        row.setUpdateBy(operator);
        return bizTechResourceMapper.updateBizTechResource(row);
    }

    private BizTechResource requireRow(Long id)
    {
        BizTechResource row = bizTechResourceMapper.selectBizTechResourceById(id);
        if (row == null)
        {
            throw new ServiceException("记录不存在或已删除");
        }
        return row;
    }

    private void assertCourseTopicIfVideo(BizTechResource row)
    {
        if (TechResourceRules.RESOURCE_TYPE_VIDEO.equals(row.getResourceType()))
        {
            techResourceCourseTopicValidator.assertAllowed(row.getCourseTopic());
        }
    }

    private static void applyDefaultExpertRating(BizTechResource row)
    {
        if (TechResourceRules.RESOURCE_TYPE_EXPERT.equals(row.getResourceType())
                && row.getExpertRating() == null)
        {
            row.setExpertRating(TechResourceRules.DEFAULT_EXPERT_RATING);
        }
    }

    private void enrichRow(BizTechResource row)
    {
        if (row != null)
        {
            TechResourceMultiValueCodec.decodeLists(row);
            TechResourcePublishStatusResolver.applyDisplayStatus(row);
        }
    }

    private void deleteIfReplaced(String oldPath, String newPath)
    {
        if (!StringUtils.equals(StringUtils.nvl(oldPath, ""), StringUtils.nvl(newPath, "")))
        {
            deleteDiskFile(oldPath);
        }
    }

    private void deleteDiskFile(String resourcePath)
    {
        if (StringUtils.isEmpty(resourcePath) || !resourcePath.startsWith(Constants.RESOURCE_PREFIX))
        {
            return;
        }
        String relative = FileUtils.stripPrefix(resourcePath);
        while (relative.startsWith("/") || relative.startsWith("\\"))
        {
            relative = relative.substring(1);
        }
        String full = RuoYiConfig.getProfile() + File.separator + relative.replace("/", File.separator);
        FileUtils.deleteFile(full);
    }
}
