"""
CHANGELOG.md editor for programmatic updates.

This module provides tools for editing CHANGELOG.md files following
the Keep a Changelog format.
"""

from datetime import datetime
from pathlib import Path
from typing import Optional, List


class ChangelogEditor:
    """Programmatic editor for CHANGELOG.md files."""

    def __init__(self, changelog_path: Optional[Path] = None):
        """Initialize changelog editor.

        Args:
            changelog_path: Path to CHANGELOG.md file
        """
        self.changelog_path = changelog_path or Path.cwd() / 'CHANGELOG.md'

    def create_version_section(self, version: str, date: Optional[str] = None) -> bool:
        """Create new version section and move Unreleased content.

        Args:
            version: Version number (e.g., "0.11.0")
            date: Release date in YYYY-MM-DD format (defaults to today)

        Returns:
            True if successful, False otherwise
        """
        if date is None:
            date = datetime.now().strftime("%Y-%m-%d")

        # Validate version format
        version_clean = version.lstrip('v')

        if not self.changelog_path.exists():
            print(f"❌ CHANGELOG.md not found at {self.changelog_path}")
            return False

        try:
            with open(self.changelog_path) as f:
                lines = f.readlines()

            # Find Unreleased section
            unreleased_idx = None
            for i, line in enumerate(lines):
                if line.strip() == "## [Unreleased]":
                    unreleased_idx = i
                    break

            if unreleased_idx is None:
                print("❌ No [Unreleased] section found in CHANGELOG.md")
                return False

            # Find next version section or end of Unreleased content
            next_section_idx = None
            for i in range(unreleased_idx + 1, len(lines)):
                if lines[i].startswith("## [") and not lines[i].startswith("## [Unreleased]"):
                    next_section_idx = i
                    break

            # Extract Unreleased content (skip the header line and first blank line)
            if next_section_idx:
                unreleased_content = lines[unreleased_idx + 1:next_section_idx]
            else:
                unreleased_content = lines[unreleased_idx + 1:]

            # Check if there's actual content to move
            has_content = any(line.strip() and not line.strip().startswith('#')
                            for line in unreleased_content)

            if not has_content:
                print(f"⚠️  [Unreleased] section is empty. Add changes before creating release section.")
                print(f"💡 Tip: You can still create the section, but it will be empty.")

            # Create new version section with moved content
            new_section_lines = [
                f"## [{version_clean}] - {date}\n",
            ]

            # Add the unreleased content (preserving structure)
            new_section_lines.extend(unreleased_content)

            # Ensure proper spacing after new section
            if new_section_lines and not new_section_lines[-1].endswith('\n\n'):
                if not new_section_lines[-1].endswith('\n'):
                    new_section_lines[-1] += '\n'
                new_section_lines.append('\n')

            # Build new file content
            # Keep everything up to and including Unreleased header
            new_lines = lines[:unreleased_idx + 1]

            # Add blank line after Unreleased header
            new_lines.append('\n')

            # Add the new version section
            new_lines.extend(new_section_lines)

            # Add remaining sections (if any)
            if next_section_idx:
                new_lines.extend(lines[next_section_idx:])

            # Write back
            with open(self.changelog_path, 'w') as f:
                f.writelines(new_lines)

            print(f"✅ Created section [{version_clean}] - {date} in CHANGELOG.md")
            if has_content:
                print(f"📝 Moved content from [Unreleased] to [{version_clean}]")
            print(f"💡 [Unreleased] section is now empty and ready for new changes")
            return True

        except Exception as e:
            print(f"❌ Error editing CHANGELOG.md: {e}")
            return False

    def get_version_content(self, version: str) -> Optional[List[str]]:
        """Extract content for a specific version section.

        Args:
            version: Version number to extract (e.g., "0.10.0")

        Returns:
            List of lines in the version section, or None if not found
        """
        version_clean = version.lstrip('v')

        if not self.changelog_path.exists():
            return None

        try:
            with open(self.changelog_path) as f:
                lines = f.readlines()

            # Find the version section
            version_idx = None
            for i, line in enumerate(lines):
                if line.strip().startswith(f"## [{version_clean}]"):
                    version_idx = i
                    break

            if version_idx is None:
                return None

            # Find next section
            next_section_idx = None
            for i in range(version_idx + 1, len(lines)):
                if lines[i].startswith("## ["):
                    next_section_idx = i
                    break

            # Extract content
            if next_section_idx:
                return lines[version_idx:next_section_idx]
            else:
                return lines[version_idx:]

        except Exception:
            return None

    def has_unreleased_content(self) -> bool:
        """Check if Unreleased section has any content.

        Returns:
            True if Unreleased section has content, False otherwise
        """
        if not self.changelog_path.exists():
            return False

        try:
            with open(self.changelog_path) as f:
                lines = f.readlines()

            # Find Unreleased section
            unreleased_idx = None
            for i, line in enumerate(lines):
                if line.strip() == "## [Unreleased]":
                    unreleased_idx = i
                    break

            if unreleased_idx is None:
                return False

            # Find next section
            next_section_idx = None
            for i in range(unreleased_idx + 1, len(lines)):
                if lines[i].startswith("## ["):
                    next_section_idx = i
                    break

            # Check content
            if next_section_idx:
                content = lines[unreleased_idx + 1:next_section_idx]
            else:
                content = lines[unreleased_idx + 1:]

            # Check if there's actual content (not just whitespace or section headers)
            return any(line.strip() and not line.strip().startswith('#')
                      for line in content)

        except Exception:
            return False
