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.TenantCreateRequest;
import com.reading.platform.dto.request.TenantUpdateRequest;
import com.reading.platform.dto.response.TenantResponse;
import com.reading.platform.entity.Tenant;
import com.reading.platform.mapper.TenantMapper;
import com.reading.platform.service.TenantService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class TenantServiceImpl implements TenantService {

    private final TenantMapper tenantMapper;

    @Override
    @Transactional
    public Tenant createTenant(TenantCreateRequest request) {
        // Check if code already exists
        Tenant existing = tenantMapper.selectOne(
                new LambdaQueryWrapper<Tenant>().eq(Tenant::getCode, request.getCode())
        );
        if (existing != null) {
            throw new BusinessException(ErrorCode.DATA_ALREADY_EXISTS, "Tenant code already exists");
        }

        Tenant tenant = new Tenant();
        tenant.setName(request.getName());
        tenant.setCode(request.getCode());
        tenant.setContactName(request.getContactName());
        tenant.setContactPhone(request.getContactPhone());
        tenant.setContactEmail(request.getContactEmail());
        tenant.setAddress(request.getAddress());
        tenant.setLogoUrl(request.getLogoUrl());
        tenant.setExpireAt(request.getExpireAt());
        tenant.setMaxStudents(request.getMaxStudents() != null ? request.getMaxStudents() : 0);
        tenant.setMaxTeachers(request.getMaxTeachers() != null ? request.getMaxTeachers() : 0);
        tenant.setStatus("active");

        tenantMapper.insert(tenant);
        return tenant;
    }

    @Override
    @Transactional
    public Tenant updateTenant(Long id, TenantUpdateRequest request) {
        Tenant tenant = getTenantById(id);

        if (StringUtils.hasText(request.getName())) {
            tenant.setName(request.getName());
        }
        if (request.getContactName() != null) {
            tenant.setContactName(request.getContactName());
        }
        if (request.getContactPhone() != null) {
            tenant.setContactPhone(request.getContactPhone());
        }
        if (request.getContactEmail() != null) {
            tenant.setContactEmail(request.getContactEmail());
        }
        if (request.getAddress() != null) {
            tenant.setAddress(request.getAddress());
        }
        if (request.getLogoUrl() != null) {
            tenant.setLogoUrl(request.getLogoUrl());
        }
        if (StringUtils.hasText(request.getStatus())) {
            tenant.setStatus(request.getStatus());
        }
        if (request.getExpireAt() != null) {
            tenant.setExpireAt(request.getExpireAt());
        }
        if (request.getMaxStudents() != null) {
            tenant.setMaxStudents(request.getMaxStudents());
        }
        if (request.getMaxTeachers() != null) {
            tenant.setMaxTeachers(request.getMaxTeachers());
        }

        tenantMapper.updateById(tenant);
        return tenant;
    }

    @Override
    public Tenant getTenantById(Long id) {
        Tenant tenant = tenantMapper.selectById(id);
        if (tenant == null) {
            throw new BusinessException(ErrorCode.TENANT_NOT_FOUND);
        }
        return tenant;
    }

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

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

        return tenantMapper.selectPage(page, wrapper);
    }

    @Override
    @Transactional
    public void deleteTenant(Long id) {
        Tenant tenant = getTenantById(id);
        tenantMapper.deleteById(id);
    }

    @Override
    public List<TenantResponse> getAllActiveTenants() {
        List<Tenant> tenants = tenantMapper.selectList(
                new LambdaQueryWrapper<Tenant>()
                        .eq(Tenant::getStatus, "active")
                        .orderByAsc(Tenant::getName)
        );
        return tenants.stream()
                .map(this::toResponse)
                .collect(Collectors.toList());
    }

    private TenantResponse toResponse(Tenant tenant) {
        return TenantResponse.builder()
                .id(tenant.getId())
                .name(tenant.getName())
                .code(tenant.getCode())
                .contactName(tenant.getContactName())
                .contactPhone(tenant.getContactPhone())
                .contactEmail(tenant.getContactEmail())
                .address(tenant.getAddress())
                .logoUrl(tenant.getLogoUrl())
                .status(tenant.getStatus())
                .expireAt(tenant.getExpireAt())
                .maxStudents(tenant.getMaxStudents())
                .maxTeachers(tenant.getMaxTeachers())
                .createdAt(tenant.getCreatedAt())
                .build();
    }

}
