#!/usr/bin/env python3
#
# Copyright 2025 The Project CHIP Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
""".
This script is designed to automate the process of fixing `[[nodiscard]]` related
build errors. It works by repeatedly building the project, parsing the compiler
output for specific errors about ignored return values, and then automatically
inserting a `TEMPORARY_RETURN_IGNORED` macro to suppress the error.

The script will continue this cycle of building and patching until the build
succeeds.

Usage:
    python3 scripts/tests/refactor_nodiscard.py
    python3 scripts/tests/refactor_nodiscard.py --input-file /path/to/build_log.txt
"""

import os
import re
import subprocess
import tempfile

import click


def run_command(command_str, capture_output=True, text=True, check=False, input_data=None):
    """
    Runs a shell command string and returns the result.
    """
    print(f"Running shell command: {command_str}")
    return subprocess.run(
        ['bash', '-c', command_str],
        capture_output=capture_output,
        text=text,
        check=check,
        input=input_data
    )


def process_build_output(build_output):
    """
    Parses build output for `[[nodiscard]]` errors and applies fixes.
    Returns True if fixes were applied, False otherwise.
    """
    # Pattern to extract file path and line number from a grep output error line.
    grep_error_line_pattern = re.compile(r"^\d+:(?:\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} INFO\s+)?([^:]+):(\d+):")

    # Grep for the error
    grep_result = run_command(
        'grep -E -A 1 -n "error: ignor|warning: ignor"',
        input_data=build_output
    )

    if grep_result.returncode != 0 and not grep_result.stdout:
        print("Could not find any 'error: ignor' or 'warning: ignor' lines with grep.")
        return False

    lines_to_fix = {}
    grep_lines = grep_result.stdout.splitlines()
    i = 0
    while i < len(grep_lines):
        line = grep_lines[i]
        i += 1

        error_match = grep_error_line_pattern.match(line)
        if error_match and ("error: ignor" in line or "warning: ignor" in line):
            raw_file_path_from_grep = error_match.group(1)
            line_number = int(error_match.group(2))
            project_root = os.getcwd()
            connectedhomeip_marker = "connectedhomeip/"

            idx = raw_file_path_from_grep.rfind(connectedhomeip_marker)
            if idx != -1:
                relative_path_within_submodule = raw_file_path_from_grep[idx + len(connectedhomeip_marker):]
                file_path = os.path.normpath(os.path.join(project_root, relative_path_within_submodule))
                print(f"Updated {file_path}")
            else:
                if not os.path.isabs(raw_file_path_from_grep):
                    file_path = os.path.normpath(os.path.join(os.path.dirname(
                        __file__), raw_file_path_from_grep.replace("../../", "../", 1)))
                else:
                    file_path = raw_file_path_from_grep

            if i < len(grep_lines) and not grep_lines[i].startswith('--'):
                context_line = grep_lines[i]
                i += 1

                last_pipe_index = context_line.rfind('|')
                if last_pipe_index != -1:
                    expected_content = context_line[last_pipe_index + 1:]
                    lines_to_fix[(file_path, line_number)] = expected_content
                else:
                    print(f"Warning: Could not parse context line for {file_path}:{line_number}: {context_line}")
            else:
                print(f"Warning: No context line found for error at {file_path}:{line_number}")
        elif line.startswith('--'):
            pass

    if not lines_to_fix:
        print("Grep found potential errors, but couldn't parse file and line numbers or context.")
        print("Grep output:")
        print(grep_result.stdout)
        return False

    for (file_path, line_number), expected_content in sorted(lines_to_fix.items(), key=lambda item: item[0][1], reverse=True):
        print(f"Attempting to patch {file_path}:{line_number}")
        try:
            with open(file_path) as f:
                lines = f.readlines()

            if 1 <= line_number <= len(lines):
                original_line = lines[line_number - 1]
                stripped_original_line = original_line.strip()
                stripped_expected_content = expected_content.strip()

                if stripped_original_line == stripped_expected_content:
                    indentation = original_line[:-len(original_line.lstrip())]
                    modified_line = indentation + "TEMPORARY_RETURN_IGNORED " + original_line.lstrip()
                    lines[line_number - 1] = modified_line

                    print(f"  - Modified line {line_number}:")
                    print(f"    - {original_line.strip()}")
                    print(f"    + {modified_line.strip()}")
                else:
                    print(f"  - Skipping line {line_number} in {file_path} due to content mismatch.")
                    print(f"    Expected: '{stripped_expected_content}'")
                    print(f"    Found:    '{stripped_original_line}'")
            else:
                print(f"  - Warning: line number {line_number} is out of bounds for {file_path} (total lines: {len(lines)})")

            with open(file_path, 'w') as f:
                f.writelines(lines)

        except FileNotFoundError:
            print(f"Error: file not found: {file_path}")
        except Exception as e:
            print(f"An error occurred while processing {file_path}: {e}")

    print("Finished applying patches.")
    return True


@click.command()
@click.option('--input-file', type=click.Path(exists=True, dir_okay=False), help='Path to a file containing build output to process instead of running a build.')
def main(input_file):
    """
    Main function to run the build-fix loop or process a single file.
    """
    if input_file:
        print(f"Processing build output from file: {input_file}")
        with open(input_file, encoding='utf-8') as f:
            build_output = f.read()
        process_build_output(build_output)
    else:
        combined_build_command = "source ./scripts/activate.sh && ./gn_build.sh"
        iteration = 1
        while True:
            print(f"\n--- Iteration {iteration} ---")
            iteration += 1

            print("Running activate and build...")
            build_result = run_command(combined_build_command)

            if build_result.returncode == 0:
                print("Build successful!")
                break

            print("Build failed. Dumping output to file for manual checking...")
            build_output = build_result.stdout + build_result.stderr

            with tempfile.NamedTemporaryFile(mode='w', delete=False, encoding='utf-8') as f:
                f.write(build_output)
                build_output_filepath = f.name
            print(f"Build output dumped to: {build_output_filepath}")

            if not process_build_output(build_output):
                print("No applicable errors found to fix in the build output. Aborting.")
                break


if __name__ == "__main__":
    main()
