package dev.sonpx.loyalty.mcp.tool;

import dev.sonpx.loyalty.mcp.model.OperationResult;
import dev.sonpx.loyalty.mcp.model.Result;
import dev.sonpx.loyalty.mcp.reward.criteria.CampaignRuleCriteria;
import dev.sonpx.loyalty.mcp.reward.dto.CampaignRuleSummaryDto;
import dev.sonpx.loyalty.mcp.reward.model.CampaignRule;
import dev.sonpx.loyalty.mcp.service.CampaignRuleService;
import dev.sonpx.loyalty.mcp.util.SearchUtils;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.ai.mcp.annotation.McpTool;
import org.springframework.stereotype.Component;

/**
 * Created by SonPhung on Monday, 20-Jul-2026
 */
@Component
@RequiredArgsConstructor
public class CampaignRuleTools {

    private final CampaignRuleService campaignRuleService;

    @McpTool(description = """
            TÌM KIẾM THỂ LỆ / RULE của chiến dịch. Trả về: tên rule, loại rule, chiến dịch gốc, công thức thưởng.
            - Param `request`: đối tượng chứa các điều kiện lọc (có thể để null nếu không cần lọc).
            - QUAN TRỌNG: Khi người dùng hỏi lấy danh sách chung ("danh sách rule", "xem thể lệ"), KHÔNG truyền điều kiện nào.
            - KHÔNG dùng tool này khi người dùng chỉ hỏi về thông tin cơ bản chiến dịch (tên, owner, loại) → hãy dùng tool searchCampaigns.
            Hiển thị tối đa 10 bản ghi.""")
    public Result<List<CampaignRuleSummaryDto>> searchRules(dev.sonpx.loyalty.mcp.tool.request.CampaignRuleSearchRequest request) {
        CampaignRuleCriteria criteria = new CampaignRuleCriteria();
        if (request != null) {
            if (request.campaignId() != null) {
                dev.sonpx.loyalty.mcp.filter.StringFilter filter = new dev.sonpx.loyalty.mcp.filter.StringFilter();
                filter.setEquals(request.campaignId());
                criteria.setCampaignId(filter);
            }
            if (request.ruleId() != null) {
                dev.sonpx.loyalty.mcp.filter.StringFilter filter = new dev.sonpx.loyalty.mcp.filter.StringFilter();
                filter.setEquals(request.ruleId());
                criteria.setRuleId(filter);
            }
            if (request.ruleName() != null) {
                dev.sonpx.loyalty.mcp.filter.StringFilter filter = new dev.sonpx.loyalty.mcp.filter.StringFilter();
                filter.setContains(request.ruleName());
                criteria.setRuleName(filter);
            }
            if (request.description() != null) {
                dev.sonpx.loyalty.mcp.filter.StringFilter filter = new dev.sonpx.loyalty.mcp.filter.StringFilter();
                filter.setContains(request.description());
                criteria.setDescription(filter);
            }
            if (request.ruleType() != null) {
                dev.sonpx.loyalty.mcp.filter.StringFilter filter = new dev.sonpx.loyalty.mcp.filter.StringFilter();
                filter.setEquals(request.ruleType());
                criteria.setRuleType(filter);
            }
            if (request.poolId() != null) {
                dev.sonpx.loyalty.mcp.filter.StringFilter filter = new dev.sonpx.loyalty.mcp.filter.StringFilter();
                filter.setEquals(request.poolId());
                criteria.setPoolId(filter);
            }
            try {
                if (request.effectiveFrom() != null) {
                    dev.sonpx.loyalty.mcp.filter.LocalDateTimeFilter filter = new dev.sonpx.loyalty.mcp.filter.LocalDateTimeFilter();
                    filter.setGreaterThanOrEqual(java.time.LocalDateTime.parse(request.effectiveFrom()));
                    criteria.setEffectiveFrom(filter);
                }
                if (request.effectiveTo() != null) {
                    dev.sonpx.loyalty.mcp.filter.LocalDateTimeFilter filter = new dev.sonpx.loyalty.mcp.filter.LocalDateTimeFilter();
                    filter.setLessThanOrEqual(java.time.LocalDateTime.parse(request.effectiveTo()));
                    criteria.setEffectiveTo(filter);
                }
            } catch (java.time.format.DateTimeParseException e) {
                return Result.failure("Invalid date format. Please use ISO-8601 format (e.g. '2026-07-27T10:00:00').");
            }
        }
        return campaignRuleService.getAll(criteria);
    }


    @McpTool(description = "Đếm số lượng RULE/THỂ LỆ, không phải chiến dịch. Để search = null nếu đếm tất cả.")
    public Result<Long> countRules(String search) {
        CampaignRuleCriteria criteria = new CampaignRuleCriteria();
        criteria.setSearch(SearchUtils.sanitizeSearch(search));
        return campaignRuleService.count(criteria);
    }

    @McpTool(description = "Lấy chi tiết MỘT RULE/THỂ LỆ theo ID. Bao gồm: công thức thưởng, giới hạn, lịch trình.")
    public Result<CampaignRule> getRuleById(String id) {
        return campaignRuleService.findActiveById(id);
    }

    @McpTool(description = "Lấy thông tin NHIỀU RULE/THỂ LỆ theo danh sách ID, phân tách bằng dấu phẩy.")
    public Result<List<CampaignRule>> getRulesByIds(String ids) {
        return campaignRuleService.findActiveByIds(ids);
    }

    @McpTool(description = "Tạo một MÃ RULE mới (rule ID), không phải mã chiến dịch.")
    public Result<String> generateRuleId() {
        return campaignRuleService.generateId();
    }

    @McpTool(description = "Kiểm tra tính hợp lệ của một MÃ RULE (rule ID).")
    public Result<String> checkRuleId(String id) {
        return campaignRuleService.checkId(id);
    }

    @McpTool(description = "Tạo một RULE/THỂ LỆ mới cho chiến dịch. Cần có campaignId để liên kết.")
    public Result<OperationResult<CampaignRule>> createRule(CampaignRule dto) {
        return campaignRuleService.create(dto);
    }

    @McpTool(description = "Tìm kiếm các rule/thể lệ khớp với một giao dịch cụ thể. Yêu cầu truyền vào loại rule, mã giao dịch (transaction code), ngày giao dịch, ngày post và ngôn ngữ (ví dụ: 'vi' hoặc 'en'). Ngày tháng format yyyy-MM-dd'T'HH:mm:ss")
    public Result<List<CampaignRule>> findMatchingRules(String ruleType, String transactionCode, String transactionDate, String postDate, String languageCode) {
        return campaignRuleService.findMatchingRules(ruleType, transactionCode, transactionDate, postDate, languageCode);
    }
}
