package com.mzh.library.service.impl;

import com.mzh.library.dao.SystemLogDao;
import com.mzh.library.entity.AuthenticatedUser;
import com.mzh.library.entity.Permission;
import com.mzh.library.entity.SystemLogPage;
import com.mzh.library.entity.SystemLogSearchCriteria;
import com.mzh.library.exception.DaoException;
import com.mzh.library.service.PermissionPolicy;
import com.mzh.library.service.ServiceResult;
import com.mzh.library.service.SystemLogService;

import java.time.LocalDate;
import java.time.format.DateTimeParseException;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

public class SystemLogServiceImpl implements SystemLogService {
    private static final Logger LOGGER = Logger.getLogger(SystemLogServiceImpl.class.getName());
    private static final String UNAVAILABLE_MESSAGE =
        "系统日志服务暂时不可用，请稍后重试。";
    private static final String DENIED_MESSAGE = "您无权查看系统日志。";
    private static final String VALIDATION_MESSAGE = "请修正系统日志检索筛选条件。";

    private final SystemLogDao systemLogDao;
    private final PermissionPolicy permissionPolicy;

    public SystemLogServiceImpl(SystemLogDao systemLogDao) {
        this(systemLogDao, new PermissionPolicy());
    }

    public SystemLogServiceImpl(SystemLogDao systemLogDao, PermissionPolicy permissionPolicy) {
        this.systemLogDao = systemLogDao;
        this.permissionPolicy = permissionPolicy;
    }

    @Override
    public ServiceResult<SystemLogPage> searchLogs(AuthenticatedUser actor, SystemLogSearchCriteria criteria) {
        if (!canViewSystemLogs(actor)) {
            return ServiceResult.failure(DENIED_MESSAGE);
        }

        SystemLogSearchCriteria normalized = criteria == null ? new SystemLogSearchCriteria() : criteria;
        Map<String, String> errors = validate(normalized);
        if (!errors.isEmpty()) {
            return ServiceResult.validationFailure(VALIDATION_MESSAGE, errors);
        }

        try {
            SystemLogPage page = new SystemLogPage();
            page.setLogs(systemLogDao.search(normalized));
            page.setOperationTypes(systemLogDao.findOperationTypes());
            return ServiceResult.success(page);
        } catch (DaoException ex) {
            LOGGER.log(Level.SEVERE, "Unable to load system logs actorId=" + actor.getId(), ex);
            return ServiceResult.failure(UNAVAILABLE_MESSAGE);
        }
    }

    private Map<String, String> validate(SystemLogSearchCriteria criteria) {
        Map<String, String> errors = new LinkedHashMap<>();
        if (criteria.getOperationType().length() > 64) {
            errors.put("operationType", "操作类型不能超过 64 个字符。");
        }
        if (criteria.getKeyword().length() > 120) {
            errors.put("keyword", "关键词不能超过 120 个字符。");
        }

        parseDate(criteria.getCreatedFromText(), "createdFrom", "开始日期", errors, criteria, true);
        parseDate(criteria.getCreatedToText(), "createdTo", "结束日期", errors, criteria, false);
        if (criteria.getCreatedFrom() != null
            && criteria.getCreatedTo() != null
            && criteria.getCreatedFrom().isAfter(criteria.getCreatedTo())) {
            errors.put("createdTo", "结束日期必须晚于或等于开始日期。");
        }
        return errors;
    }

    private void parseDate(String value, String field, String label, Map<String, String> errors,
                           SystemLogSearchCriteria criteria, boolean fromDate) {
        if (value == null || value.isEmpty()) {
            return;
        }
        try {
            LocalDate parsed = LocalDate.parse(value);
            if (fromDate) {
                criteria.setCreatedFrom(parsed);
            } else {
                criteria.setCreatedTo(parsed);
            }
        } catch (DateTimeParseException ex) {
            errors.put(field, label + "必须使用 YYYY-MM-DD 格式。");
        }
    }

    private boolean canViewSystemLogs(AuthenticatedUser actor) {
        return actor != null && permissionPolicy.allows(actor.getRole(), Permission.VIEW_SYSTEM_LOGS);
    }
}
