from __future__ import annotations

import io
import unittest
from types import SimpleNamespace
from unittest.mock import patch


class SystemInitializerCliTest(unittest.TestCase):
    def test_parse_fresh_arguments(self) -> None:
        from scripts.system_initialize import parse_args

        args = parse_args(
            [
                "fresh",
                "--company-name",
                "百华",
                "--admin-name",
                "超级管理员",
                "--admin-phone",
                "13800000000",
                "--admin-password",
                "secret123",
                "--smart-operation-report",
                "off",
                "--delete-files",
                "--allow-any-database",
            ]
        )

        self.assertEqual(args.mode, "fresh")
        self.assertEqual(args.company_name, "百华")
        self.assertEqual(args.admin_name, "超级管理员")
        self.assertEqual(args.admin_phone, "13800000000")
        self.assertEqual(args.admin_password, "secret123")
        self.assertEqual(args.smart_operation_report, "off")
        self.assertTrue(args.delete_files)
        self.assertTrue(args.allow_any_database)
        self.assertFalse(hasattr(args, "confirm_reset"))

    def test_parse_reset_arguments(self) -> None:
        from scripts.system_initialize import parse_args

        args = parse_args(
            [
                "reset",
                "--company-name",
                "百华",
                "--admin-name",
                "超级管理员",
                "--admin-phone",
                "13800000000",
                "--admin-password",
                "secret123",
                "--confirm-reset",
                "--smart-operation-report",
                "off",
            ]
        )

        self.assertEqual(args.mode, "reset")
        self.assertEqual(args.company_name, "百华")
        self.assertEqual(args.admin_phone, "13800000000")
        self.assertTrue(args.confirm_reset)
        self.assertEqual(args.smart_operation_report, "off")

    def test_main_fresh_creates_database_then_initializes_without_real_db(self) -> None:
        from scripts import system_initialize

        settings = SimpleNamespace(
            mysql_host="127.0.0.1",
            mysql_port=3306,
            mysql_database="erp_test",
            mysql_dsn="mysql+pymysql://root:secret@127.0.0.1:3306/erp_test",
        )
        result = SimpleNamespace(
            backup_path=None,
            summary_path="/tmp/summary.json",
            seeded={"admin_username": "13800000000"},
        )

        with (
            patch.object(system_initialize, "get_settings", return_value=settings),
            patch.object(system_initialize, "create_engine", return_value="engine") as create_engine_mock,
            patch.object(system_initialize, "create_database_if_missing", return_value="erp_test") as create_db_mock,
            patch.object(system_initialize, "fresh_initialize_database", return_value=result) as fresh_mock,
            patch.object(system_initialize, "reset_existing_database_with_backup") as reset_mock,
            patch("sys.stdout", new_callable=io.StringIO) as stdout,
        ):
            exit_code = system_initialize.main(
                [
                    "fresh",
                    "--company-name",
                    "百华",
                    "--admin-name",
                    "超级管理员",
                    "--admin-phone",
                    "13800000000",
                    "--admin-password",
                    "secret123",
                    "--smart-operation-report",
                    "on",
                ]
            )

        self.assertEqual(exit_code, 0)
        create_db_mock.assert_called_once_with(settings)
        create_engine_mock.assert_called_once_with(settings.mysql_dsn, pool_pre_ping=True, future=True)
        fresh_mock.assert_called_once()
        reset_mock.assert_not_called()
        self.assertIn("mode=fresh", stdout.getvalue())
        self.assertIn("database=127.0.0.1:3306/erp_test", stdout.getvalue())
        self.assertIn("summary_path=/tmp/summary.json", stdout.getvalue())
        self.assertIn("admin_username=13800000000", stdout.getvalue())

    def test_main_reset_calls_backup_reset_without_swallowing_service_errors(self) -> None:
        from scripts import system_initialize

        settings = SimpleNamespace(
            mysql_host="127.0.0.1",
            mysql_port=3306,
            mysql_database="erp_test",
            mysql_dsn="mysql+pymysql://root:secret@127.0.0.1:3306/erp_test",
        )

        with (
            patch.object(system_initialize, "get_settings", return_value=settings),
            patch.object(system_initialize, "create_engine", return_value="engine"),
            patch.object(
                system_initialize,
                "reset_existing_database_with_backup",
                side_effect=ValueError("Refusing to reset database without --confirm-reset"),
            ),
        ):
            with self.assertRaisesRegex(ValueError, "confirm-reset"):
                system_initialize.main(
                    [
                        "reset",
                        "--company-name",
                        "百华",
                        "--admin-name",
                        "超级管理员",
                        "--admin-phone",
                        "13800000000",
                        "--admin-password",
                        "secret123",
                    ]
                )


if __name__ == "__main__":
    unittest.main()
