package dev.sonpx.loyalty.mcp.service;

import dev.sonpx.loyalty.mcp.model.OperationResult;
import dev.sonpx.loyalty.mcp.model.Result;
import dev.sonpx.loyalty.mcp.reward.client.CampaignRuleClient;
import dev.sonpx.loyalty.mcp.reward.criteria.CampaignRuleCriteria;
import dev.sonpx.loyalty.mcp.reward.dto.CampaignRuleSummaryDto;
import dev.sonpx.loyalty.mcp.reward.model.CampaignFormulaOne;
import dev.sonpx.loyalty.mcp.reward.model.CampaignRule;
import java.util.List;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

/**
 * Created by SonPhung on Monday, 20-Jul-2026
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class CampaignRuleService {

    private final CampaignRuleClient campaignRuleClient;

    public Result<List<CampaignRuleSummaryDto>> getAll(CampaignRuleCriteria criteria) {
        List<CampaignRule> rules = campaignRuleClient.getAll(criteria, Pageable.ofSize(10));
        List<CampaignRuleSummaryDto> summaries = rules != null
                ? rules.stream().map(this::toSummaryDto).toList()
                : List.of();
        return Result.of(summaries, """
                Trả lời tự nhiên bằng tiếng Việt. Không dùng markdown table.
                Hiển thị mỗi rule theo dạng danh sách đánh số:
                  **[ruleName]** (`[ruleId]`) — Chiến dịch: [campaignId.description hoặc campaignId.code], Loại: [ruleType - dùng tên tiếng Việt], Hiệu lực: [effectiveFrom] → [effectiveTo]
                  Mô tả: [description, tóm tắt nếu quá dài, hoặc "Chưa có"]
                Nếu không tìm thấy kết quả, thông báo nhẹ nhàng và gợi ý thử từ khóa khác.
                Luôn kết thúc bằng câu gợi mở (ví dụ: xem chi tiết rule, xem chiến dịch gốc).
                """);
    }

    public CampaignRuleSummaryDto toSummaryDto(CampaignRule rule) {
        if (rule == null) {
            return null;
        }
        return CampaignRuleSummaryDto.builder()
                .ruleId(rule.getRuleId())
                .ruleName(rule.getRuleName())
                .ruleType(rule.getRuleType())
                .campaignId(rule.getCampaignId())
                .effectiveFrom(rule.getEffectiveFrom())
                .effectiveTo(rule.getEffectiveTo())
                .poolId(rule.getPoolId())
                .build();
    }

    public Result<Long> count(CampaignRuleCriteria criteria) {
        Long count = campaignRuleClient.count(criteria);
        return Result.of(count, """
                Trả lời tự nhiên bằng tiếng Việt. Ví dụ: "Có [count] thể lệ [phù hợp với điều kiện tìm kiếm]."
                Nếu count = 0, gợi ý người dùng thử từ khóa khác hoặc tạo rule mới.
                """);
    }

    public Result<CampaignRule> findActiveById(String id) {
        CampaignRule rule = campaignRuleClient.findActiveById(id);
        sanitizeFormulas(rule);
        return Result.of(rule, """
                Trả lời tự nhiên bằng tiếng Việt. Trình bày chi tiết rule một cách rõ ràng:
                - Thông tin cơ bản: Tên, Mã Rule, Loại rule (tên tiếng Việt), Chiến dịch liên kết
                - Thời gian hiệu lực, Mô tả
                - Cấu hình thưởng: Pool, Sub-Pool, Chính sách hết hạn (nếu có)
                - Formula đang dùng (liệt kê tên formula có giá trị, ví dụ: "Dùng Formula 1 + Formula 4")
                - Giới hạn thưởng (Award Limits), lịch trình (Schedule) nếu có
                - Kênh thông báo (SMS/Email/Notification) nếu được cấu hình
                Dùng bullet list hoặc key-value dễ đọc, KHÔNG dùng table.
                Gợi ý người dùng có thể quay lại xem chiến dịch gốc hoặc các rule khác.
                """);
    }

    public Result<List<CampaignRule>> findActiveByIds(String ids) {
        List<String> idList = java.util.Arrays.asList(ids.split(",\\s*"));
        List<CampaignRule> rules = campaignRuleClient.findActiveByIds(idList);
        if (rules != null) {
            rules.forEach(this::sanitizeFormulas);
        }
        return Result.of(rules, """
                Trả lời tự nhiên bằng tiếng Việt. Hiển thị danh sách rule theo dạng đánh số,
                mỗi rule ghi: Tên, Mã Rule, Chiến dịch, Loại rule, Trạng thái.
                Không dùng markdown table. Tóm tắt ngắn gọn nếu danh sách dài.
                """);
    }

    public void sanitizeFormulas(CampaignRule rule) {
        if (rule == null) {
            return;
        }
        if (rule.getCampaignFormulaOne() != null && isFormulaOneEmpty(rule.getCampaignFormulaOne())) {
            rule.setCampaignFormulaOne(null);
        }
        if (rule.getCampaignFormulaTwo() != null && rule.getCampaignFormulaTwo().getFixedAmt() == null) {
            rule.setCampaignFormulaTwo(null);
        }
        if (rule.getCampaignFormulaFour() != null && (rule.getCampaignFormulaFour().getTiers() == null || rule.getCampaignFormulaFour().getTiers().isEmpty())) {
            rule.setCampaignFormulaFour(null);
        }
        if (rule.getCampaignFormulaSix() != null && (rule.getCampaignFormulaSix().getTiers() == null || rule.getCampaignFormulaSix().getTiers().isEmpty())) {
            rule.setCampaignFormulaSix(null);
        }
        if (rule.getCampaignFormulaFives() != null && rule.getCampaignFormulaFives().isEmpty()) {
            rule.setCampaignFormulaFives(null);
        }
        if (rule.getCampaignFormulaEights() != null && rule.getCampaignFormulaEights().isEmpty()) {
            rule.setCampaignFormulaEights(null);
        }
        if (rule.getCampaignFormulaTens() != null && rule.getCampaignFormulaTens().isEmpty()) {
            rule.setCampaignFormulaTens(null);
        }
        if (rule.getCampaignFormulaElevens() != null && rule.getCampaignFormulaElevens().isEmpty()) {
            rule.setCampaignFormulaElevens(null);
        }
        if (rule.getCampaignAwardLimits() != null && rule.getCampaignAwardLimits().isEmpty()) {
            rule.setCampaignAwardLimits(null);
        }
        if (rule.getCampaignTcLinkages() != null && rule.getCampaignTcLinkages().isEmpty()) {
            rule.setCampaignTcLinkages(null);
        }
        if (rule.getCampaignContributors() != null && rule.getCampaignContributors().isEmpty()) {
            rule.setCampaignContributors(null);
        }
    }

    private boolean isFormulaOneEmpty(CampaignFormulaOne f) {
        return f.getAwardPerTxnAmt() == null
                && f.getTxnAmt() == null
                && f.getAwardPerTxnAmtAfter() == null
                && f.getTxnAmtAfter() == null;
    }

    public Result<String> generateId() {
        String id = campaignRuleClient.generateId();
        return Result.of(id, """
                Trả lời tự nhiên bằng tiếng Việt. Ví dụ: "Mã rule mới đã được tạo: `[id]`."
                Gợi ý người dùng có thể dùng mã này để tạo rule mới cho chiến dịch.
                """);
    }

    public Result<String> checkId(String id) {
        String checkResult = campaignRuleClient.checkId(id);
        return Result.of(checkResult, """
                Trả lời tự nhiên bằng tiếng Việt. Giải thích kết quả kiểm tra mã rule:
                - Nếu hợp lệ/khả dụng: thông báo tích cực, gợi ý tạo rule.
                - Nếu đã tồn tại/không hợp lệ: thông báo rõ ràng lý do, gợi ý tạo mã mới.
                """);
    }

    public Result<OperationResult<CampaignRule>> create(CampaignRule dto) {
        OperationResult<CampaignRule> opResult = campaignRuleClient.create(dto);
        return Result.of(opResult, """
                Trả lời tự nhiên bằng tiếng Việt.
                - Nếu thành công: chúc mừng, hiển thị tóm tắt rule vừa tạo (Tên, ID, Chiến dịch, Loại, Thời gian), gợi ý bước tiếp (cấu hình formula, giới hạn thưởng, lịch trình).
                - Nếu lỗi: thông báo lỗi rõ ràng, giải thích nguyên nhân, gợi ý cách khắc phục.
                """);
    }

    public Result<List<CampaignRule>> findMatchingRules(String ruleType, String transactionCode, String transactionDate, String postDate, String languageCode) {
        List<CampaignRule> rules = campaignRuleClient.findMatchingRules(ruleType, transactionCode, transactionDate, postDate, languageCode);
        if (rules != null) {
            rules.forEach(this::sanitizeFormulas);
        }
        return Result.of(rules, """
                Trả lời tự nhiên bằng tiếng Việt. Hiển thị danh sách các rule/thể lệ khớp với thông tin giao dịch,
                mỗi rule ghi: Tên, Mã Rule, Loại, Thời gian hiệu lực.
                Tóm tắt ngắn gọn cấu hình thưởng nếu có. Không dùng markdown table.
                """);
    }
}

