from typing import Optional

import requests

from mflux.release.changelog_parser import ChangelogParser
from mflux.release.git_operations import GitOperations
from mflux.release.github_api import GitHubAPI
from mflux.release.pypi_publisher import PyPIPublisher
from mflux.release.release_validator import ReleaseValidator
from mflux.utils.version_util import VersionUtil


class ReleaseManager:
    @staticmethod
    def create_release(
        github_token: str,
        pypi_token: str,
        test_pypi_token: Optional[str] = None,
        github_repo: str = "filipstrand/mflux",
        package_name: str = "mflux",
    ) -> None:
        # 0. Load version from pyproject.toml
        version = VersionUtil.get_mflux_version()
        tag_name = f"v.{version}"
        print("🚀 Starting MFLUX release process...")
        print(f"📦 Releasing version: {version} (tag: {tag_name}) [from pyproject.toml]")

        # 1. Validate everything is ready for release
        ReleaseValidator.validate_release_ready(version)

        # 2. Check current release state
        git_tag_exists = GitOperations.check_tag_exists(tag_name)
        github_release_exists = GitHubAPI.check_github_release_exists(github_token, github_repo, tag_name)

        # 3. Print release status and exit early if already complete
        ReleaseManager._print_release_status(tag_name, git_tag_exists, github_release_exists)
        if ReleaseManager._is_release_complete(git_tag_exists, github_release_exists):
            return

        # 4. Handle PyPI publishing FIRST (before creating git artifacts)
        if ReleaseManager._should_publish_to_pypi(git_tag_exists, github_release_exists, package_name, version):
            PyPIPublisher.build_and_verify_package()
            PyPIPublisher.publish_to_test_pypi(test_pypi_token, package_name, version)
            PyPIPublisher.publish_to_pypi(pypi_token, package_name, version)

        # 5. Create git tag if needed
        if not git_tag_exists:
            GitOperations.create_and_push_tag(tag_name, version)

        # 6. Create GitHub release if needed
        if not github_release_exists:
            release_notes = ChangelogParser.extract_release_notes_from_changelog(version)
            GitHubAPI.create_github_release(github_token, github_repo, tag_name, version, release_notes)

        print(f"🎉 Release process completed successfully for version {version}!")

    @staticmethod
    def _is_release_complete(git_tag_exists: bool, github_release_exists: bool) -> bool:
        return git_tag_exists and github_release_exists

    @staticmethod
    def _is_release_partial(git_tag_exists: bool, github_release_exists: bool) -> bool:
        return git_tag_exists or github_release_exists

    @staticmethod
    def _should_publish_to_pypi(
        git_tag_exists: bool,
        github_release_exists: bool,
        package_name: str,
        version: str,
    ) -> bool:
        # Only publish if this is a completely new release
        if ReleaseManager._is_release_partial(git_tag_exists, github_release_exists):
            print("⚠️  Skipping PyPI publishing since this appears to be a re-run")
            return False

        # Check if version already exists on PyPI
        try:
            if PyPIPublisher.version_exists_on_pypi(package_name, version, test_pypi=False):
                return False
        except (requests.RequestException, ValueError, OSError) as e:
            print(f"❌ Failed to check PyPI version: {e}")
            raise ValueError(f"PyPI version check failed: {e}") from e

        return True

    @staticmethod
    def _print_release_status(tag_name: str, git_tag_exists: bool, github_release_exists: bool) -> None:
        if ReleaseManager._is_release_complete(git_tag_exists, github_release_exists):
            print(f"✅ Release {tag_name} already exists completely")
            print("🔄 This appears to be a re-run of an existing release - nothing to do!")
        elif ReleaseManager._is_release_partial(git_tag_exists, github_release_exists):
            print("⚠️  Partial release state detected:")
            print(f"   Git tag exists: {git_tag_exists}")
            print(f"   GitHub release exists: {github_release_exists}")
            print("   Will complete the missing parts...")
