package com.smqjh.agent.mcp;

import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;

import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

final class BusinessSchemaRegistry {
    private final Map<String, TableInfo> tables = new LinkedHashMap<>();

    BusinessSchemaRegistry() {
        add(new TableInfo(
            "smqjh_oms.oms_order",
            "订单主表",
            "订单、支付、配送、物流、收货人、渠道、金额等主数据。默认过滤 COALESCE(delete_status,0)=0。",
            new String[] {
                "order_id: 订单ID",
                "order_number: 订单号",
                "third_order_id/out_trade_no/transaction_id: 第三方订单或交易流水",
                "member_id: 会员ID",
                "channel_id/channel_name: 企业渠道",
                "hb_order_status: 业务订单状态",
                "hb_logistic_status: 物流或配送状态",
                "is_payed: 是否已付款，1 表示已付款",
                "order_money/total/actual_total: 订单金额，销售额优先 COALESCE(actual_total,total,order_money,0)",
                "freight_amount: 运费金额",
                "offset_points: 积分抵扣",
                "coupon_money/member_discount_amount: 优惠或会员折扣",
                "dvy_type/dvy_id/dvy_flow_id/dvy_no/dvy_name: 配送方式、配送单号、快递/物流信息",
                "consignee_name/consignee_mobile/consignee_address: 收货人信息",
                "pay_time/dvy_time/arrive_time/complete_time/create_time: 支付、发货、到达、完成、创建时间",
                "delete_status: 逻辑删除状态"
            },
            "SELECT order_number,hb_order_status,hb_logistic_status,dvy_type,dvy_flow_id,dvy_no,dvy_name,dvy_time,arrive_time,complete_time FROM smqjh_oms.oms_order WHERE COALESCE(delete_status,0)=0 AND order_number LIKE '%订单号%' LIMIT 20",
            "OrderController: /api/v1/order/backendOrderList, /backendOrderInfo, /deliveryNode, /riderInfo, /queryTrace, POST /export"
        ));
        add(new TableInfo(
            "smqjh_oms.oms_order_item",
            "订单商品明细表",
            "订单内商品行、商品金额、数量、SKU、商品名称。月结、商品汇总、订单明细通常需要关联订单主表。",
            new String[] {
                "order_id/order_number: 关联订单",
                "prod_id/sku_id: 商品与 SKU",
                "prod_name/sku_name/spec: 商品名称、SKU 名称、规格",
                "price: 商品单价",
                "prod_count/prod_num: 商品数量",
                "product_total_amount: 商品行小计",
                "item_discount_amount/member_discount_share_amount/use_score/gain_score: 商品行折扣、会员折扣、积分抵扣、赠送积分"
            },
            "SELECT oi.order_number,oi.prod_name,oi.sku_name,oi.spec,oi.price,oi.prod_count,oi.product_total_amount FROM smqjh_oms.oms_order_item oi JOIN smqjh_oms.oms_order o ON o.order_id=oi.order_id WHERE COALESCE(o.delete_status,0)=0 LIMIT 50",
            "OmsOrderMapper.exportProductList"
        ));
        add(new TableInfo(
            "smqjh_system.sm_member",
            "会员表",
            "会员手机号、企业归属、用户基础信息。按手机号查会员或订单时常与订单表 member_id 关联。",
            new String[] {
                "id: 会员ID",
                "mobile: 手机号",
                "nick_name/username/name: 用户名称，字段以实际库结构为准",
                "channel_id/channel_no: 企业渠道归属",
                "create_time/update_time: 创建和更新时间"
            },
            "SELECT id,mobile,channel_id,create_time FROM smqjh_system.sm_member WHERE mobile LIKE '%手机号%' LIMIT 20",
            "企业会员查询接口: /api/v1/members/enterprise/getByMobile, /api/v1/members/enterprise/export"
        ));
        add(new TableInfo(
            "smqjh_system.sm_channel",
            "渠道/企业表",
            "企业用户渠道。当前已确认月结企业：招商银行贵阳分行、中数未来、铜仁移动。",
            new String[] {
                "id: channelId",
                "channel_no: 渠道编码",
                "channel_name: 企业名称",
                "type/status: 渠道类型和状态"
            },
            "SELECT id,channel_no,channel_name,type,status FROM smqjh_system.sm_channel WHERE status=1 LIMIT 50",
            "月结企业：招商银行贵阳分行 channelId=54/channelNo=1；中数未来 channelId=55/channelNo=2；铜仁移动 channelId=58/channelNo=5"
        ));
        add(new TableInfo(
            "smqjh_system.sm_points_recharge",
            "积分充值记录表",
            "企业员工充值、可用积分、消费积分、过期积分、充值单号。充值结算和员工积分核对需要使用。",
            new String[] {
                "id: 主键",
                "tenant_id: 租户ID",
                "user_id/user_name/user_phone: 用户ID、姓名、手机号",
                "channel_id/channel_name: 企业渠道",
                "recharge_number: 充值单号",
                "type: 充值类型，1银行、2现金、3支付宝、4微信、5其他",
                "recharge_status: 积分状态",
                "points: 充值积分",
                "available_points: 可用积分",
                "consume_points: 消耗积分",
                "expiry_points: 过期积分",
                "expiry_date: 过期日期",
                "create_time/update_time: 创建和更新时间"
            },
            "SELECT channel_id,channel_name,SUM(points) AS pointsTotal,SUM(available_points) AS availablePoints,SUM(consume_points) AS consumePoints,SUM(expiry_points) AS expiryPoints FROM smqjh_system.sm_points_recharge WHERE create_time>='2026-05-01' AND create_time<'2026-06-01' GROUP BY channel_id,channel_name",
            "PointsRechargeController: /api/v1/pointsRecharge/page, /statisticsList, /import, /exportTemplate, /export"
        ));
        add(new TableInfo(
            "smqjh_system.sm_points_record",
            "积分流水明细表",
            "积分充值、下单、退款、过期、冲正流水。月结时负数通常表示充值转换为积分再抵扣的金额。",
            new String[] {
                "id: 主键",
                "tenant_id: 租户ID",
                "user_id/channel_id: 用户和企业渠道",
                "order_number: 订单编号",
                "points_id: 关联充值积分ID",
                "variable_points: 变动积分",
                "expiry_points: 过期积分",
                "points_type: 记录类型，1充值、2下单、3退款、4过期、5退款时过期积分",
                "points_audit: 使用状态",
                "currently_available_points: 当前可用积分",
                "creation_date/update_time: 创建和更新时间",
                "is_adjust: 是否冲正数据"
            },
            "SELECT order_number,channel_id,points_type,SUM(variable_points) AS variablePoints FROM smqjh_system.sm_points_record WHERE creation_date>='2026-05-01' AND creation_date<'2026-06-01' GROUP BY order_number,channel_id,points_type LIMIT 100",
            "PointsRecordController: /app-api/v1/pointsRecord/backendPointsRecordList, /backendPointsRecordListExport"
        ));
        add(new TableInfo(
            "smqjh_pms.tz_prod",
            "商城商品表",
            "商城商品主表。商品描述、品牌、状态、基础价格通常在这里。",
            new String[] {
                "prod_id: 商品ID",
                "prod_name: 商品名",
                "brand_name: 品牌",
                "brief: 商品描述",
                "price/ori_price: 价格字段，最终以业务系统实际单位为准",
                "status: 商品状态",
                "is_delete: 逻辑删除"
            },
            "SELECT p.prod_id,p.prod_name,p.brand_name,p.brief,p.price,p.ori_price,p.status FROM smqjh_pms.tz_prod p WHERE COALESCE(p.is_delete,0)=0 AND p.prod_name LIKE '%商品关键词%' LIMIT 20",
            "商品查询、描述查询、报价补齐"
        ));
        add(new TableInfo(
            "smqjh_pms.tz_sku",
            "商城 SKU 表",
            "商品规格、SKU 编码、SKU 价格。商品精确匹配和报价补齐时通常与 tz_prod 关联。",
            new String[] {
                "sku_id: SKU ID",
                "prod_id: 商品ID",
                "prod_name/sku_name: 商品和规格名",
                "sku_code: SKU 编码",
                "price/ori_price: SKU 价格字段",
                "status: SKU 状态",
                "is_delete: 逻辑删除"
            },
            "SELECT p.prod_id,p.prod_name,s.sku_id,s.sku_name,s.sku_code,s.price FROM smqjh_pms.tz_prod p LEFT JOIN smqjh_pms.tz_sku s ON s.prod_id=p.prod_id AND COALESCE(s.is_delete,0)=0 WHERE COALESCE(p.is_delete,0)=0 AND (p.prod_name LIKE '%关键词%' OR s.sku_name LIKE '%关键词%') LIMIT 20",
            "商品/SKU 精确匹配"
        ));
        add(new TableInfo(
            "smqjh_pms.tz_channel_prod",
            "渠道商品价格表",
            "企业渠道商品配置、采购价、出货价、渠道售价。报价单、上架、月结价格核对都需要用，但写操作必须走审批。",
            new String[] {
                "id: 主键",
                "tenant_id: 租户ID",
                "channel_id/channel_name: 企业渠道",
                "sku_id: SKU ID",
                "shop_id: 店铺ID",
                "purchase_price: 采购价",
                "delivery_price: 出货价",
                "channel_prod_price: 渠道商品售价",
                "is_delete: 逻辑删除",
                "update_time/rec_time: 修改和记录时间"
            },
            "SELECT cp.channel_id,cp.channel_name,cp.sku_id,cp.shop_id,cp.purchase_price,cp.delivery_price,cp.channel_prod_price FROM smqjh_pms.tz_channel_prod cp WHERE COALESCE(cp.is_delete,0)=0 LIMIT 50",
            "ChannelProdController: 查询、导入、批量改价、上架/下架相关写操作，Agent 只能预览和标记需人工确认"
        ));
        add(new TableInfo(
            "smqjh_pms.tz_shop_sku",
            "门店 SKU 表",
            "门店商品价格、库存、可售状态。商品上架/下架和库存核对需要使用。",
            new String[] {
                "id: 主键",
                "shop_id: 门店ID",
                "sku_id/spu_id: SKU 与商品ID",
                "shop_sku_price: 门店商品价格",
                "shop_sku_stocks: 门店库存",
                "sale_status: 可售状态，1可售、0不可售",
                "is_delete: 逻辑删除",
                "update_time/rec_time: 更新时间"
            },
            "SELECT shop_id,sku_id,spu_id,shop_sku_price,shop_sku_stocks,sale_status FROM smqjh_pms.tz_shop_sku WHERE COALESCE(is_delete,0)=0 LIMIT 50",
            "ShopSkuMapper.exportList / ShopSkuService.exportChannelProds"
        ));
    }

    ObjectNode search(String query) {
        String normalized = query == null ? "" : query.toLowerCase(Locale.ROOT);
        ArrayNode rows = Jsons.MAPPER.createArrayNode();
        Set<String> emitted = new LinkedHashSet<>();
        for (TableInfo table : tables.values()) {
            if (!emitted.add(table.name)) {
                continue;
            }
            String haystack = (table.name + " " + table.title + " " + table.description + " " + table.interfaceHint + " " + String.join(" ", table.fields)).toLowerCase(Locale.ROOT);
            if (normalized.isBlank() || haystack.contains(normalized) || matchesBusinessKeyword(normalized, haystack)) {
                rows.add(toSummary(table));
            }
        }
        ObjectNode result = Jsons.object();
        result.put("ok", true);
        result.put("query", query == null ? "" : query);
        result.put("rowCount", rows.size());
        result.set("columns", Jsons.MAPPER.valueToTree(new String[] {"table", "title", "description", "interfaceHint", "exampleSql"}));
        result.set("rows", rows);
        return result;
    }

    ObjectNode getTable(String name) {
        String normalized = normalizeTableName(name);
        TableInfo table = tables.get(normalized);
        if (table == null) {
            throw new IllegalArgumentException("未登记的业务表: " + name);
        }
        ObjectNode result = Jsons.object();
        result.put("ok", true);
        result.put("table", table.name);
        result.put("title", table.title);
        result.put("description", table.description);
        result.put("interfaceHint", table.interfaceHint);
        result.set("fields", Jsons.MAPPER.valueToTree(table.fields));
        result.put("exampleSql", table.exampleSql);
        return result;
    }

    ObjectNode businessRules(String topic) {
        String normalized = topic == null ? "" : topic.trim();
        ObjectNode result = Jsons.object();
        result.put("ok", true);
        result.put("topic", normalized);
        ArrayNode rules = Jsons.MAPPER.createArrayNode();
        rules.add("只要用户询问业务系统事实，Agent 应优先自动调用 MCP 工具查询，不让用户自己执行 SQL 或去后台翻。");
        rules.add("数据库查询默认只读 SELECT，默认过滤逻辑删除，明细查询必须 LIMIT。");
        rules.add("订单销售额优先使用 COALESCE(actual_total,total,order_money,0)，并区分已付款 is_payed=1。");
        rules.add("商品查询默认排除逻辑删除商品/SKU，优先匹配商品名、SKU 名、SKU 编码和品牌。");
        rules.add("月结企业包括：招商银行贵阳分行(channelId=54/channelNo=1)、中数未来(channelId=55/channelNo=2)、铜仁移动(channelId=58/channelNo=5)。");
        rules.add("月结范围为企业用户定时月结、所有已付款订单；商品总额、运费、积分抵扣、现金支付有差异时只标记“需人工确认”，不自动修改业务系统。");
        rules.add("结算报告后续流程：发送客户核对 -> 打印盖章 -> 开电子发票 -> 等待客户付款。");
        rules.add("充值流程：从企业获取客户充值信息表 -> 调整排错 -> 导入业务系统 -> 开具成功上账凭据和上账记录。");
        rules.add("消费流程：C 端用户即时配送；企业用户统一发货，非及时性发货需要导出订单分仓、联系供应商、入库，再配送闪送或物流快递。");
        result.set("rules", rules);
        return result;
    }

    String promptContext() {
        StringBuilder builder = new StringBuilder();
        builder.append("业务表与口径:\n");
        Set<String> emitted = new LinkedHashSet<>();
        for (TableInfo table : tables.values()) {
            if (!emitted.add(table.name)) {
                continue;
            }
            builder.append("- ").append(table.name).append(": ").append(table.title).append("。").append(table.description).append("\n");
            builder.append("  常用字段: ").append(String.join("; ", table.fields)).append("\n");
            builder.append("  业务接口/来源: ").append(table.interfaceHint).append("\n");
            builder.append("  SQL 示例: ").append(table.exampleSql).append("\n");
        }
        builder.append("业务规则: 订单默认排除逻辑删除；销售额优先 COALESCE(actual_total,total,order_money,0)；商品默认排除 is_delete=1；月结差异只标记需人工确认，不自动写库。\n");
        return builder.toString();
    }

    private void add(TableInfo table) {
        tables.put(normalizeTableName(table.name), table);
        String shortName = table.name.substring(table.name.lastIndexOf('.') + 1);
        tables.putIfAbsent(shortName.toLowerCase(Locale.ROOT), table);
    }

    private ObjectNode toSummary(TableInfo table) {
        ObjectNode row = Jsons.object();
        row.put("table", table.name);
        row.put("title", table.title);
        row.put("description", table.description);
        row.put("interfaceHint", table.interfaceHint);
        row.put("exampleSql", table.exampleSql);
        return row;
    }

    private String normalizeTableName(String name) {
        return (name == null ? "" : name.trim().replace("`", "")).toLowerCase(Locale.ROOT);
    }

    private boolean matchesBusinessKeyword(String query, String haystack) {
        if ((query.contains("物流") || query.contains("配送") || query.contains("订单")) && haystack.contains("订单")) {
            return true;
        }
        if ((query.contains("商品") || query.contains("sku") || query.contains("价格") || query.contains("描述")) && haystack.contains("商品")) {
            return true;
        }
        if ((query.contains("会员") || query.contains("手机号") || query.contains("用户")) && haystack.contains("会员")) {
            return true;
        }
        if ((query.contains("结算") || query.contains("月结") || query.contains("渠道") || query.contains("企业")) && haystack.contains("渠道")) {
            return true;
        }
        if ((query.contains("积分") || query.contains("充值") || query.contains("抵扣")) && haystack.contains("积分")) {
            return true;
        }
        return false;
    }

    private record TableInfo(String name, String title, String description, String[] fields, String exampleSql, String interfaceHint) {
    }
}
