from __future__ import annotations

from typing import List, Dict

from .models import SuggestionItem, StyleProfile, DocumentPlan, PlannedEdit


class ChangePlanner:
    def build_plan(
        self,
        repo_path: str,
        style: StyleProfile,
        suggestions: List[SuggestionItem],
        available_files: Dict[str, str],
    ) -> DocumentPlan:
        planned: List[PlannedEdit] = []
        seen_headers: set[tuple[str, str]] = set()

        def section_header(title: str) -> str:
            # use heading level 2 for inserts to be safe
            h = style.heading_style or "#"
            return f"{h*2} {title}\n\n"

        for s in suggestions:
            for target in s.target_files:
                if target not in available_files:
                    # allow planning; renderer will skip if missing
                    pass

                if s.action == "add_dependencies_section":
                    # Use LLM generation instead of template
                    header_key = (target, (s.anchor_hint or "Dependencies").strip().lower())
                    if header_key in seen_headers:
                        continue
                    planned.append(PlannedEdit(
                        file_path=target,
                        edit_type="append_section",
                        anchor={"type": "header", "value": s.anchor_hint or "Dependencies"},
                        content_template="",  # Will be generated by LLM
                        rationale=s.source.get("evidence", ""),
                        suggestion_id=s.id,
                    ))
                    seen_headers.add(header_key)
                elif s.action == "add_system_requirements_section":
                    # Use LLM generation instead of template
                    header_key = (target, (s.anchor_hint or "System Requirements").strip().lower())
                    if header_key in seen_headers:
                        continue
                    planned.append(PlannedEdit(
                        file_path=target,
                        edit_type="append_section",
                        anchor={"type": "header", "value": s.anchor_hint or "System Requirements"},
                        content_template="",  # Will be generated by LLM
                        rationale=s.source.get("evidence", ""),
                        suggestion_id=s.id,
                    ))
                    seen_headers.add(header_key)
                elif s.action == "mention_license_section":
                    content = section_header("License") + "This project is released under the MIT License. See LICENSE for details.\n"
                    header_key = (target, (s.anchor_hint or "License").strip().lower())
                    if header_key in seen_headers:
                        continue
                    planned.append(PlannedEdit(
                        file_path=target,
                        edit_type="append_section",
                        anchor={"type": "header", "value": s.anchor_hint or "License"},
                        content_template=content,
                        rationale=s.source.get("evidence", ""),
                        suggestion_id=s.id,
                    ))
                    seen_headers.add(header_key)
                elif s.action == "normalize_headings_structure":
                    # Minimal placeholder: avoid heavy rewrites
                    # Plan a no-op or a small note; actual normalization could be added later
                    continue
                elif s.action == "add_usage_section":
                    content = section_header("Usage") + "- Brief example of typical workflow.\n"
                    header_key = (target, "usage")
                    if header_key in seen_headers:
                        continue
                    planned.append(PlannedEdit(
                        file_path=target,
                        edit_type="append_section",
                        anchor={"type": "header", "value": "Usage"},
                        content_template=content,
                        rationale=s.source.get("evidence", ""),
                        suggestion_id=s.id,
                    ))
                    seen_headers.add(header_key)
                elif s.action == "replace_intro":
                    # Replace intro block (between H1 and first H2) with a clean Overview section
                    # Use empty content_template so LLM can generate content based on guidance
                    header_key = (target, "overview")
                    if header_key in seen_headers:
                        continue
                    planned.append(PlannedEdit(
                        file_path=target,
                        edit_type="replace_intro_block",
                        anchor={"type": "header", "value": "Overview"},
                        content_template="",  # Will be filled by LLM generation
                        rationale=s.source.get("evidence", ""),
                        suggestion_id=s.id,
                    ))
                    seen_headers.add(header_key)
                elif s.action == "clarify_mandatory_vs_optional":
                    # Use specific guidance from evaluation report instead of generic template
                    guidance = s.content_guidance or "Specify compatibility details for dependencies across operating systems and architectures."
                    content = section_header("Dependencies") + f"- {guidance}\n"
                    header_key = (target, "dependencies")
                    if header_key in seen_headers:
                        continue
                    planned.append(PlannedEdit(
                        file_path=target,
                        edit_type="append_section",
                        anchor={"type": "header", "value": "Dependencies"},
                        content_template=content,
                        rationale=s.source.get("evidence", ""),
                        suggestion_id=s.id,
                    ))
                    seen_headers.add(header_key)
                elif s.action == "add_hardware_requirements":
                    # Use LLM generation instead of template
                    header_key = (target, (s.anchor_hint or "Hardware Requirements").strip().lower())
                    if header_key in seen_headers:
                        continue
                    planned.append(PlannedEdit(
                        file_path=target,
                        edit_type="append_section",
                        anchor={"type": "header", "value": s.anchor_hint or "Hardware Requirements"},
                        content_template="",  # Will be generated by LLM
                        rationale=s.source.get("evidence", ""),
                        suggestion_id=s.id,
                    ))
                    seen_headers.add(header_key)
                elif s.action == "improve_clarity_and_error_handling":
                    # Handle targeted improvements to user guides
                    planned.append(PlannedEdit(
                        file_path=target,
                        edit_type="append_section",
                        anchor={"type": "header", "value": s.anchor_hint or "Introduction"},
                        content_template="",  # Will be filled by LLM generation
                        rationale=s.source.get("evidence", ""),
                        suggestion_id=s.id,
                    ))
                elif s.action == "improve_consistency":
                    # Handle consistency improvements
                    planned.append(PlannedEdit(
                        file_path=target,
                        edit_type="append_section",
                        anchor={"type": "header", "value": s.anchor_hint or "Examples"},
                        content_template="",  # Will be filled by LLM generation
                        rationale=s.source.get("evidence", ""),
                        suggestion_id=s.id,
                    ))
                elif s.action == "improve_tutorial_quality":
                    # Handle tutorial quality improvements
                    planned.append(PlannedEdit(
                        file_path=target,
                        edit_type="append_section",
                        anchor={"type": "header", "value": s.anchor_hint or "Setup"},
                        content_template="",  # Will be filled by LLM generation
                        rationale=s.source.get("evidence", ""),
                        suggestion_id=s.id,
                    ))
                # All actions now use full_replace mode
                planned.append(PlannedEdit(
                    file_path=target,
                    edit_type="full_replace",
                    anchor={"type": "document", "value": "full_document"},
                    content_template="",  # Will be filled by LLM generation
                    rationale=s.source.get("evidence", ""),
                    suggestion_id=s.id,
                ))

        # If a file is planned for full_replace, suppress other edits for that file to avoid redundancy
        by_file: Dict[str, List[PlannedEdit]] = {}
        for e in planned:
            by_file.setdefault(e.file_path, []).append(e)
        filtered: List[PlannedEdit] = []
        for fpath, edits in by_file.items():
            has_full = any(e.edit_type == "full_replace" for e in edits)
            if has_full:
                filtered.extend([e for e in edits if e.edit_type == "full_replace"])
            else:
                filtered.extend(edits)

        return DocumentPlan(repo_path=repo_path, style_profile=style, planned_edits=filtered)


