# Define the file name
import json
import os
from typing import List, Dict, Tuple
from pathlib import Path

import pandas as pd

file_name = "output.txt"
folder_name = "content"

# Define the text content


def write_to_file(text: str, output_filename=f'merged_filtered_.txt', line_number=None):
    from pathlib import Path

    file_name = f"{output_filename}"
    path = Path.cwd() / folder_name / file_name
    path.parent.mkdir(parents=True, exist_ok=True)

    words = text.split()
    if line_number:
        with open(path, "a", encoding="utf-8") as f:
            f.write(f"{line_number}  ")
    with open(path, "a", encoding="utf-8") as f:
        for i in range(0, len(words), 13):
            line = " ".join(words[i:i + 13])
            f.write(line + "\n")
        f.write("\n")


def write_split(output_filename=f'merged_filtered_.txt', should_write=True):
    if should_write:
        from pathlib import Path
        file_name = f"{output_filename}"
        path = Path.cwd() / folder_name / file_name
        path.parent.mkdir(parents=True, exist_ok=True)

        with open(path, "a", encoding="utf-8") as f:
            f.write("******************************************\n")


def write_to_file_with_index(text: str, output_filename=f'merged_filtered_.txt', line_number=None, should_write=True):
    if should_write:
        from pathlib import Path
        file_name = f"{output_filename}"
        path = Path.cwd() / folder_name / file_name
        path.parent.mkdir(parents=True, exist_ok=True)

        words = text.split()
        if line_number:
            with open(path, "a", encoding="utf-8") as f:
                f.write(f"{line_number}  ")
        with open(path, "a", encoding="utf-8") as f:
            for i in range(0, len(words), 13):
                line = " ".join(words[i:i + 13])
                f.write(line + "\n")
            f.write("\n")


def clean(output_filename=f'merged_filtered_.txt'):
    from pathlib import Path
    file_name = f"{output_filename}"
    path = Path.cwd() / folder_name / file_name
    path.parent.mkdir(parents=True, exist_ok=True)

    with open(path, "w", encoding="utf-8"):
        pass


import csv



FILE = "File"
MATCHES = "matches"
EXPECTED_BOUNDARY = "boundary"
SIMILARITIES = "similarities"
POSSIBLE_BREAKS = "possible_breaks"
SOURCE_COUNT = "source_count"
MATCH_PERCENTAGE = "percentage_match"


def save_pair_to_csv(key: str, possible_breaks: List[int],# todo rename
                     expected_boundary: list[int], source_count: int,
                     file_path:str):
    fieldnames = [FILE, EXPECTED_BOUNDARY, POSSIBLE_BREAKS, SOURCE_COUNT,MATCHES, MATCH_PERCENTAGE]

    p = Path(file_path)
    if p.parent:  # only if there's a directory component
        p.parent.mkdir(parents=True, exist_ok=True)

    # os.makedirs(os.path.dirname(file_path), exist_ok=True)

    with open(file_path, "a", newline="", encoding="utf-8") as f:
        writer = csv.DictWriter(f, fieldnames=fieldnames)
        if f.tell() == 0:  # if file is empty, write header
            writer.writeheader()
        matches = match_with_tolerance2(expected_boundary, possible_breaks, tolerance=3)
        writer.writerow({
            FILE: key,
            POSSIBLE_BREAKS: possible_breaks,
            EXPECTED_BOUNDARY: expected_boundary,
            SOURCE_COUNT: source_count,
            MATCHES: matches,
            MATCH_PERCENTAGE: find_percent_in_dict(matches)
        })

def save_result_tocsv(combination:str,result:float):
    file_name = "result.csv"
    p = Path(file_name)
    if p.parent:
        p.parent.mkdir(parents=True, exist_ok=True)

    with open(file_name, "a", newline="", encoding="utf-8") as f:
        writer = csv.DictWriter(f, fieldnames=["combination", "result"])
        if f.tell() == 0:
            writer.writeheader()
        writer.writerow({
            "combination": combination,
            "result": result
        })


def find_percent_in_dict(d: Dict[int, bool]):
    total_keys = len(d)
    if total_keys == 0:
        return 0
    true_count = sum(1 for v in d.values() if v)
    percent = (true_count / total_keys) * 100
    return round(percent)



def match_with_tolerance(expected_boundary: list[int],#todo test
                         possible_breaks: list[int],
                         tolerance: int = 3) -> dict[int, bool]:
    """
    Returns a dict mapping expected index -> True/False depending on whether there
    exists a predicted value within ±tolerance from the expected value.
    """
    matches: dict[int, bool] = {}
    for idx, exp in enumerate(possible_breaks):
        # True if any predicted is within ±tolerance
        is_match = any(abs(exp - p) <= tolerance for p in expected_boundary[:-1])
        matches[idx] = is_match
    if len(matches)<len(expected_boundary[:-1]):
        for i in range(len(matches)-1,len(expected_boundary)-len(matches)):
            matches.update({i+1: False})
    return matches

def match_with_tolerance2(expected_boundary: list[int],#todo test
                         possible_breaks: list[int],
                         tolerance: int = 3) -> dict[int, bool]:
    """
    Returns a dict mapping expected index -> True/False depending on whether there
    exists a predicted value within ±tolerance from the expected value.
    """
    matches = {}
    for index, expected in enumerate(expected_boundary[:-1]):
        matches[index] = False
        for found in possible_breaks:
            if abs(expected - found) <= tolerance:
                matches[index] = True
    return matches


# v = match_with_tolerance(
#     expected_boundary=[12, 25, 38, 50],
#     possible_breaks=[26, 35], )
#
# print(v)
