"""
Release summary generator.

This module generates comprehensive release summary documents from
CHANGELOG content and git metadata.
"""

import subprocess
from datetime import datetime
from pathlib import Path
from typing import Optional, Dict, Any, List
import re


class SummaryGenerator:
    """Generate release summary documents."""

    def __init__(self, project_root: Optional[Path] = None):
        """Initialize summary generator.

        Args:
            project_root: Root directory of the project
        """
        self.project_root = project_root or Path.cwd()
        self.changelog_path = self.project_root / 'CHANGELOG.md'
        self.dist_dir = self.project_root / 'dist'

    def generate(self, version: str, output_path: Optional[Path] = None) -> str:
        """Generate release summary document.

        Args:
            version: Version to generate summary for (e.g., "0.10.0")
            output_path: Optional path to write summary to

        Returns:
            Generated summary content
        """
        version_clean = version.lstrip('v')
        tag_name = f"v{version_clean}"

        # Get components
        changelog_section = self.extract_changelog_section(version_clean)
        git_stats = self.get_git_statistics(tag_name)
        build_artifacts = self.list_build_artifacts()
        validation_results = self.get_validation_results()

        # Determine project name
        project_name = self._get_project_name()

        # Build summary
        summary = f"""# {project_name} {version_clean} Release Summary

**Release Date**: {git_stats.get('release_date', 'Unknown')}
**Git Tag**: {tag_name}
**Commit**: {git_stats.get('commit_hash', 'Unknown')}

---

## Changes

{changelog_section}

---

## Git Statistics

- **Commits**: {git_stats.get('commit_count', 0)} commit(s) since last release
- **Files Changed**: {git_stats.get('files_changed', 0)} file(s)
- **Insertions**: +{git_stats.get('insertions', 0)} lines
- **Deletions**: -{git_stats.get('deletions', 0)} lines
- **Contributors**: {git_stats.get('contributors', 'Unknown')}

---

## Build Artifacts

{build_artifacts}

---

## Validation

{validation_results}

---

**Generated**: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
"""

        if output_path:
            output_path.write_text(summary)
            print(f"✅ Release summary written to {output_path}")

        return summary

    def extract_changelog_section(self, version: str) -> str:
        """Extract CHANGELOG section for a specific version.

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

        Returns:
            Markdown content of the version section
        """
        if not self.changelog_path.exists():
            return "⚠️ CHANGELOG.md not found"

        try:
            with open(self.changelog_path) as f:
                content = f.read()

            # Find the version section
            pattern = rf"## \[{re.escape(version)}\].*?\n\n(.*?)(?=\n## \[|\Z)"
            match = re.search(pattern, content, re.DOTALL)

            if match:
                section_content = match.group(1).strip()
                return section_content if section_content else "No changes documented"
            else:
                return f"⚠️ No section found for version {version} in CHANGELOG.md"

        except Exception as e:
            return f"❌ Error reading CHANGELOG: {e}"

    def get_git_statistics(self, tag: str) -> Dict[str, Any]:
        """Get git statistics for a release tag.

        Args:
            tag: Git tag name (e.g., "v0.10.0")

        Returns:
            Dictionary with git statistics
        """
        stats = {}

        try:
            # Get tag date
            try:
                result = subprocess.run(
                    ['git', 'log', '-1', '--format=%ci', tag],
                    capture_output=True, text=True, check=True, cwd=self.project_root
                )
                date_str = result.stdout.strip()
                # Parse to get just the date
                stats['release_date'] = date_str.split()[0] if date_str else 'Unknown'
            except subprocess.CalledProcessError:
                stats['release_date'] = 'Unknown'

            # Get commit hash
            try:
                result = subprocess.run(
                    ['git', 'rev-parse', tag],
                    capture_output=True, text=True, check=True, cwd=self.project_root
                )
                stats['commit_hash'] = result.stdout.strip()[:8]
            except subprocess.CalledProcessError:
                stats['commit_hash'] = 'Unknown'

            # Find previous tag
            try:
                result = subprocess.run(
                    ['git', 'describe', '--tags', '--abbrev=0', f'{tag}^'],
                    capture_output=True, text=True, check=True, cwd=self.project_root
                )
                previous_tag = result.stdout.strip()
            except subprocess.CalledProcessError:
                # No previous tag, use initial commit
                previous_tag = None

            # Get commit count
            if previous_tag:
                try:
                    result = subprocess.run(
                        ['git', 'rev-list', '--count', f'{previous_tag}..{tag}'],
                        capture_output=True, text=True, check=True, cwd=self.project_root
                    )
                    stats['commit_count'] = int(result.stdout.strip())
                except subprocess.CalledProcessError:
                    stats['commit_count'] = 0
            else:
                try:
                    result = subprocess.run(
                        ['git', 'rev-list', '--count', tag],
                        capture_output=True, text=True, check=True, cwd=self.project_root
                    )
                    stats['commit_count'] = int(result.stdout.strip())
                except subprocess.CalledProcessError:
                    stats['commit_count'] = 0

            # Get file changes, insertions, deletions
            if previous_tag:
                diff_range = f'{previous_tag}..{tag}'
            else:
                diff_range = tag

            try:
                result = subprocess.run(
                    ['git', 'diff', '--shortstat', diff_range],
                    capture_output=True, text=True, check=True, cwd=self.project_root
                )
                shortstat = result.stdout.strip()

                # Parse shortstat: "X files changed, Y insertions(+), Z deletions(-)"
                files_match = re.search(r'(\d+) files? changed', shortstat)
                insert_match = re.search(r'(\d+) insertions?', shortstat)
                delete_match = re.search(r'(\d+) deletions?', shortstat)

                stats['files_changed'] = int(files_match.group(1)) if files_match else 0
                stats['insertions'] = int(insert_match.group(1)) if insert_match else 0
                stats['deletions'] = int(delete_match.group(1)) if delete_match else 0
            except subprocess.CalledProcessError:
                stats['files_changed'] = 0
                stats['insertions'] = 0
                stats['deletions'] = 0

            # Get contributors
            try:
                result = subprocess.run(
                    ['git', 'log', '--format=%an', f'{previous_tag}..{tag}' if previous_tag else tag],
                    capture_output=True, text=True, check=True, cwd=self.project_root
                )
                contributors = list(set(result.stdout.strip().split('\n')))
                stats['contributors'] = ', '.join(contributors) if contributors and contributors[0] else 'Unknown'
            except subprocess.CalledProcessError:
                stats['contributors'] = 'Unknown'

        except Exception as e:
            print(f"⚠️  Error getting git statistics: {e}")

        return stats

    def list_build_artifacts(self) -> str:
        """List build artifacts in dist/ directory.

        Returns:
            Formatted markdown list of build artifacts
        """
        if not self.dist_dir.exists():
            return "No build artifacts found (dist/ directory does not exist)"

        artifacts = list(self.dist_dir.glob('*'))
        if not artifacts:
            return "No build artifacts found in dist/"

        lines = []
        for artifact in sorted(artifacts):
            if artifact.is_file():
                size = artifact.stat().st_size
                size_kb = size / 1024
                size_mb = size / (1024 * 1024)

                if size_mb >= 1:
                    size_str = f"{size_mb:.2f} MB"
                else:
                    size_str = f"{size_kb:.2f} KB"

                lines.append(f"- **{artifact.name}** ({size_str})")

        return '\n'.join(lines) if lines else "No build artifacts found"

    def get_validation_results(self) -> str:
        """Get validation results summary.

        Returns:
            Formatted validation results
        """
        # Import here to avoid circular dependency
        from ..utils.validation import ReleaseValidator

        validator = ReleaseValidator(self.project_root)
        is_valid, issues = validator.validate_release_state(force=True)  # Force to get all issues

        if is_valid:
            return "✅ All validation checks passed"
        else:
            lines = ["Validation Issues:"]
            for issue in issues:
                lines.append(f"- {issue}")
            return '\n'.join(lines)

    def _get_project_name(self) -> str:
        """Get project name from pyproject.toml.

        Returns:
            Project name or default
        """
        pyproject_path = self.project_root / 'pyproject.toml'

        if not pyproject_path.exists():
            return "Project"

        try:
            import tomllib
        except ImportError:
            try:
                import tomli as tomllib
            except ImportError:
                return "Project"

        try:
            with open(pyproject_path, 'rb') as f:
                config = tomllib.load(f)
                return config.get('project', {}).get('name', 'Project').title()
        except Exception:
            return "Project"
