package com.ga.api.service.training;

import com.ga.common.exception.BizException;
import com.ga.common.exception.ErrorCode;
import com.ga.common.model.PageResponse;
import com.ga.core.mapper.training.AgentTrainingMapper;
import com.ga.core.mapper.training.TrainingRequirementMapper;
import com.ga.core.vo.training.*;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class AgentTrainingService {

    private final AgentTrainingMapper trainingMapper;
    private final TrainingRequirementMapper requirementMapper;

    // ── Training ──────────────────────────────────────────────────────────────

    public PageResponse<AgentTrainingResp> list(AgentTrainingSearchParam param) {
        param.startPage();
        return PageResponse.of(trainingMapper.selectList(param));
    }

    public AgentTrainingResp detail(Long trainingId) {
        AgentTrainingResp resp = trainingMapper.selectById(trainingId);
        if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
        return resp;
    }

    /**
     * 설계사 + 연도 기준 연간 이수 시간 합계.
     * 의무 시간 충족 여부도 함께 반환.
     */
    public BigDecimal annualHours(Long agentId, int year) {
        BigDecimal hours = trainingMapper.selectAnnualHoursByAgent(agentId, year);
        return hours != null ? hours : BigDecimal.ZERO;
    }

    @Transactional
    public Long create(AgentTrainingSaveReq req) {
        AgentTrainingVO vo = new AgentTrainingVO();
        vo.setAgentId(req.getAgentId());
        vo.setCourseName(req.getCourseName());
        vo.setCourseType(req.getCourseType());
        vo.setTrainingDate(req.getTrainingDate());
        vo.setHours(req.getHours());
        vo.setCertificateNo(req.getCertificateNo());
        vo.setInstructor(req.getInstructor());
        trainingMapper.insert(vo);
        return vo.getTrainingId();
    }

    @Transactional
    public void update(Long trainingId, AgentTrainingSaveReq req) {
        AgentTrainingResp existing = trainingMapper.selectById(trainingId);
        if (existing == null) throw new BizException(ErrorCode.NOT_FOUND);
        AgentTrainingVO vo = new AgentTrainingVO();
        vo.setTrainingId(trainingId);
        vo.setAgentId(req.getAgentId());
        vo.setCourseName(req.getCourseName());
        vo.setCourseType(req.getCourseType());
        vo.setTrainingDate(req.getTrainingDate());
        vo.setHours(req.getHours());
        vo.setCertificateNo(req.getCertificateNo());
        vo.setInstructor(req.getInstructor());
        trainingMapper.update(vo);
    }

    @Transactional
    public void delete(Long trainingId) {
        AgentTrainingResp existing = trainingMapper.selectById(trainingId);
        if (existing == null) throw new BizException(ErrorCode.NOT_FOUND);
        trainingMapper.delete(trainingId);
    }

    // ── Requirement ───────────────────────────────────────────────────────────

    public List<TrainingRequirementResp> listRequirements(TrainingRequirementSearchParam param) {
        return requirementMapper.selectList(param);
    }

    public TrainingRequirementResp requirementByYear(int year) {
        TrainingRequirementResp resp = requirementMapper.selectByYear(year);
        if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
        return resp;
    }

    @Transactional
    public void saveRequirement(TrainingRequirementSaveReq req) {
        TrainingRequirementVO existing = new TrainingRequirementVO();
        existing.setTargetYear(req.getTargetYear());
        existing.setRequiredHours(req.getRequiredHours());
        existing.setDescription(req.getDescription());
        // upsert: try update first, insert if 0 rows
        TrainingRequirementResp curr = requirementMapper.selectByYear(req.getTargetYear());
        if (curr == null) {
            requirementMapper.insert(existing);
        } else {
            existing.setReqId(curr.getReqId());
            requirementMapper.update(existing);
        }
    }
}
