from __future__ import annotations

import json
from types import SimpleNamespace

import pytest
from fastapi import HTTPException
from sqlalchemy import create_engine
from sqlalchemy.orm import Session
from sqlalchemy.pool import StaticPool

from app.models import Base
from app.models.ai_config import ContentGenerationConfig
from app.services.content_generation_config_service import (
    SAMPLE_VALUES,
    ContentGenerationConfigService,
)
from app.services.tracked_generation_service import TrackedGenerationService


def _db() -> Session:
    engine = create_engine("sqlite:///:memory:", connect_args={"check_same_thread": False}, poolclass=StaticPool)
    Base.metadata.create_all(engine)
    return Session(engine)


def test_template_preview_keeps_locked_notice_and_rejects_unknown_variables():
    content = ContentGenerationConfigService.preview(
        "help_card",
        "问题：{{issue}}\n摘要：{{summary}}",
    )

    assert "问题：我第一次参加带练" in content
    assert "不会自动发送给老师" in content
    assert "不代表已经转人工处理" in content

    with pytest.raises(HTTPException) as error:
        ContentGenerationConfigService.preview(
            "help_card",
            "问题：{{issue}}\n摘要：{{summary}}\n未知：{{unknown}}",
        )
    assert error.value.status_code == 400
    assert "未知变量" in str(error.value.detail)

    with pytest.raises(HTTPException) as malformed:
        ContentGenerationConfigService.preview(
            "help_card",
            "问题：{{issue}}\n摘要：{{summary}}\n错误变量：{{bad-name}}",
        )
    assert malformed.value.status_code == 400


def test_config_versions_save_reset_and_restore_without_overwriting_history():
    with _db() as db:
        first = ContentGenerationConfigService.save(
            db,
            config_type="help_card",
            template_content="自定义一：{{issue}}\n{{summary}}",
            instruction_content="只整理明确内容",
            updated_by=1,
        )
        db.commit()
        first_id = first.id

        reset = ContentGenerationConfigService.reset(db, config_type="help_card", updated_by=1)
        db.commit()
        restored = ContentGenerationConfigService.restore(
            db,
            config_type="help_card",
            source_config_id=first_id,
            updated_by=2,
        )
        db.commit()

        assert db.query(ContentGenerationConfig).count() == 3
        assert restored.id != first_id
        assert restored.source_config_id == first_id
        assert restored.change_type == "restore"
        assert restored.template_content == "自定义一：{{issue}}\n{{summary}}"
        assert reset.change_type == "reset"
        assert ContentGenerationConfigService.current(db, "help_card").id == restored.id


def test_ai_generation_uses_configured_instruction_and_only_accepts_allowed_fields(monkeypatch):
    captured: dict[str, str] = {}

    def fake_generate(db, *, prompt, scenario, user_id):
        captured["prompt"] = prompt
        return SimpleNamespace(
            answer=json.dumps(
                {
                    "issue": "整理后的问题",
                    "summary": "整理后的摘要",
                    "current_focus": "整理后的关注",
                    "unknown": "不能进入卡片",
                },
                ensure_ascii=False,
            )
        )

    monkeypatch.setattr(TrackedGenerationService, "generate", fake_generate)
    with _db() as db:
        generated, used_fallback = ContentGenerationConfigService.generate_values(
            db,
            config_type="help_card",
            instruction_content="优先保留用户原话",
            values=dict(SAMPLE_VALUES),
            user_id=1,
        )

    assert used_fallback is False
    assert generated["issue"] == "整理后的问题"
    assert generated["summary"] == "整理后的摘要"
    assert "unknown" not in generated
    assert "优先保留用户原话" in captured["prompt"]
    assert "不得分析人格" in captured["prompt"]
