package com.petshop.backend.service;

import com.petshop.backend.dto.common.BulkDeleteRequest;
import com.petshop.backend.dto.inventory.InventoryRequest;
import com.petshop.backend.dto.inventory.InventoryResponse;
import com.petshop.backend.entity.Inventory;
import com.petshop.backend.entity.Product;
import com.petshop.backend.entity.StoreLocation;
import com.petshop.backend.exception.ResourceNotFoundException;
import com.petshop.backend.repository.InventoryRepository;
import com.petshop.backend.repository.ProductRepository;
import com.petshop.backend.repository.StoreRepository;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class InventoryService {

    private final InventoryRepository inventoryRepository;
    private final ProductRepository productRepository;
    private final StoreRepository storeRepository;

    public InventoryService(InventoryRepository inventoryRepository, ProductRepository productRepository, StoreRepository storeRepository) {
        this.inventoryRepository = inventoryRepository;
        this.productRepository = productRepository;
        this.storeRepository = storeRepository;
    }

    public Page<InventoryResponse> getAllInventory(String query, Long storeId, Pageable pageable) {
        String normalizedQuery = normalizeFilter(query);
        Page<Inventory> inventory = inventoryRepository.searchInventory(normalizedQuery, storeId, pageable);
        return inventory.map(this::mapToResponse);
    }

    public InventoryResponse getInventoryById(Long id) {
        Inventory inventory = inventoryRepository.findById(id)
                .orElseThrow(() -> new ResourceNotFoundException("Inventory not found with id: " + id));
        return mapToResponse(inventory);
    }

    @Transactional
    public InventoryResponse createInventory(InventoryRequest request) {
        Product product = productRepository.findById(request.getProdId())
                .orElseThrow(() -> new ResourceNotFoundException("Product not found with id: " + request.getProdId()));

        StoreLocation store = request.getStoreId() != null
                ? storeRepository.findById(request.getStoreId())
                        .orElseThrow(() -> new ResourceNotFoundException("Store not found with id: " + request.getStoreId()))
                : null;

        Inventory inventory = new Inventory();
        inventory.setProduct(product);
        inventory.setStore(store);
        inventory.setQuantity(request.getQuantity());

        inventory = inventoryRepository.save(inventory);
        return mapToResponse(inventory);
    }

    @Transactional
    public InventoryResponse updateInventory(Long id, InventoryRequest request) {
        Inventory inventory = inventoryRepository.findByIdForUpdate(id)
                .orElseThrow(() -> new ResourceNotFoundException("Inventory not found with id: " + id));

        Product product = productRepository.findById(request.getProdId())
                .orElseThrow(() -> new ResourceNotFoundException("Product not found with id: " + request.getProdId()));

        StoreLocation store = request.getStoreId() != null
                ? storeRepository.findById(request.getStoreId())
                        .orElseThrow(() -> new ResourceNotFoundException("Store not found with id: " + request.getStoreId()))
                : null;

        inventory.setProduct(product);
        inventory.setStore(store);
        inventory.setQuantity(request.getQuantity());

        inventory = inventoryRepository.save(inventory);
        return mapToResponse(inventory);
    }

    @Transactional
    public void deleteInventory(Long id) {
        if (!inventoryRepository.existsById(id)) {
            throw new ResourceNotFoundException("Inventory not found with id: " + id);
        }
        inventoryRepository.deleteById(id);
    }

    @Transactional
    public void bulkDeleteInventory(BulkDeleteRequest request) {
        inventoryRepository.deleteAllById(request.getIds());
    }

    private String normalizeFilter(String value) {
        if (value == null) {
            return null;
        }
        String trimmed = value.trim();
        return trimmed.isEmpty() ? null : trimmed;
    }

    private InventoryResponse mapToResponse(Inventory inventory) {
        StoreLocation store = inventory.getStore();
        return new InventoryResponse(
            inventory.getInventoryId(),
            inventory.getProduct().getProdId(),
            inventory.getProduct().getProdName(),
            inventory.getProduct().getCategory().getCategoryName(),
            store != null ? store.getStoreId() : null,
            store != null ? store.getStoreName() : null,
            inventory.getQuantity(),
            inventory.getCreatedAt(),
            inventory.getUpdatedAt()
        );
    }
}
