package com.campus.activity.service.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.campus.activity.common.ResultCode;
import com.campus.activity.dto.request.RegistrationRequest;
import com.campus.activity.entity.Activity;
import com.campus.activity.entity.Registration;
import com.campus.activity.entity.User;
import com.campus.activity.exception.BusinessException;
import com.campus.activity.mapper.ActivityMapper;
import com.campus.activity.mapper.RegistrationMapper;
import com.campus.activity.service.ActivityService;
import com.campus.activity.service.AuthService;
import com.campus.activity.service.RegistrationService;
import com.campus.activity.util.PdfUtil;
import com.campus.activity.vo.RegistrationVO;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

@Service
@RequiredArgsConstructor
public class RegistrationServiceImpl implements RegistrationService {

    private final RegistrationMapper registrationMapper;
    private final ActivityMapper activityMapper;
    private final AuthService authService;
    private final ActivityService activityService;

    @Override
    @Transactional
    public RegistrationVO register(RegistrationRequest request) {
        User currentUser = authService.getCurrentUser();

        Activity activity = activityMapper.selectById(request.getActivityId());
        if (activity == null || activity.getDeleted() == 1) {
            throw new BusinessException(ResultCode.ACTIVITY_NOT_FOUND);
        }

        if (activity.getStatus() != 1) {
            throw new BusinessException(ResultCode.BAD_REQUEST.getCode(), "活动不在报名中");
        }

        if (activity.getRegistrationDeadline() != null &&
            LocalDateTime.now().isAfter(activity.getRegistrationDeadline())) {
            throw new BusinessException(ResultCode.BAD_REQUEST.getCode(), "报名已截止");
        }

        if (activity.getCurrentParticipants() >= activity.getMaxParticipants()) {
            throw new BusinessException(ResultCode.ACTIVITY_FULL);
        }

        Registration existingRegistration = registrationMapper.selectOne(
                new LambdaQueryWrapper<Registration>()
                        .eq(Registration::getUserId, currentUser.getId())
                        .eq(Registration::getActivityId, request.getActivityId())
                        .in(Registration::getStatus, 1, 2)
        );

        if (existingRegistration != null) {
            throw new BusinessException(ResultCode.ALREADY_REGISTERED);
        }

        List<Registration> myRegistrations = registrationMapper.selectList(
                new LambdaQueryWrapper<Registration>()
                        .eq(Registration::getUserId, currentUser.getId())
                        .eq(Registration::getStatus, 1)
        );

        for (Registration reg : myRegistrations) {
            Activity myActivity = activityMapper.selectById(reg.getActivityId());
            if (isTimeConflict(activity, myActivity)) {
                throw new BusinessException(ResultCode.ACTIVITY_TIME_CONFLICT);
            }
        }

        Registration registration = new Registration();
        registration.setUserId(currentUser.getId());
        registration.setActivityId(request.getActivityId());
        registration.setTicketCode(generateTicketCode());
        registration.setStatus(1);

        registrationMapper.insert(registration);

        activity.setCurrentParticipants(activity.getCurrentParticipants() + 1);
        activityMapper.updateById(activity);

        return convertToVO(registration, activity);
    }

    @Override
    @Transactional
    public void cancelRegistration(Long id) {
        User currentUser = authService.getCurrentUser();

        Registration registration = registrationMapper.selectById(id);
        if (registration == null) {
            throw new BusinessException(ResultCode.REGISTRATION_NOT_FOUND);
        }

        if (!registration.getUserId().equals(currentUser.getId())) {
            throw new BusinessException(ResultCode.FORBIDDEN);
        }

        if (registration.getStatus() != 1) {
            throw new BusinessException(ResultCode.BAD_REQUEST.getCode(), "无法取消当前报名");
        }

        Activity activity = activityMapper.selectById(registration.getActivityId());
        if (activity == null || activity.getDeleted() == 1) {
            throw new BusinessException(ResultCode.ACTIVITY_NOT_FOUND);
        }

        if (LocalDateTime.now().isAfter(activity.getStartTime())) {
            throw new BusinessException(ResultCode.ACTIVITY_ALREADY_STARTED);
        }

        registration.setStatus(0);
        registration.setCanceledAt(LocalDateTime.now());
        registrationMapper.updateById(registration);

        activity.setCurrentParticipants(Math.max(0, activity.getCurrentParticipants() - 1));
        activityMapper.updateById(activity);
    }

    @Override
    public IPage<RegistrationVO> getMyRegistrations(Page<Registration> page, Integer status) {
        User currentUser = authService.getCurrentUser();
        return registrationMapper.selectMyRegistrations(page, currentUser.getId(), status);
    }

    @Override
    public IPage<RegistrationVO> getActivityRegistrations(Page<Registration> page, Long activityId) {
        return registrationMapper.selectActivityRegistrations(page, activityId);
    }

    @Override
    public byte[] generateTicketPdf(Long id) {
        User currentUser = authService.getCurrentUser();

        Registration registration = registrationMapper.selectById(id);
        if (registration == null) {
            throw new BusinessException(ResultCode.REGISTRATION_NOT_FOUND);
        }

        if (!registration.getUserId().equals(currentUser.getId())) {
            throw new BusinessException(ResultCode.FORBIDDEN);
        }

        if (registration.getStatus() != 1) {
            throw new BusinessException(ResultCode.BAD_REQUEST.getCode(), "报名状态异常");
        }

        Activity activity = activityMapper.selectById(registration.getActivityId());
        if (activity == null || activity.getDeleted() == 1) {
            throw new BusinessException(ResultCode.ACTIVITY_NOT_FOUND);
        }

        return PdfUtil.generateTicketPdf(currentUser, activity, registration);
    }

    private String generateTicketCode() {
        return "TK" + DateUtil.format(LocalDateTime.now(), "yyyyMMddHHmmss") +
               String.format("%04d", (int)(Math.random() * 10000));
    }

    private boolean isTimeConflict(Activity activity1, Activity activity2) {
        return !(activity1.getEndTime().isBefore(activity2.getStartTime()) ||
                activity1.getStartTime().isAfter(activity2.getEndTime()));
    }

    private RegistrationVO convertToVO(Registration registration, Activity activity) {
        RegistrationVO vo = new RegistrationVO();
        BeanUtils.copyProperties(registration, vo);
        vo.setActivityTitle(activity.getTitle());
        vo.setActivityStartTime(activity.getStartTime());
        vo.setActivityEndTime(activity.getEndTime());
        vo.setActivityLocation(activity.getLocation());
        return vo;
    }
}