package com.reading.platform.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.reading.platform.common.enums.ErrorCode;
import com.reading.platform.common.exception.BusinessException;
import com.reading.platform.common.util.PageUtils;
import com.reading.platform.dto.request.ParentCreateRequest;
import com.reading.platform.dto.request.ParentUpdateRequest;
import com.reading.platform.entity.Parent;
import com.reading.platform.entity.ParentStudent;
import com.reading.platform.mapper.ParentMapper;
import com.reading.platform.mapper.ParentStudentMapper;
import com.reading.platform.service.ParentService;
import lombok.RequiredArgsConstructor;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

@Service
@RequiredArgsConstructor
public class ParentServiceImpl implements ParentService {

    private final ParentMapper parentMapper;
    private final ParentStudentMapper parentStudentMapper;
    private final PasswordEncoder passwordEncoder;

    @Override
    @Transactional
    public Parent createParent(Long tenantId, ParentCreateRequest request) {
        // Check if username already exists
        Parent existing = parentMapper.selectOne(
                new LambdaQueryWrapper<Parent>().eq(Parent::getUsername, request.getUsername())
        );
        if (existing != null) {
            throw new BusinessException(ErrorCode.DATA_ALREADY_EXISTS, "Username already exists");
        }

        Parent parent = new Parent();
        parent.setTenantId(tenantId);
        parent.setUsername(request.getUsername());
        parent.setPassword(passwordEncoder.encode(request.getPassword()));
        parent.setName(request.getName());
        parent.setPhone(request.getPhone());
        parent.setEmail(request.getEmail());
        parent.setGender(request.getGender());
        parent.setStatus("active");

        parentMapper.insert(parent);
        return parent;
    }

    @Override
    @Transactional
    public Parent updateParent(Long id, ParentUpdateRequest request) {
        Parent parent = getParentById(id);

        if (StringUtils.hasText(request.getName())) {
            parent.setName(request.getName());
        }
        if (request.getPhone() != null) {
            parent.setPhone(request.getPhone());
        }
        if (request.getEmail() != null) {
            parent.setEmail(request.getEmail());
        }
        if (request.getAvatarUrl() != null) {
            parent.setAvatarUrl(request.getAvatarUrl());
        }
        if (request.getGender() != null) {
            parent.setGender(request.getGender());
        }
        if (StringUtils.hasText(request.getStatus())) {
            parent.setStatus(request.getStatus());
        }

        parentMapper.updateById(parent);
        return parent;
    }

    @Override
    public Parent getParentById(Long id) {
        Parent parent = parentMapper.selectById(id);
        if (parent == null) {
            throw new BusinessException(ErrorCode.USER_NOT_FOUND, "Parent not found");
        }
        return parent;
    }

    @Override
    public Page<Parent> getParentPage(Long tenantId, Integer pageNum, Integer pageSize, String keyword, String status) {
        Page<Parent> page = PageUtils.of(pageNum, pageSize);
        LambdaQueryWrapper<Parent> wrapper = new LambdaQueryWrapper<>();

        wrapper.eq(Parent::getTenantId, tenantId);

        if (StringUtils.hasText(keyword)) {
            wrapper.and(w -> w
                    .like(Parent::getName, keyword)
                    .or()
                    .like(Parent::getUsername, keyword)
                    .or()
                    .like(Parent::getPhone, keyword)
            );
        }
        if (StringUtils.hasText(status)) {
            wrapper.eq(Parent::getStatus, status);
        }
        wrapper.orderByDesc(Parent::getCreatedAt);

        return parentMapper.selectPage(page, wrapper);
    }

    @Override
    @Transactional
    public void deleteParent(Long id) {
        getParentById(id);
        parentMapper.deleteById(id);
    }

    @Override
    @Transactional
    public void resetPassword(Long id, String newPassword) {
        Parent parent = getParentById(id);
        parent.setPassword(passwordEncoder.encode(newPassword));
        parentMapper.updateById(parent);
    }

    @Override
    @Transactional
    public void bindStudent(Long parentId, Long studentId, String relationship, Boolean isPrimary) {
        // Check if already bound
        ParentStudent existing = parentStudentMapper.selectOne(
                new LambdaQueryWrapper<ParentStudent>()
                        .eq(ParentStudent::getParentId, parentId)
                        .eq(ParentStudent::getStudentId, studentId)
        );
        if (existing != null) {
            throw new BusinessException(ErrorCode.DATA_ALREADY_EXISTS, "Student already bound to this parent");
        }

        ParentStudent parentStudent = new ParentStudent();
        parentStudent.setParentId(parentId);
        parentStudent.setStudentId(studentId);
        parentStudent.setRelationship(relationship != null ? relationship : "parent");
        parentStudent.setIsPrimary(isPrimary != null && isPrimary ? 1 : 0);

        parentStudentMapper.insert(parentStudent);
    }

    @Override
    @Transactional
    public void unbindStudent(Long parentId, Long studentId) {
        parentStudentMapper.delete(
                new LambdaQueryWrapper<ParentStudent>()
                        .eq(ParentStudent::getParentId, parentId)
                        .eq(ParentStudent::getStudentId, studentId)
        );
    }

}
