package com.saas.admin.service;

import com.saas.admin.dto.request.CreateTenantRequest;
import com.saas.admin.dto.response.TenantResponse;
import com.saas.admin.entity.Tenant;
import com.saas.admin.repository.TenantRepository;
import com.saas.shared.dto.common.PageResponse;
import com.saas.shared.dto.mapper.TenantMapper;
import com.saas.shared.exception.BusinessException;
import com.saas.shared.exception.ErrorCode;
import com.saas.shared.exception.ResourceNotFoundException;
import com.saas.shared.util.SlugUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.UUID;

@Service
@Slf4j
@RequiredArgsConstructor
public class TenantService {
    
    private final TenantRepository tenantRepository;
    private final TenantMapper tenantMapper;
    private final TenantSchemaService tenantSchemaService;
    
    @Transactional
    public TenantResponse createTenant(CreateTenantRequest request) {
        log.info("Creating tenant: {}", request.getTenantName());
        
        String slug = SlugUtils.toSlug(request.getTenantName());
        String schemaName = "tenant_" + slug;
        
        if (tenantRepository.existsBySchemaName(schemaName)) {
            throw new BusinessException(ErrorCode.TENANT_ALREADY_EXISTS, 
                "Tenant with name " + request.getTenantName() + " already exists");
        }
        
        Tenant tenant = tenantMapper.toEntity(request);
        tenant.setTenantId(UUID.randomUUID().toString());
        tenant.setSchemaName(schemaName);
        tenant.setStatus(request.getStatus() != null ? request.getStatus() : "ACTIVE");
        
        Tenant savedTenant = tenantRepository.save(tenant);
        
        log.info("Tenant created successfully with ID: {}", savedTenant.getTenantId());
        return tenantMapper.toResponse(savedTenant);
    }
    
    @Transactional(readOnly = true)
    public TenantResponse getTenantById(String tenantId) {
        log.debug("Fetching tenant with ID: {}", tenantId);
        return tenantRepository.findByTenantId(tenantId)
            .map(tenantMapper::toResponse)
            .orElseThrow(() -> new ResourceNotFoundException("Tenant", tenantId));
    }
    
    @Transactional(readOnly = true)
    public List<TenantResponse> getAllTenants() {
        log.debug("Fetching all tenants");
        return tenantMapper.toResponseList(tenantRepository.findAll());
    }
    
    @Transactional(readOnly = true)
    public PageResponse<TenantResponse> getTenants(int page, int size) {
        log.debug("Fetching tenants - page: {}, size: {}", page, size);
        Pageable pageable = PageRequest.of(page, size);
        Page<Tenant> tenantPage = tenantRepository.findAll(pageable);
        
        return PageResponse.<TenantResponse>builder()
            .content(tenantMapper.toResponseList(tenantPage.getContent()))
            .page(page)
            .size(size)
            .totalElements(tenantPage.getTotalElements())
            .totalPages(tenantPage.getTotalPages())
            .hasNext(tenantPage.hasNext())
            .hasPrevious(tenantPage.hasPrevious())
            .build();
    }
    
    @Transactional
    public void deleteTenant(String tenantId) {
        log.info("Deleting tenant with ID: {}", tenantId);
        
        Tenant tenant = tenantRepository.findByTenantId(tenantId)
            .orElseThrow(() -> new ResourceNotFoundException("Tenant", tenantId));
        
        tenantRepository.delete(tenant);
        log.info("Tenant deleted successfully with ID: {}", tenantId);
    }
}
