package com.nebula.erp.product.service;

import com.nebula.erp.product.model.Fees;
import com.nebula.erp.product.model.Product;
import com.nebula.erp.product.model.Tax;
import com.nebula.erp.product.repository.FeesRepository;
import com.nebula.erp.product.repository.TaxRepository;
import com.nebula.erp.product.requestmodel.FeesRequest;
import com.nebula.erp.product.utility.CreateLogger;
import com.nebula.erp.product.utility.JwtRequestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import java.util.Optional;

@Service
public class FeesService {
    @Autowired
    private FeesRepository feesRepository;

    @Autowired
    private TaxRepository taxRepository;

    @Autowired
    private JwtRequestUtils jwtRequestUtils;

    @Autowired
    private CreateLogger createLogger;

    private static final String path = "/fees";

    public Page<Fees> getAllFees(int page, int size, String practitioner_id) {
        String tenantName = jwtRequestUtils.getTenantName();

        Pageable pageable = PageRequest.of(page - 1, size);
        return feesRepository.findAllByTenant(pageable, tenantName, practitioner_id);
    }

    public Fees createFees(FeesRequest feesRequest) {
        // Validate required fields
        if (feesRequest.getPractitioner_id() == null || feesRequest.getRate() == null) {
            throw new IllegalArgumentException("Practitioner id and rate is required");
        }
        String tenantName = jwtRequestUtils.getTenantName();
        String userId = jwtRequestUtils.getUserId();

        // Check if an entry with the same values already exists
        boolean exists = feesRepository.checkIfExists(
                feesRequest.getPractitioner_id(),
                feesRequest.getSpeciality(),
                feesRequest.getLocation_id(),
                feesRequest.getFees_type_id(),
                feesRequest.getService_category(),
                feesRequest.getMeasurement(),
                feesRequest.getRate()
        );

        if (exists) {
            createLogger.createLogger("error", path, "POST", "Fees entry already exists with the same details.", "");
            throw new IllegalArgumentException("Fees entry already exists with the same details.");
        }

        // Create a new Tax object
        Fees fees = new Fees();
        fees.setPractitioner_id(feesRequest.getPractitioner_id());
        fees.setSpeciality(feesRequest.getSpeciality());
        fees.setLocation_id(feesRequest.getLocation_id());
        fees.setFees_type_id(feesRequest.getFees_type_id());
        fees.setFees_type_name(feesRequest.getFees_type_name());
        fees.setService_category(feesRequest.getService_category());
        fees.setMeasurement(feesRequest.getMeasurement());
        fees.setRate(feesRequest.getRate());
        fees.setDescription(feesRequest.getDescription());
        fees.setCreated_by(userId);
        fees.setTenant(tenantName);

        // Set tax if provided
        if (feesRequest.getTax_id() != null) {
            Tax tax = taxRepository.findById(feesRequest.getTax_id())
                    .orElseThrow(() -> new RuntimeException("Tax not found"));
            fees.setTax(tax);
        }

        return feesRepository.save(fees);
    }

    public Optional<Fees> getFees(Long id) {
        String tenantName = jwtRequestUtils.getTenantName();
        return feesRepository.findByIdAndTenant(id, tenantName);
    }

    public Fees updateFees(Long id, FeesRequest feesRequest) {
        String tenantName = jwtRequestUtils.getTenantName();

        // Fetch the existing fees from the database
        Fees fees = feesRepository.findByIdAndTenant(id, tenantName)
                .orElseThrow(() -> new RuntimeException("Fees not found"));

        // Check if an entry with the same values already exists (excluding the current entry)
        boolean exists = feesRepository.existCheckExcludeId(
                feesRequest.getPractitioner_id(),
                feesRequest.getSpeciality(),
                feesRequest.getLocation_id(),
                feesRequest.getFees_type_id(),
                feesRequest.getService_category(),
                feesRequest.getMeasurement(),
                feesRequest.getRate(),
                id
        );

        if (exists) {
            createLogger.createLogger("error", path, "PUT", "Fees entry already exists with the same details.", "");
            throw new IllegalArgumentException("Fees entry already exists with the same details.");
        }

        // Update fees basic fields
        fees.setPractitioner_id(feesRequest.getPractitioner_id());
        fees.setSpeciality(feesRequest.getSpeciality());
        fees.setLocation_id(feesRequest.getLocation_id());
        fees.setFees_type_id(feesRequest.getFees_type_id());
        fees.setFees_type_name(feesRequest.getFees_type_name());
        fees.setService_category(feesRequest.getService_category());
        fees.setMeasurement(feesRequest.getMeasurement());
        fees.setRate(feesRequest.getRate());
        fees.setDescription(feesRequest.getDescription());

        // Update the relationship with Tax if provided
        if (feesRequest.getTax_id() != null) {
            Tax tax = taxRepository.findById(feesRequest.getTax_id())
                    .orElseThrow(() -> new RuntimeException("Tax not found"));
            fees.setTax(tax);
        }

        // Save the updated product with all the related entities
        return feesRepository.save(fees);
    }
}