package com.petshop.backend.service;

import com.petshop.backend.dto.activity.ActivityLogResponse;
import com.petshop.backend.entity.ActivityLog;
import com.petshop.backend.entity.StoreLocation;
import com.petshop.backend.entity.User;
import com.petshop.backend.repository.ActivityLogRepository;
import com.petshop.backend.repository.UserRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
public class ActivityLogService {

    private static final Logger log = LoggerFactory.getLogger(ActivityLogService.class);

    private final ActivityLogRepository activityLogRepository;
    private final UserRepository userRepository;

    public ActivityLogService(ActivityLogRepository activityLogRepository, UserRepository userRepository) {
        this.activityLogRepository = activityLogRepository;
        this.userRepository = userRepository;
    }

    @Transactional
    public void record(User user, String activity) {
        if (user == null || activity == null || activity.isBlank()) {
            return;
        }

        try {
            User managedUser = userRepository.findById(user.getId()).orElse(user);
            StoreLocation store = managedUser.getPrimaryStore();
            ActivityLog entry = new ActivityLog();
            entry.setUser(managedUser);
            entry.setStore(store);
            entry.setUsernameSnapshot(managedUser.getUsername());
            entry.setFullNameSnapshot(resolveFullName(managedUser));
            entry.setRoleSnapshot(managedUser.getRole() != null ? managedUser.getRole().name() : null);
            entry.setStoreNameSnapshot(store != null ? store.getStoreName() : null);
            entry.setActivity(activity.trim());
            activityLogRepository.save(entry);
        } catch (Exception ex) {
            log.warn("Failed to persist activity log", ex);
        }
    }

    @Transactional(readOnly = true)
    public List<ActivityLogResponse> getLogs(int limit) {
        return activityLogRepository.findRecent(PageRequest.of(0, limit)).stream().map(this::toResponse).toList();
    }

    private ActivityLogResponse toResponse(ActivityLog entry) {
        ActivityLogResponse response = new ActivityLogResponse();
        response.setLogId(entry.getLogId());

        if (entry.getUser() != null) {
            response.setUserId(entry.getUser().getId());
            response.setUsername(firstNonBlank(entry.getUsernameSnapshot(), entry.getUser().getUsername()));
            response.setFullName(firstNonBlank(entry.getFullNameSnapshot(), resolveFullName(entry.getUser())));
            response.setRole(firstNonBlank(entry.getRoleSnapshot(), entry.getUser().getRole() != null ? entry.getUser().getRole().name() : null));
        }

        StoreLocation store = entry.getStore();
        if (store != null) {
            response.setStoreId(store.getStoreId());
            response.setStoreName(firstNonBlank(entry.getStoreNameSnapshot(), store.getStoreName()));
        }

        response.setUsernameSnapshot(entry.getUsernameSnapshot());
        response.setFullNameSnapshot(entry.getFullNameSnapshot());
        response.setRoleSnapshot(entry.getRoleSnapshot());
        response.setStoreNameSnapshot(entry.getStoreNameSnapshot());

        response.setActivity(entry.getActivity());
        response.setLogTimestamp(entry.getLogTimestamp());
        return response;
    }

    private String resolveFullName(User user) {
        if (user == null) {
            return null;
        }
        if (user.getFullName() != null && !user.getFullName().isBlank()) {
            return user.getFullName();
        }
        String first = user.getFirstName();
        String last = user.getLastName();
        if (first == null || first.isBlank()) {
            return last;
        }
        if (last == null || last.isBlank()) {
            return first;
        }
        return first.trim() + " " + last.trim();
    }

    private String firstNonBlank(String preferred, String fallback) {
        if (preferred != null && !preferred.isBlank()) {
            return preferred;
        }
        return fallback;
    }
}
