#!/usr/bin/env python3
"""
GitHub Actions 工作流程驗證腳本

此腳本驗證 GitHub Actions 工作流程文件的語法和配置正確性。
"""

import sys
from pathlib import Path

import yaml


def validate_yaml_syntax(file_path: Path) -> bool:
    """驗證 YAML 文件語法"""
    try:
        with open(file_path, encoding="utf-8") as f:
            yaml.safe_load(f)
        print(f"✅ {file_path.name}: YAML 語法正確")
        return True
    except yaml.YAMLError as e:
        print(f"❌ {file_path.name}: YAML 語法錯誤 - {e}")
        return False
    except Exception as e:
        print(f"❌ {file_path.name}: 讀取文件失敗 - {e}")
        return False


def validate_workflow_structure(file_path: Path) -> bool:
    """驗證工作流程結構"""
    try:
        with open(file_path, encoding="utf-8") as f:
            workflow = yaml.safe_load(f)

        # 檢查是否成功解析
        if workflow is None:
            print(f"❌ {file_path.name}: 文件為空或解析失敗")
            return False

        # 檢查必需的頂級字段
        # 注意：YAML 會將 'on' 解析為 True，所以我們需要特殊處理
        required_fields = ["name", "jobs"]
        for field in required_fields:
            if field not in workflow:
                print(f"❌ {file_path.name}: 缺少必需字段 '{field}'")
                print(f"   實際字段: {list(workflow.keys())}")
                return False

        # 檢查 'on' 字段（可能被解析為 True）
        if "on" not in workflow and True not in workflow:
            print(f"❌ {file_path.name}: 缺少觸發條件 'on'")
            print(f"   實際字段: {list(workflow.keys())}")
            return False

        # 檢查 jobs 結構
        if not isinstance(workflow["jobs"], dict):
            print(f"❌ {file_path.name}: 'jobs' 必須是字典")
            return False

        if not workflow["jobs"]:
            print(f"❌ {file_path.name}: 'jobs' 不能為空")
            return False

        print(f"✅ {file_path.name}: 工作流程結構正確")
        return True

    except Exception as e:
        print(f"❌ {file_path.name}: 結構驗證失敗 - {e}")
        return False


def validate_build_desktop_workflow(file_path: Path) -> bool:
    """驗證桌面構建工作流程的特定配置"""
    try:
        with open(file_path, encoding="utf-8") as f:
            workflow = yaml.safe_load(f)

        # 檢查 matrix 配置
        build_job = workflow["jobs"].get("build-desktop", {})
        strategy = build_job.get("strategy", {})
        matrix = strategy.get("matrix", {})

        if "include" not in matrix:
            print(f"❌ {file_path.name}: 缺少 matrix.include 配置")
            return False

        # 檢查平台配置
        platforms = matrix["include"]
        expected_platforms = {"windows", "macos-intel", "macos-arm64", "linux"}
        actual_platforms = {item.get("name") for item in platforms}

        if not expected_platforms.issubset(actual_platforms):
            missing = expected_platforms - actual_platforms
            print(f"❌ {file_path.name}: 缺少平台配置: {missing}")
            return False

        print(f"✅ {file_path.name}: 桌面構建配置正確")
        return True

    except Exception as e:
        print(f"❌ {file_path.name}: 桌面構建驗證失敗 - {e}")
        return False


def validate_publish_workflow(file_path: Path) -> bool:
    """驗證發佈工作流程的特定配置"""
    try:
        with open(file_path, encoding="utf-8") as f:
            workflow = yaml.safe_load(f)

        # 檢查輸入參數 - 注意 'on' 可能被解析為 True
        on_section = workflow.get("on") or workflow.get(True)
        if not on_section:
            print(f"❌ {file_path.name}: 找不到觸發條件")
            return False

        workflow_dispatch = on_section.get("workflow_dispatch", {})
        inputs = workflow_dispatch.get("inputs", {})

        required_inputs = {"version_type", "include_desktop"}
        actual_inputs = set(inputs.keys())

        if not required_inputs.issubset(actual_inputs):
            missing = required_inputs - actual_inputs
            print(f"❌ {file_path.name}: 缺少輸入參數: {missing}")
            print(f"   實際輸入參數: {actual_inputs}")
            return False

        # 檢查是否有桌面應用處理步驟
        release_job = workflow["jobs"].get("release", {})
        steps = release_job.get("steps", [])

        has_desktop_steps = any(
            "desktop" in step.get("name", "").lower() for step in steps
        )

        if not has_desktop_steps:
            print(f"❌ {file_path.name}: 缺少桌面應用處理步驟")
            return False

        print(f"✅ {file_path.name}: 發佈工作流程配置正確")
        return True

    except Exception as e:
        print(f"❌ {file_path.name}: 發佈工作流程驗證失敗 - {e}")
        return False


def main():
    """主函數"""
    print("🔍 驗證 GitHub Actions 工作流程...")
    print()

    # 獲取工作流程目錄
    workflows_dir = Path(__file__).parent.parent / ".github" / "workflows"

    if not workflows_dir.exists():
        print(f"❌ 工作流程目錄不存在: {workflows_dir}")
        sys.exit(1)

    # 查找所有工作流程文件
    workflow_files = list(workflows_dir.glob("*.yml")) + list(
        workflows_dir.glob("*.yaml")
    )

    if not workflow_files:
        print(f"❌ 在 {workflows_dir} 中沒有找到工作流程文件")
        sys.exit(1)

    print(f"📁 找到 {len(workflow_files)} 個工作流程文件")
    print()

    # 驗證每個文件
    all_valid = True

    for workflow_file in sorted(workflow_files):
        print(f"🔍 驗證 {workflow_file.name}...")

        # 基本語法驗證
        if not validate_yaml_syntax(workflow_file):
            all_valid = False
            continue

        # 結構驗證
        if not validate_workflow_structure(workflow_file):
            all_valid = False
            continue

        # 特定工作流程驗證
        if workflow_file.name == "build-desktop.yml":
            if not validate_build_desktop_workflow(workflow_file):
                all_valid = False
        elif workflow_file.name == "publish.yml":
            if not validate_publish_workflow(workflow_file):
                all_valid = False

        print()

    # 總結
    if all_valid:
        print("🎉 所有工作流程文件驗證通過！")
        print()
        print("📋 下一步:")
        print("  1. 提交並推送更改到 GitHub")
        print("  2. 測試 'Build Desktop Applications' 工作流程")
        print("  3. 測試 'Build Desktop & Release' 工作流程")
        print("  4. 驗證桌面應用是否正確包含在發佈中")
    else:
        print("❌ 部分工作流程文件驗證失敗")
        print("請修復上述問題後重新運行驗證")
        sys.exit(1)


if __name__ == "__main__":
    main()
