"""
目标页数与一级篇章数量区间：阈值与 generator._effective_volume 一致。

小章节（自动填充子目录行）总条数：与「目标页数」线性映射，见 subchapter_total_* 与
allocate_subchapters_to_main *。
"""
from __future__ import annotations

import random
from typing import List, Optional, Tuple

# 与 modules.generator._effective_volume 页数分界一致
PAGE_VOLUME_THRESHOLDS = (125, 175, 225)

# 各篇幅档位对应的一级篇章数量 [min, max]（与页数映射表一致）
TOP_LEVEL_CHAPTER_RANGES = {
    'concise': (6, 8),
    'standard': (8, 10),
    'detailed': (10, 12),
    'full': (12, 16),
}

# 小章节总条数 = slope * pages + intercept（过点 100->78, 300->212）
SUBCHAPTER_PAGES_SLOPE = 0.67
SUBCHAPTER_PAGES_INTERCEPT = 11.0
SUBCHAPTER_JITTER_LOW = 0.9
SUBCHAPTER_JITTER_HIGH = 1.1
# expand 在请求/库/配置均未给出页数时，按 100 页 ≈ 基线 78 章 ±10%，避免小章节失控到数百
EXPAND_OUTLINE_DEFAULT_TARGET_PAGES = 100


def subchapter_total_base_from_pages(pages: int) -> float:
    return SUBCHAPTER_PAGES_SLOPE * float(pages) + SUBCHAPTER_PAGES_INTERCEPT


def subchapter_jitter_bounds(n_base: float) -> Tuple[int, int]:
    """
    对线性基线 N_base 的严格 ±10% 整数闭区间 [lo, hi]（用于全标小章节行总数抽样后夹紧）。
    例：N_base=78（约 100 页）→ lo=70, hi=86。
    """
    lo = max(1, int(round(n_base * SUBCHAPTER_JITTER_LOW)))
    hi = max(lo, int(round(n_base * SUBCHAPTER_JITTER_HIGH)))
    return lo, hi


def subchapter_total_effective(
    pages: int,
    k: int,
    rng: Optional[random.Random] = None,
) -> int:
    """
    在目标页数 P 下，对一次「小章节自动填充」抽样的子章节行总数上界（全标合计）。
    先按 N_base(P)=0.67*P+11 与 U~Uniform(0.9,1.1) 取整，再**严格夹紧**到 [round(N_base*0.9), round(N_base*1.1)]，
    故 100 页时锚定 78±10% → 恒在 70–86 条（在仅受随机影响时）。

    不再用 max(n, k) 抬升总数：主章数 k 很大时若强行「每章至少 1 条」会把 N 抬到 300+，与 78±10% 目标冲突。
    当 n < k 时由 allocate_subchapters_to_mains 将额度优先分给部分主章，其余主章 quota 为 0（该次不填小章）。
    pages<=0 或 k<=0 时返回 0（调用方不应在 TARGET_PAGES>0 且可扩展主章>0 之外使用）。
    """
    if pages <= 0 or k <= 0:
        return 0
    r = rng if rng is not None else random.Random()
    n_base = subchapter_total_base_from_pages(pages)
    lo, hi = subchapter_jitter_bounds(n_base)
    n = int(round(n_base * r.uniform(SUBCHAPTER_JITTER_LOW, SUBCHAPTER_JITTER_HIGH)))
    n = min(max(n, lo), hi)
    return n


def allocate_subchapters_to_mains(n: int, k: int) -> List[int]:
    """
    将整数 n 均分到 k 个主章：前 n%k 个主章得 floor+1，其余得 floor；k=0 返回 []。
    """
    if k <= 0:
        return []
    n = max(0, n)
    q, r = n // k, n % k
    return [q + 1] * r + [q] * (k - r)


def resolve_expand_target_pages(
    request_pages: Optional[int],
    no_subchapter_limit: bool,
    db_pages: int,
    config_pages: int,
) -> int:
    """
    得到本次「自动填充小章节」使用的目标页数 P（>0 则启用条数上界，0=不限制）。

    显式不限制时返回 0；否则优先正数 request → 落库值 → 全局配置 → 默认 100 页。
    """
    if no_subchapter_limit:
        return 0
    if request_pages is not None and int(request_pages) > 0:
        return int(request_pages)
    d = int(db_pages or 0)
    if d > 0:
        return d
    c = int(config_pages or 0)
    if c > 0:
        return c
    return EXPAND_OUTLINE_DEFAULT_TARGET_PAGES


def volume_key_from_target_pages(pages: int, content_volume_default: str = 'standard') -> str:
    """与 _effective_volume 相同逻辑的档位 key（不读 config，便于测试）。"""
    if pages <= 0:
        return content_volume_default
    if pages <= PAGE_VOLUME_THRESHOLDS[0]:
        return 'concise'
    if pages <= PAGE_VOLUME_THRESHOLDS[1]:
        return 'standard'
    if pages <= PAGE_VOLUME_THRESHOLDS[2]:
        return 'detailed'
    return 'full'


def top_level_chapter_range_from_pages(pages: int, content_volume_default: str = 'standard') -> Tuple[int, int]:
    """
    返回一级篇章数量区间 (lo, hi)。
    未设置目标页数时沿用默认 8–10 章。
    """
    if pages <= 0:
        return TOP_LEVEL_CHAPTER_RANGES['standard']
    vk = volume_key_from_target_pages(pages, content_volume_default)
    return TOP_LEVEL_CHAPTER_RANGES[vk]


def outline_chapter_count_hint(
    pages: int,
    content_volume_default: str = 'standard',
    page_char_estimate: int = 700,
) -> str:
    """
    嵌入大纲提示词的篇章约束句（替换原固定「8–10 个」相关描述）。

    当 pages>0 时提醒：全稿正文字量与「页数×每页字数」可替换的总目标同量级，目录
    层次不宜过细，以免成稿后每节可写篇幅过薄、难成合理技术应答。
    """
    pce = max(1, int(page_char_estimate or 700))
    if pages <= 0:
        return (
            '总的章节数应该控制在8-10个，一级篇章总数不超过10个'
        )
    lo, hi = top_level_chapter_range_from_pages(pages, content_volume_default)
    total_g = int(round(pages * pce))
    return (
        f'总的章节数应该控制在约 {lo}–{hi} 个，一级篇章总数不超过 {hi} 个'
        f'（目标约 {pages} 页，按目标页数映射的篇幅档位估算）。'
        f'全稿正文字量规模需与总目标约 {total_g} 字'
        f'（{pages} 页×约每页 {pce} 字的粗略换算计）同量级，目录层次与末级小节目不宜过细，'
        f'避免叶节数过多时单节篇幅过薄、难以成文。'
    )


def outline_chapter_count_hint_with_rating_variant(
    pages: int,
    content_volume_default: str = 'standard',
    page_char_estimate: int = 700,
) -> str:
    """带评分目录模板中的同类约束（原含「不超过10个」的收紧表述）。"""
    pce = max(1, int(page_char_estimate or 700))
    if pages <= 0:
        return (
            '总的章节数应该控制在8-10个,不超过10个'
        )
    lo, hi = top_level_chapter_range_from_pages(pages, content_volume_default)
    total_g = int(round(pages * pce))
    return (
        f'总的章节数应该控制在约 {lo}–{hi} 个,不超过{hi} 个'
        f'（目标约 {pages} 页，按目标页数映射的篇幅档位估算）'
        f'全稿正文字量约与总目标 {total_g} 字同量级,末级子目不宜过细'
    )
