import ast
import unittest
from pathlib import Path


ROOT = Path(__file__).resolve().parents[1]


def module(path: str) -> ast.Module:
    return ast.parse((ROOT / path).read_text(encoding="utf-8"))


def function_names(parsed: ast.Module) -> set[str]:
    return {
        node.name
        for node in ast.walk(parsed)
        if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef))
    }


def source(path: str) -> str:
    return (ROOT / path).read_text(encoding="utf-8")


class DeliveryReadinessTests(unittest.TestCase):
    def test_config_routes_require_current_user_or_admin(self) -> None:
        config_source = source("app/api/config.py")

        self.assertTrue("get_current_user" in config_source or "require_admin" in config_source)
        self.assertIn("current_user", config_source)

    def test_security_defines_admin_guard(self) -> None:
        parsed = module("app/core/security.py")
        self.assertIn("require_admin", function_names(parsed))

    def test_runtime_services_read_database_config(self) -> None:
        email_source = source("app/services/email_service.py")
        telegram_source = source("app/services/telegram_service.py")

        self.assertIn("get_smtp_config", email_source)
        self.assertIn("get_telegram_config", telegram_source)

    def test_no_hard_coded_delivery_secrets(self) -> None:
        forbidden = [
            "erp-super-secret",
            "Admin@2026!",
            "1234567890",
        ]

        for relative_path in [
            "app/core/security.py",
            "create_admin.py",
            "init_db.py",
            ".env",
        ]:
            file_source = source(relative_path)
            for marker in forbidden:
                self.assertNotIn(marker, file_source, f"{marker!r} found in {relative_path}")

    def test_localhost_mysql_is_not_forced_to_sqlite(self) -> None:
        db_source = source("app/core/database.py")
        self.assertNotIn('DB_HOST == "localhost"', db_source)

    def test_frontend_finance_clients_and_routes_exist(self) -> None:
        router = source("../frontend/src/router/index.js")
        app_apis = {
            "expenses": source("../frontend/src/api/expenses.js"),
            "employees": source("../frontend/src/api/employees.js"),
            "payroll": source("../frontend/src/api/payroll.js"),
            "finance": source("../frontend/src/api/finance.js"),
        }

        self.assertIn("path: 'expenses'", router)
        self.assertIn("path: 'receipts'", router)
        self.assertIn("path: 'employees'", router)
        self.assertIn("path: 'payroll'", router)
        self.assertIn("path: 'finance'", router)
        self.assertIn("/upload-receipt", app_apis["expenses"])
        self.assertIn("/calculate", app_apis["payroll"])
        self.assertIn("/summary", app_apis["finance"])

    def test_employee_and_payroll_pages_exist(self) -> None:
        layout = source("../frontend/src/components/AppLayout.vue")
        employees_page = source("../frontend/src/pages/EmployeesPage.vue")
        detail_page = source("../frontend/src/pages/EmployeeDetailPage.vue")
        payroll_page = source("../frontend/src/pages/PayrollPage.vue")

        self.assertIn("员工管理", layout)
        self.assertIn("IRD", employees_page)
        self.assertIn("payrollApi", detail_page)
        self.assertIn("employeesApi", payroll_page)
        self.assertIn("calculate", payroll_page.lower())

    def test_finance_summary_page_supports_gst_and_date_views(self) -> None:
        page = source("../frontend/src/pages/FinanceSummaryPage.vue")

        self.assertIn("GST", page)
        self.assertIn("fiscal", page.lower())
        self.assertIn("calendar", page.lower())
        self.assertIn("custom", page.lower())
        self.assertIn("financeApi.summary", page)


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