from __future__ import annotations

import json
from types import SimpleNamespace

from govcrawler.adapters import gov_cn_policy
from govcrawler.models import Article
from scripts.backfill_gov_cn_zcwjk_metadata import _apply_values, _values_from_raw


class _Resp:
    status_code = 200

    def __init__(self, payload: dict):
        self._payload = payload
        self.text = json.dumps(payload, ensure_ascii=False)

    def json(self):
        return self._payload

    def raise_for_status(self):
        pass


def test_zcwjk_maps_government_document_standard_fields(monkeypatch):
    payload = {
        "searchVO": {
            "catMap": {
                "gongwen": {
                    "listVO": [
                        {
                            "id": "26016856",
                            "index": "000014349/2026-00026",
                            "title": "国务院关于推进服务业扩能提质的意见",
                            "url": "https://www.gov.cn/zhengce/zhengceku/202604/content_7066484.htm",
                            "pcode": "国发〔2026〕7号",
                            "puborg": "国务院",
                            "childtype": "商贸、海关、旅游\\其他",
                            "subjectword": "服务业",
                            "ptime": 1776157200000,
                            "pubtime": 1776762000000,
                            "pubtimeStr": "2026.04.21",
                        }
                    ]
                }
            }
        }
    }
    seen = {}

    def _fake_get(url, *, params=None, **_kw):
        seen["params"] = params
        return _Resp(payload)

    monkeypatch.setattr(gov_cn_policy.httpx, "get", _fake_get)

    _list_url, items, fr = gov_cn_policy._fetch_list_page_zcwjk(page_num=1, page_size=20)

    assert fr.status == 200
    assert seen["params"]["t"] == "zhengcelibrary_gw"
    assert seen["params"]["type"] == "gwyzcwjk"
    assert len(items) == 1
    item = items[0]
    assert item.native_post_id == "26016856"
    assert item.index_no == "000014349/2026-00026"
    assert item.publisher == "国务院"
    assert item.source_raw == "国务院"
    assert item.doc_no == "国发〔2026〕7号"
    assert item.content_category == "商贸、海关、旅游"
    assert item.content_subcategory == "其他"
    assert item.open_category == "商贸、海关、旅游\\其他"
    assert item.topic_words == "服务业"
    assert item.publish_time is not None
    assert item.publish_time.date().isoformat() == "2026-04-21"
    assert item.publish_date is not None
    assert item.publish_date.isoformat() == "2026-04-14"
    assert item.metadata_json["zcwjk_cat_key"] == "gongwen"


def test_zcwjk_maps_department_file_facet(monkeypatch):
    payload = {
        "searchVO": {
            "catMap": {
                "bumenfile": {
                    "listVO": [
                        {
                            "id": "bm-1",
                            "index": "000019713/2026-00001",
                            "title": "工业和信息化部关于某事项的通知",
                            "url": "https://www.gov.cn/zhengce/zhengceku/202605/content_bm.htm",
                            "pcode": "工信部规〔2026〕1号",
                            "puborg": "工业和信息化部",
                            "childtype": "工业、交通\\信息产业（含电信）",
                            "subjectword": "工业",
                            "ptime": "2026-05-01",
                            "pubtimeStr": "2026.05.08",
                        }
                    ]
                }
            }
        }
    }
    seen = {}

    def _fake_get(url, *, params=None, **_kw):
        seen["params"] = params
        return _Resp(payload)

    monkeypatch.setattr(gov_cn_policy.httpx, "get", _fake_get)

    _list_url, items, fr = gov_cn_policy._fetch_list_page_zcwjk(
        page_num=1,
        page_size=20,
        search_t="zhengcelibrary_bm",
        cat_key="bumenfile",
        library_label="国务院部门文件",
    )

    assert fr.status == 200
    assert seen["params"]["t"] == "zhengcelibrary_bm"
    assert len(items) == 1
    item = items[0]
    assert item.native_post_id == "bm-1"
    assert item.publisher == "工业和信息化部"
    assert item.doc_no == "工信部规〔2026〕1号"
    assert item.content_category == "工业、交通"
    assert item.content_subcategory == "信息产业（含电信）"
    assert item.metadata_json["zcwjk_cat_key"] == "bumenfile"
    assert item.metadata_json["zcwjk_library_label"] == "国务院部门文件"


def test_zcwjk_parses_older_millisecond_ptime(monkeypatch):
    payload = {
        "searchVO": {
            "catMap": {
                "gongwen": {
                    "listVO": [
                        {
                            "id": "old-1",
                            "title": "国务院关于授予和晋升人民警察警衔的命令",
                            "url": "https://www.gov.cn/zhengce/zhengceku/2019-03/26/content_old.htm",
                            "puborg": "国务院",
                            "ptime": 860720860000,
                            "pubtime": 1553562406000,
                        }
                    ]
                }
            }
        }
    }

    def _fake_get(url, *, params=None, **_kw):
        return _Resp(payload)

    monkeypatch.setattr(gov_cn_policy.httpx, "get", _fake_get)

    _list_url, items, fr = gov_cn_policy._fetch_list_page_zcwjk(page_num=43, page_size=20)

    assert fr.status == 200
    assert len(items) == 1
    assert items[0].publish_time is not None
    assert items[0].publish_time.date().isoformat() == "2019-03-26"
    assert items[0].publish_date is not None
    assert items[0].publish_date.isoformat() == "1997-04-11"


def test_rules_maps_department_regulation_fields(monkeypatch):
    payload = {
        "result": {
            "data": {
                "pager": {"pageCount": 54, "total": 2654, "pageNo": 1, "pageSize": 50},
                "list": [
                    {
                        "doc_pub_url": "https://www.gov.cn/zhengce/202604/content_7065486.htm",
                        "f_20232124962": ["https://www.gov.cn/zhengce/202604/content_7065486.htm"],
                        "f_202321360426": "民用航空空中交通管制员执照管理规则",
                        "f_202321807875": "<em>部门规章</em>",
                        "f_202321915922": "2026-03-26 00:00:00",
                        "f_202323394765": "交通运输部",
                        "f_202355832506": "交通运输部",
                        "f_202344311304": "（2026年3月26日交通运输部令2026年第9号公布 自2026年7月1日起施行）",
                        "f_202321758948": "民用航空空中交通管制员执照管理规则 第一章 总则",
                    }
                ],
            }
        },
        "resultCode": {"code": 200, "cnMsg": True},
    }
    seen = {}

    def _fake_post(url, *, json=None, headers=None, **_kw):
        seen["url"] = url
        seen["json"] = json
        seen["headers"] = headers
        return _Resp(payload)

    monkeypatch.setattr(gov_cn_policy.httpx, "post", _fake_post)
    monkeypatch.setattr(gov_cn_policy, "_rsa_encrypt_b64", lambda *_a, **_kw: "cipher")

    _list_url, items, fr = gov_cn_policy._fetch_list_page_rules(page_num=1, page_size=50)

    assert fr.status == 200
    assert seen["json"]["pageSize"] == 50
    assert seen["json"]["searchFields"][0]["fieldName"] == "f_202321807875"
    assert seen["json"]["searchFields"][0]["searchWord"] == "部门规章"
    assert seen["headers"]["athenaappname"] == "%E8%A7%84%E7%AB%A0%E5%BA%93"
    assert len(items) == 1
    item = items[0]
    assert item.url == "https://www.gov.cn/zhengce/202604/content_7065486.htm"
    assert item.title == "民用航空空中交通管制员执照管理规则"
    assert item.publisher == "交通运输部"
    assert item.source_raw == "交通运输部"
    assert item.doc_no == "交通运输部令2026年第9号"
    assert item.publish_time is not None
    assert item.publish_time.date().isoformat() == "2026-03-26"
    assert item.publish_date is not None
    assert item.publish_date.isoformat() == "2026-03-26"
    assert item.effective_date is not None
    assert item.effective_date.isoformat() == "2026-07-01"
    assert item.content_category == "法规文件"
    assert item.content_subcategory == "部门规章"
    assert item.open_category == "部门规章"
    assert item.metadata_json["rules_profile"] == "department_rules"


def test_rules_accepts_legacy_1994_publish_time(monkeypatch):
    payload = {
        "result": {
            "data": {
                "pager": {"pageCount": 54, "total": 2654, "pageNo": 52, "pageSize": 50},
                "list": [
                    {
                        "doc_pub_url": "https://www.gov.cn/zhengce/199412/content_1.htm",
                        "f_202321360426": "历史部门规章",
                        "f_202321807875": "<em>部门规章</em>",
                        "f_202321915922": "1994-12-31 00:00:00",
                        "f_202323394765": "某部委",
                        "f_202344311304": "（1994年12月31日某部委令第1号公布）",
                    }
                ],
            }
        },
        "resultCode": {"code": 200, "cnMsg": True},
    }

    monkeypatch.setattr(gov_cn_policy.httpx, "post", lambda *_a, **_kw: _Resp(payload))
    monkeypatch.setattr(gov_cn_policy, "_rsa_encrypt_b64", lambda *_a, **_kw: "cipher")

    _list_url, items, fr = gov_cn_policy._fetch_list_page_rules(page_num=52, page_size=50)

    assert fr.status == 200
    assert len(items) == 1
    assert items[0].publish_time.date().isoformat() == "1994-12-31"


def test_rules_doc_no_uses_latest_publish_clause():
    statement = "（2026年3月16日经国家发展改革委第29次委务会通过 2026年3月18日国家发展改革委令第41号公布 自2026年7月1日起施行）"

    assert gov_cn_policy._extract_rules_doc_no(statement) == "国家发展改革委令第41号"


def test_fetch_list_page_preserves_adapter_category(monkeypatch):
    payload = {
        "searchVO": {
            "catMap": {
                "gongwen": {
                    "listVO": [
                        {
                            "id": "1",
                            "index": "idx",
                            "title": "标题",
                            "url": "https://www.gov.cn/zhengce/x.htm",
                            "puborg": "国务院办公厅",
                            "childtype": "国民经济管理、国有资产监管\\宏观经济",
                            "pubtimeStr": "2026.04.21",
                        }
                    ]
                }
            }
        }
    }

    monkeypatch.setattr(gov_cn_policy.httpx, "get", lambda *_a, **_kw: _Resp(payload))
    rt = SimpleNamespace(
        site=SimpleNamespace(
            site_code="gov_cn_zcwjk",
            adapter_params_json={"policy_profile": "zcwjk"},
        ),
        target=SimpleNamespace(
            id=12,
            dept_id=None,
            channel_name="政策文件库",
            channel_path="政策 > 文件库",
            content_category="政策文件",
            content_subcategory=None,
        ),
    )

    _url, items, _fr = gov_cn_policy.fetch_list_page(
        rt, page_num=1, params=rt.site.adapter_params_json,
    )

    assert len(items) == 1
    item = items[0]
    assert item.site_id == "gov_cn_zcwjk"
    assert item.target_id == 12
    assert item.channel_name == "政策文件库"
    assert item.content_category == "国民经济管理、国有资产监管"
    assert item.content_subcategory == "宏观经济"


def test_fetch_list_page_accepts_target_adapter_param_overrides(monkeypatch):
    captured = {}

    def _fake_zcwjk(*, page_num, page_size, search_t, cat_key, library_label):
        captured.update({
            "page_num": page_num,
            "page_size": page_size,
            "search_t": search_t,
            "cat_key": cat_key,
            "library_label": library_label,
        })
        return (
            "https://sousuo.www.gov.cn/search-gov/data?t=zhengcelibrary_bm",
            [
                gov_cn_policy.CrawlItem(
                    site_id="placeholder",
                    url="https://www.gov.cn/zhengce/bm.htm",
                    url_hash=gov_cn_policy.compute_url_hash("https://www.gov.cn/zhengce/bm.htm"),
                    title="部门文件",
                    publisher="工业和信息化部",
                )
            ],
            SimpleNamespace(status=200),
        )

    monkeypatch.setattr(gov_cn_policy, "_fetch_list_page_zcwjk", _fake_zcwjk)
    rt = SimpleNamespace(
        site=SimpleNamespace(
            site_code="gov_cn_zcwjk",
            adapter_params_json={
                "policy_profile": "zcwjk",
                "page_size": 20,
                "zcwjk_t": "zhengcelibrary_bm",
                "zcwjk_cat_key": "bumenfile",
                "zcwjk_library_label": "国务院部门文件",
            },
        ),
        target=SimpleNamespace(
            id=13,
            dept_id=None,
            channel_name="国务院政策文件库",
            channel_path="政策 > 国务院部门文件",
            content_category="政策文件",
            content_subcategory="国务院部门文件",
        ),
    )

    _url, items, _fr = gov_cn_policy.fetch_list_page(
        rt, page_num=7, params=rt.site.adapter_params_json,
    )

    assert captured == {
        "page_num": 7,
        "page_size": 20,
        "search_t": "zhengcelibrary_bm",
        "cat_key": "bumenfile",
        "library_label": "国务院部门文件",
    }
    assert items[0].target_id == 13
    assert items[0].channel_path == "政策 > 国务院部门文件"


def test_fetch_list_page_dispatches_rules_profile(monkeypatch):
    captured = {}

    def _fake_rules(*, page_num, page_size):
        captured["page_num"] = page_num
        captured["page_size"] = page_size
        return (
            "https://sousuoht.www.gov.cn/athena/forward/rules",
            [
                gov_cn_policy.CrawlItem(
                    site_id="placeholder",
                    url="https://www.gov.cn/zhengce/rules.htm",
                    url_hash=gov_cn_policy.compute_url_hash("https://www.gov.cn/zhengce/rules.htm"),
                    title="规章",
                    content_category="法规文件",
                    content_subcategory="部门规章",
                )
            ],
            SimpleNamespace(status=200),
        )

    monkeypatch.setattr(gov_cn_policy, "_fetch_list_page_rules", _fake_rules)
    rt = SimpleNamespace(
        site=SimpleNamespace(
            site_code="gov_cn_gjgzk",
            adapter_params_json={"policy_profile": "rules", "page_size": 50},
        ),
        target=SimpleNamespace(
            id=18,
            dept_id=None,
            channel_name="国家规章库",
            channel_path="政策 > 国家规章库",
            content_category="政策文件",
            content_subcategory=None,
        ),
    )

    _url, items, _fr = gov_cn_policy.fetch_list_page(
        rt, page_num=3, params=rt.site.adapter_params_json,
    )

    assert captured == {"page_num": 3, "page_size": 50}
    item = items[0]
    assert item.site_id == "gov_cn_gjgzk"
    assert item.target_id == 18
    assert item.channel_name == "国家规章库"
    assert item.content_category == "法规文件"
    assert item.content_subcategory == "部门规章"


def test_backfill_values_from_stored_zcwjk_raw():
    values = _values_from_raw({
        "id": "26016856",
        "index": "000014349/2026-00026",
        "pcode": "国发〔2026〕7号",
        "puborg": "国务院",
        "childtype": "商贸、海关、旅游\\其他",
        "subjectword": "服务业",
        "ptime": 1776157200000,
        "pubtimeStr": "2026.04.21",
    })

    assert values["native_post_id"] == "26016856"
    assert values["index_no"] == "000014349/2026-00026"
    assert values["publisher"] == "国务院"
    assert values["source_raw"] == "国务院"
    assert values["doc_no"] == "国发〔2026〕7号"
    assert values["content_category"] == "商贸、海关、旅游"
    assert values["content_subcategory"] == "其他"
    assert values["open_category"] == "商贸、海关、旅游\\其他"
    assert values["topic_words"] == "服务业"
    assert values["publish_time"].date().isoformat() == "2026-04-21"
    assert values["publish_date"].isoformat() == "2026-04-14"


def test_backfill_corrects_legacy_values_unless_only_missing():
    article = Article(
        site_id=1,
        url="https://www.gov.cn/zhengce/x.htm",
        url_hash="h",
        content_category="政策文件",
        content_subcategory="商贸、海关、旅游",
        publisher=None,
        doc_no=None,
    )
    values = {
        "content_category": "商贸、海关、旅游",
        "content_subcategory": "其他",
        "publisher": "国务院",
        "doc_no": "国发〔2026〕7号",
    }

    changed = _apply_values(article, values, only_missing=False)
    assert changed == ["content_category", "content_subcategory", "publisher", "doc_no"]
    assert article.content_category == "商贸、海关、旅游"
    assert article.content_subcategory == "其他"

    protected = Article(
        site_id=1,
        url="https://www.gov.cn/zhengce/x.htm",
        url_hash="h2",
        content_category="政策文件",
        content_subcategory=None,
    )
    changed = _apply_values(protected, values, only_missing=True)
    assert changed == ["content_subcategory", "publisher", "doc_no"]
    assert protected.content_category == "政策文件"
    assert protected.content_subcategory == "其他"
