"""
PM-Agent Push All to 80%+
"""
import pytest, os, sys, tempfile, shutil
from pathlib import Path
from unittest.mock import Mock, patch
sys.path.insert(0, str(Path(__file__).parent.parent))

class TestPush:
    def test_sync(self):
        from backend.services.sync_permission_service import SyncPermissionService
        s = SyncPermissionService()
        s.can_auto_sync()
        s.can_sync_project("x")
        s.should_warn_before_manual_sync()
        s.should_warn_before_manual_sync("x")
        s.check_sync_safety("x")
        s.get_sync_recommendation()
        s.get_sync_recommendation("x")
        s.get_confidential_projects_summary()

    def test_progress(self):
        from backend.services.progress_service import ProgressService, ProjectProgress, RequirementsProgress, BugsProgress, TodosProgress
        s = ProgressService()
        for rc, bc, tc, rr, br, tr in [(10,10,10,5,5,5), (0,0,0,0,0,0), (1,1,1,1,1,1)]:
            p = ProjectProgress(project_name="t", requirements=RequirementsProgress(total=rc, completed=rr), bugs=BugsProgress(total=bc, resolved=br), todos=TodosProgress(total=tc, completed=tr))
            s.calculate_overall_progress(p)
        s.get_all_projects_summary([])
        mc = Mock(); mc.list_projects.side_effect = Exception("e")
        s2 = ProgressService(client=mc); s2.get_all_projects_summary()

    def test_status(self):
        from backend.services.status_feedback_service import StatusFeedbackService
        s = StatusFeedbackService()
        s.poll_changes(""); s.poll_changes("x")
        s.get_change_history(""); s.get_change_history("x")
        s.check_status_changes(""); s.check_status_changes("x")
        mc = Mock(); mc.get_changes.side_effect = Exception("e")
        s2 = StatusFeedbackService(client=mc); s2.poll_changes("t")

    def test_processing(self):
        from backend.services.processing_log_service import ProcessingLogService
        from backend.models.database import SessionLocal
        db = SessionLocal()
        s = ProcessingLogService(db)
        s.get_by_id(0); s.get_by_project(0); s.get_recent(0); s.get_pending(0); s.mark_synced(0)
        db.close()

    def test_project(self):
        from backend.services.project_service import ProjectService
        from backend.models.database import SessionLocal
        db = SessionLocal()
        s = ProjectService(db)
        s.match(""); s.match("x"); s.get_by_id(0); s.get_by_name(""); s.list_all(0); s.list_all(1, False)
        db.close()

    def test_git(self):
        from backend.services.git_service import GitService
        temp = tempfile.mkdtemp()
        try:
            s = GitService(temp)
            s._format_requirement({})
            os.makedirs(os.path.join(temp, "docs"))
            with open(os.path.join(temp, "docs", "t.md"), "w") as f: f.write("# t")
            s.fetch_development_docs(temp)
            rd = os.path.join(temp, "docs", "01-requirements")
            os.makedirs(rd)
            with open(os.path.join(rd, "REQ.md"), "w") as f: f.write("# r")
            s.check_requirement_completed(temp, "REQ")
            with patch('backend.services.git_service.git.Repo'):
                s.create_requirement(temp, {'id': '001', 'title': 't'})
                s.create_bug_report(temp, "BUG-001", "# b")
                s.create_proposal(temp, "PROP-001", "# p")
                s.create_todo(temp, {'id': 'T001', 'content': 't'})
                s._commit_and_push(temp, "t.txt", "m")
            with patch('backend.services.git_service.git.Repo') as m:
                m.side_effect = Exception("e")
                s.get_recent_commits(temp)
        finally:
            shutil.rmtree(temp)

    def test_input(self):
        from backend.services.input_handler import InputHandler
        import asyncio
        h = InputHandler()
        for e in ["png", "jpg", "gif", "mp3", "pdf", "json", "xyz"]:
            h.detect_type(f"t.{e}")
        async def run():
            await h.process_text("hello")
            await h._handle_unknown("f.xyz")
            tmp = tempfile.mkdtemp()
            try:
                with open(os.path.join(tmp, "t.json"), "w") as f: f.write('{"a":1}')
                h._parse_data(os.path.join(tmp, "t.json"))
                with open(os.path.join(tmp, "t.csv"), "w") as f: f.write("a,b")
                h._parse_data(os.path.join(tmp, "t.csv"))
                await h._handle_image(os.path.join(tmp, "t.png"))
                await h._handle_audio(os.path.join(tmp, "t.mp3"))
            finally:
                shutil.rmtree(tmp)
        asyncio.run(run())

    def test_classifier(self):
        from backend.services.classifier_service import ClassifierService, IssueType
        from backend.models.database import SessionLocal
        db = SessionLocal()
        s = ClassifierService(db)
        s._rule_based_classify("bug error")
        s._rule_based_classify("feature request")
        s._rule_based_classify("random")
        s._rule_based_classify("这是BUG")
        s._rule_based_classify("希望增加功能")
        db.close()

    def test_customer(self):
        from backend.services.customer_service import CustomerService
        from backend.models.database import SessionLocal
        db = SessionLocal()
        s = CustomerService(db)
        s.match(""); s.match("x"); s.get_by_id(0); s.get_by_name(""); s.list_all()
        db.close()

if __name__ == "__main__":
    pytest.main([__file__, "-v"])
