# ============================================================
# 商家端 — 全量端到端测试
# 覆盖 24 个 Controller，约 90 个 API 端点
# ============================================================
import pytest
import json
import random
from api_client import ApiClient
from config import SELLER_SHOP_ID


# ============================================================
# 商家 — 店铺切换 (SellerShopContextController)
# ============================================================
class TestSellerContext:

    def test_80_switch_shop(self, client, seller_token):
        """切换店铺上下文"""
        resp = client.put("/agri/seller/context/shop", json={
            "shopId": SELLER_SHOP_ID
        })
        client.assert_ok("切换店铺失败")
        print(f"  [OK] 切换店铺 shopId={SELLER_SHOP_ID}")


# ============================================================
# 商家 — 员工管理 (MerchantEmployeeController)
# ============================================================
class TestSellerEmployee:

    def test_81_employee_list(self, client, seller_token):
        """员工列表"""
        resp = client.get("/agri/seller/employee/list")
        client.assert_ok("查询员工列表失败")
        data = client.extract_data() or {}
        print(f"  [OK] 员工列表 total={data.get('total','?')}")

    def test_82_employee_quota(self, client, seller_token):
        """员工名额配额"""
        resp = client.get("/agri/seller/employee/quota")
        client.assert_ok("查询员工配额失败")
        quota = client.extract_data() or {}
        print(f"  [OK] 员工配额: {quota}")

    def test_83_employee_role_options(self, client, seller_token):
        """员工角色选项"""
        resp = client.get("/agri/seller/employee/roleOptions")
        client.assert_ok("查询角色选项失败")
        roles = client.extract_data() or []
        print(f"  [OK] 员工角色选项 count={len(roles) if isinstance(roles, list) else 0}")


# ============================================================
# 商家 — 角色管理 (MerchantRoleController)
# ============================================================
class TestSellerRole:

    def test_84_role_list(self, client, seller_token):
        """角色列表"""
        resp = client.get("/agri/seller/role/list")
        client.assert_ok("查询角色列表失败")
        data = client.extract_data() or {}
        print(f"  [OK] 角色列表 total={data.get('total','?')}")

    def test_85_role_menu_tree(self, client, seller_token):
        """角色菜单树"""
        resp = client.get("/agri/seller/role/menuTree")
        client.assert_ok("查询菜单树失败")
        tree = client.extract_data() or []
        print(f"  [OK] 角色菜单树 nodes={len(tree)}")


# ============================================================
# 商家 — 商品管理 (SellerGoodsController)
# ============================================================
class TestSellerGoods:

    def test_86_goods_list(self, client, seller_token):
        """商家商品列表"""
        resp = client.get("/agri/seller/goods/list")
        client.assert_ok("查询商品列表失败")
        data = client.extract_data() or {}
        total = data.get("total", 0) if isinstance(data, dict) else 0
        print(f"  [OK] 商家商品列表 total={total}")

    def test_87_goods_category_options(self, client, seller_token):
        """商品分类选项"""
        resp = client.get("/agri/seller/goods/categoryOptions")
        client.assert_ok("查询分类选项失败")
        cats = client.extract_data() or []
        print(f"  [OK] 分类选项 count={len(cats)}")
        if cats:
            client._test_seller_category_id = cats[0].get("categoryId") or cats[0].get("id")

    def test_88_goods_service_options(self, client, seller_token):
        """商品服务选项"""
        resp = client.get("/agri/seller/goods/serviceOptions")
        client.assert_ok("查询服务选项失败")
        svc = client.extract_data() or {}
        print(f"  [OK] 服务选项: {json.dumps(svc, ensure_ascii=False)[:100]}")

    def test_89_goods_attr_template_options(self, client, seller_token):
        """属性模板选项"""
        resp = client.get("/agri/seller/goods/attrTemplateOptions")
        client.assert_ok("查询属性模板失败")
        tmpl = client.extract_data() or []
        print(f"  [OK] 属性模板选项 count={len(tmpl) if isinstance(tmpl, list) else 0}")

    def test_90_goods_freight_options(self, client, seller_token):
        """运费模板选项"""
        resp = client.get("/agri/seller/goods/freightTemplateOptions")
        client.assert_ok("查询运费模板失败")
        tmpl = client.extract_data() or []
        print(f"  [OK] 运费模板选项 count={len(tmpl)}")
        if tmpl:
            client._test_seller_freight_id = tmpl[0].get("templateId") or tmpl[0].get("id")

    def test_91_goods_freight_default(self, client, seller_token):
        """默认运费模板"""
        resp = client.get("/agri/seller/goods/freightDefault")
        client.assert_ok("查询默认运费模板失败")
        default = client.extract_data() or {}
        print(f"  [OK] 默认运费: {json.dumps(default, ensure_ascii=False)[:80]}")

    def test_92_goods_shop_category_options(self, client, seller_token):
        """店铺商品分类选项"""
        resp = client.get("/agri/seller/goods/shopCategoryOptions", params={"visibleOnly": True})
        client.assert_ok("查询店铺分类选项失败")
        cats = client.extract_data() or []
        print(f"  [OK] 店铺分类选项 count={len(cats) if isinstance(cats, list) else 0}")

    def test_93_goods_detail(self, client, seller_token):
        """商家商品详情"""
        resp = client.get("/agri/seller/goods/list", params={"pageSize": 1})
        data = client.assert_ok()
        rows = (data.get("data") or {}).get("rows") or []
        if not rows:
            pytest.skip("无商品数据")
        gid = rows[0].get("goodsId")
        resp = client.get(f"/agri/seller/goods/{gid}")
        client.assert_ok("查询商品详情失败")
        print(f"  [OK] 商家商品详情 goodsId={gid}")


# ============================================================
# 商家 — 订单管理 (SellerOrderController)
# ============================================================
class TestSellerOrder:

    def test_94_seller_order_list(self, client, seller_token):
        """商家订单列表"""
        resp = client.get("/agri/seller/order/list")
        client.assert_ok("查询订单列表失败")
        data = client.extract_data() or {}
        total = data.get("total", 0) if isinstance(data, dict) else 0
        print(f"  [OK] 商家订单列表 total={total}")

    def test_95_seller_order_detail(self, client, seller_token):
        """商家订单详情"""
        resp = client.get("/agri/seller/order/list", params={"pageSize": 1})
        data = client.assert_ok()
        rows = (data.get("data") or {}).get("rows") or []
        if not rows:
            pytest.skip("无订单数据")
        oid = rows[0].get("orderId")
        resp = client.get(f"/agri/seller/order/{oid}")
        client.assert_ok("查询订单详情失败")
        print(f"  [OK] 商家订单详情 orderId={oid}")


# ============================================================
# 商家 — 发货管理 (SellerShipController)
# ============================================================
class TestSellerShip:

    def test_96_ship_badges(self, client, seller_token):
        """发货角标"""
        resp = client.get("/agri/seller/ship/badges")
        client.assert_ok("查询发货角标失败")
        badges = client.extract_data() or {}
        print(f"  [OK] 发货角标: {badges}")

    def test_97_ship_list(self, client, seller_token):
        """发货列表"""
        resp = client.get("/agri/seller/ship/list")
        client.assert_ok("查询发货列表失败")
        data = client.extract_data() or {}
        total = data.get("total", 0) if isinstance(data, dict) else 0
        print(f"  [OK] 发货列表 total={total}")

    def test_98_ship_detail(self, client, seller_token):
        """发货详情"""
        resp = client.get("/agri/seller/ship/list", params={"pageSize": 1})
        data = client.assert_ok()
        rows = (data.get("data") or {}).get("rows") or []
        if not rows:
            pytest.skip("无发货数据")
        oid = rows[0].get("orderId")
        resp = client.get(f"/agri/seller/ship/{oid}")
        client.assert_ok("查询发货详情失败")
        print(f"  [OK] 发货详情 orderId={oid}")


# ============================================================
# 商家 — 售后管理 (SellerAftersaleController)
# ============================================================
class TestSellerAftersale:

    def test_99_aftersale_list(self, client, seller_token):
        """售后列表"""
        resp = client.get("/agri/seller/aftersale/list")
        client.assert_ok("查询售后列表失败")
        data = client.extract_data() or {}
        total = data.get("total", 0) if isinstance(data, dict) else 0
        print(f"  [OK] 售后列表 total={total}")

    def test_100_aftersale_detail(self, client, seller_token):
        """售后详情"""
        resp = client.get("/agri/seller/aftersale/list", params={"pageSize": 1})
        data = client.assert_ok()
        rows = (data.get("data") or {}).get("rows") or []
        if not rows:
            pytest.skip("无售后数据")
        aid = rows[0].get("aftersaleId")
        resp = client.get(f"/agri/seller/aftersale/{aid}")
        client.assert_ok("查询售后详情失败")
        print(f"  [OK] 售后详情 aftersaleId={aid}")


# ============================================================
# 商家 — 评价管理 (SellerReviewController)
# ============================================================
class TestSellerReview:

    def test_101_review_list(self, client, seller_token):
        """评价列表"""
        resp = client.get("/agri/seller/review/list")
        client.assert_ok("查询评价列表失败")
        data = client.extract_data() or {}
        total = data.get("total", 0) if isinstance(data, dict) else 0
        print(f"  [OK] 评价列表 total={total}")


# ============================================================
# 商家 — 运费模板 (SellerFreightTemplateController)
# ============================================================
class TestSellerFreight:

    def test_102_freight_template_list(self, client, seller_token):
        """运费模板列表"""
        resp = client.get("/agri/seller/freightTemplate/list")
        client.assert_ok("查询运费模板失败")
        data = client.extract_data() or {}
        total = data.get("total", 0) if isinstance(data, dict) else 0
        print(f"  [OK] 运费模板列表 total={total}")

    def test_103_freight_template_detail(self, client, seller_token):
        """运费模板详情"""
        resp = client.get("/agri/seller/freightTemplate/list", params={"pageSize": 1})
        data = client.assert_ok()
        rows = (data.get("data") or {}).get("rows") or []
        if not rows:
            pytest.skip("无运费模板")
        tid = rows[0].get("templateId")
        resp = client.get(f"/agri/seller/freightTemplate/{tid}")
        client.assert_ok("查询运费模板详情失败")
        print(f"  [OK] 运费模板详情 templateId={tid}")


# ============================================================
# 商家 — 属性模板 (SellerAttrTemplateController)
# ============================================================
class TestSellerAttrTemplate:

    def test_104_attr_template_list(self, client, seller_token):
        """属性模板列表"""
        resp = client.get("/agri/seller/attrTemplate/list")
        client.assert_ok("查询属性模板失败")
        data = client.extract_data() or {}
        total = data.get("total", 0) if isinstance(data, dict) else 0
        print(f"  [OK] 属性模板列表 total={total}")

    def test_105_attr_template_detail(self, client, seller_token):
        """属性模板详情"""
        resp = client.get("/agri/seller/attrTemplate/list", params={"pageSize": 1})
        data = client.assert_ok()
        rows = (data.get("data") or {}).get("rows") or []
        if not rows:
            pytest.skip("无属性模板")
        tid = rows[0].get("templateId")
        resp = client.get(f"/agri/seller/attrTemplate/{tid}")
        client.assert_ok("查询属性模板详情失败")
        print(f"  [OK] 属性模板详情 templateId={tid}")


# ============================================================
# 商家 — 分类管理 (SellerPlatformCategory + ShopGoodsCategory)
# ============================================================
class TestSellerCategory:

    def test_106_platform_category_options(self, client, seller_token):
        """平台分类选项"""
        resp = client.get("/agri/seller/category/platformLevel2Options")
        client.assert_ok("查询平台分类选项失败")
        cats = client.extract_data() or []
        print(f"  [OK] 平台分类选项 count={len(cats) if isinstance(cats, list) else 0}")

    def test_107_shop_category_list(self, client, seller_token):
        """店铺分类列表"""
        resp = client.get("/agri/seller/shopCategory/list")
        client.assert_ok("查询店铺分类失败")
        data = client.extract_data() or {}
        print(f"  [OK] 店铺分类列表正常")

    def test_108_shop_category_scope(self, client, seller_token):
        """店铺分类使用范围"""
        resp = client.get("/agri/seller/shopCategory/scope")
        client.assert_ok("查询店铺分类范围失败")
        scope = client.extract_data() or {}
        print(f"  [OK] 店铺分类范围: {scope}")


# ============================================================
# 商家 — 店铺管理 (SellerShopController)
# ============================================================
class TestSellerShop:

    def test_109_shop_employee_stats(self, client, seller_token):
        """店铺员工统计"""
        resp = client.get("/agri/seller/shop/employeeStats")
        client.assert_ok("查询员工统计失败")
        stats = client.extract_data() or {}
        print(f"  [OK] 员工统计: {stats}")


# ============================================================
# 商家 — 配送设置 (SellerDeliveryController)
# ============================================================
class TestSellerDelivery:

    def test_110_delivery_setting_get(self, client, seller_token):
        """配送设置查询"""
        resp = client.get("/agri/seller/delivery")
        client.assert_ok("查询配送设置失败")
        setting = client.extract_data() or {}
        print(f"  [OK] 配送设置: {json.dumps(setting, ensure_ascii=False)[:100]}")


# ============================================================
# 商家 — 财务管理 (SellerFund / PayAccount / Withdraw)
# ============================================================
class TestSellerFinance:

    def test_111_fund_summary(self, client, seller_token):
        """资金概览"""
        resp = client.get("/agri/seller/finance/overview/summary")
        client.assert_ok("查询资金概览失败")
        summary = client.extract_data() or {}
        print(f"  [OK] 商家资金概览: {json.dumps(summary, ensure_ascii=False)[:100]}")

    def test_112_fund_logs(self, client, seller_token):
        """资金流水"""
        resp = client.get("/agri/seller/finance/overview/logs")
        client.assert_ok("查询资金流水失败")
        data = client.extract_data() or {}
        total = data.get("total", 0) if isinstance(data, dict) else 0
        print(f"  [OK] 资金流水 total={total}")

    def test_113_pay_account_list(self, client, seller_token):
        """收款账户列表"""
        resp = client.get("/agri/seller/finance/payAccount/list")
        client.assert_ok("查询收款账户失败")
        accounts = client.extract_data() or []
        print(f"  [OK] 收款账户 count={len(accounts) if isinstance(accounts, list) else 0}")

    def test_114_pay_account_options(self, client, seller_token):
        """收款账户选项"""
        resp = client.get("/agri/seller/finance/payAccount/options")
        client.assert_ok("查询账户选项失败")
        opts = client.extract_data() or []
        print(f"  [OK] 收款账户选项正常")

    def test_115_withdraw_balance(self, client, seller_token):
        """提现余额"""
        resp = client.get("/agri/seller/finance/withdraw/balance")
        client.assert_ok("查询提现余额失败")
        balance = client.extract_data() or {}
        print(f"  [OK] 提现余额: {json.dumps(balance, ensure_ascii=False)[:80]}")

    def test_116_withdraw_list(self, client, seller_token):
        """提现记录"""
        resp = client.get("/agri/seller/finance/withdraw/list")
        client.assert_ok("查询提现记录失败")
        data = client.extract_data() or {}
        total = data.get("total", 0) if isinstance(data, dict) else 0
        print(f"  [OK] 提现记录 total={total}")


# ============================================================
# 商家 — 库存管理 (5个StockController)
# ============================================================
class TestSellerStock:

    def test_117_stock_query_list(self, client, seller_token):
        """库存查询"""
        resp = client.get("/agri/seller/stock/query/list")
        client.assert_ok("查询库存失败")
        data = client.extract_data() or {}
        total = data.get("total", 0) if isinstance(data, dict) else 0
        print(f"  [OK] 库存查询 total={total}")

    def test_118_stock_inbound_list(self, client, seller_token):
        """入库记录"""
        resp = client.get("/agri/seller/stock/inbound/list")
        client.assert_ok("查询入库记录失败")
        data = client.extract_data() or {}
        total = data.get("total", 0) if isinstance(data, dict) else 0
        print(f"  [OK] 入库记录 total={total}")

    def test_119_stock_outbound_list(self, client, seller_token):
        """出库记录"""
        resp = client.get("/agri/seller/stock/outbound/list")
        client.assert_ok("查询出库记录失败")
        data = client.extract_data() or {}
        total = data.get("total", 0) if isinstance(data, dict) else 0
        print(f"  [OK] 出库记录 total={total}")

    def test_120_stock_adjust_list(self, client, seller_token):
        """库存调整记录"""
        resp = client.get("/agri/seller/stock/adjust/list")
        client.assert_ok("查询库存调整失败")
        data = client.extract_data() or {}
        total = data.get("total", 0) if isinstance(data, dict) else 0
        print(f"  [OK] 库存调整 total={total}")

    def test_121_stock_log_list(self, client, seller_token):
        """库存流水日志"""
        resp = client.get("/agri/seller/stock/log/list")
        client.assert_ok("查询库存日志失败")
        data = client.extract_data() or {}
        total = data.get("total", 0) if isinstance(data, dict) else 0
        print(f"  [OK] 库存日志 total={total}")

    def test_122_stock_inbound_detail(self, client, seller_token):
        """入库详情"""
        resp = client.get("/agri/seller/stock/inbound/list", params={"pageSize": 1})
        data = client.assert_ok()
        rows = (data.get("data") or {}).get("rows") or []
        if not rows:
            pytest.skip("无入库记录")
        iid = rows[0].get("inboundId")
        resp = client.get(f"/agri/seller/stock/inbound/{iid}")
        client.assert_ok("查询入库详情失败")
        print(f"  [OK] 入库详情 inboundId={iid}")

    def test_123_stock_goods_logs(self, client, seller_token):
        """商品库存流水"""
        resp = client.get("/agri/seller/stock/query/list", params={"pageSize": 1})
        data = client.assert_ok()
        rows = (data.get("data") or {}).get("rows") or []
        if not rows:
            pytest.skip("无库存数据")
        gid = rows[0].get("goodsId")
        resp = client.get(f"/agri/seller/stock/query/{gid}/logs")
        client.assert_ok("查询商品流水失败")
        print(f"  [OK] 商品库存流水 goodsId={gid}")


# ============================================================
# 商家 — 微信支付配置 (SellerShopWechatPayController)
# ============================================================
class TestSellerWechat:

    def test_124_wechat_pay_get(self, client, seller_token):
        """商家微信支付配置"""
        resp = client.get("/agri/seller/wechat-pay")
        client.assert_ok("查询支付配置失败")
        config = client.extract_data() or {}
        print(f"  [OK] 商家支付配置: {json.dumps(config, ensure_ascii=False)[:100]}")
