import re
import json

def temporal_iou(A, B):
    max0 = max((A[0]), (B[0]))
    min0 = min((A[0]), (B[0]))
    max1 = max((A[1]), (B[1]))
    min1 = min((A[1]), (B[1]))
    _iou=max(min1 - max0, 0) / (max1 - min0)
    return max(0,_iou)

def relaxed_temporal_iou(pred, gt, relax_ratio=0.1):
    """
    pred: tuple(float, float), predicted start and end (already normalized)
    gt: tuple(float, float), ground truth start and end (assumed normalized)
    relax_ratio: float, amount to relax the GT boundaries (e.g., 0.1 -> 10%)
    """

    gt_start, gt_end = gt
    gt_duration = gt_end - gt_start

    relaxed_start = gt_start - relax_ratio * gt_duration
    relaxed_end = gt_end + relax_ratio * gt_duration

    # Ensure the relaxed range stays within [0, 1] or valid timeline
    relaxed_start = max(0.0, relaxed_start)
    relaxed_end = min(1.0, relaxed_end)

    # Compute tIoU with relaxed GT
    inter = max(0.0, min(pred[1], relaxed_end) - max(pred[0], relaxed_start))
    union = max(pred[1], relaxed_end) - min(pred[0], relaxed_start)
    iou = inter / union if union > 0 else 0.0

    return iou

def tvg_format_reward(predict_str: str) -> float:
    pattern = r'<think>.*?</think>\s*<answer>\s*{\s*"start_time"\s*:\s*"([\d.]+)"\s*,\s*"end_time"\s*:\s*"([\d.]+)"\s*}\s*</answer>'
    match = re.fullmatch(pattern, predict_str, re.DOTALL)
    return 1.0 if match else 0.0


def tvg_accuracy_reward(predict_str: str, ground_truth: list, video_length: float) -> float:
    try:
        content_answer_match = re.search(r"<answer>(.*?)</answer>", predict_str, re.DOTALL)
        content_answer = content_answer_match.group(1).strip()
        answer_data = json.loads(content_answer)

        answer_timestamp = [
            float(answer_data["start_time"]) / video_length, 
            float(answer_data["end_time"]) / video_length
        ]
        # reward = temporal_iou(answer_timestamp, ground_truth)
        reward = relaxed_temporal_iou(answer_timestamp, ground_truth)

        # print(f"[pred]: {answer_timestamp} [gt]: {ground_truth} [reward]: {reward}")
        # print(f"gt: {ground_truth}, pred: {answer_timestamp}")

        # reward = 1.0 if reward >= 0.5 else 0
        return reward
    except Exception as e:
        # print(e)
        pass  # Continue to next verification method if this fails

    return 0.0


def tvg_compute_score(predict_str: str, ground_truth: list, video_length: float) -> float:
    # print(predict_str, ground_truth, video_length)
    acc_reward = tvg_accuracy_reward(predict_str, ground_truth, video_length)
    format_reward = tvg_format_reward(predict_str)
    # print(f"acc: {acc_reward}, format: {format_reward}")
    reward = 0.5 * acc_reward + 0.5 * format_reward
    # reward /= 2
    return reward

def tvg_compute_score_confident(predict_str: str, ground_truth: list, video_length: float, confidence: float) -> float:
    acc_reward = tvg_accuracy_reward(predict_str, ground_truth, video_length)
    format_reward = tvg_format_reward(predict_str)
    # print(f"acc: {acc_reward}, format: {format_reward}")
    reward = 0.5 * acc_reward * confidence + 0.5 * format_reward
    # reward /= 2
    return reward
