"""Tests for CHECK_FILE upload deduplication helpers."""
import os
import tempfile
import unittest
from datetime import datetime, timedelta

from app.utils.file_upload_check import (
    compare_incoming_vs_existing,
    escape_like_pattern,
    pick_best_candidate,
    resolve_upload_action,
    strip_leading_timestamp,
)


def _row(file_id: str, original: str, upload_date: str, file_path: str = ""):
    return (
        file_id,
        original,
        original,
        "pdf",
        file_path,
        "FolderA",
        original,
        upload_date,
        0,
        "",
        "",
        "",
        "",
        "agent1",
    )


class TestStripLeadingTimestamp(unittest.TestCase):
    def test_compact_datetime(self):
        rest, ts = strip_leading_timestamp("20250525143000 Report Q1.pdf")
        self.assertEqual(rest, "Report Q1.pdf")
        self.assertEqual(ts, datetime(2025, 5, 25, 14, 30, 0))

    def test_compact_date_only(self):
        rest, ts = strip_leading_timestamp("20250525 Report.pdf")
        self.assertEqual(rest, "Report.pdf")
        self.assertEqual(ts, datetime(2025, 5, 25))

    def test_iso_datetime(self):
        rest, ts = strip_leading_timestamp("2025-05-25 14:30:00 Report.pdf")
        self.assertEqual(rest, "Report.pdf")
        self.assertIsNotNone(ts)

    def test_no_strip_without_timestamp(self):
        rest, ts = strip_leading_timestamp("v1 Report.pdf")
        self.assertEqual(rest, "v1 Report.pdf")
        self.assertIsNone(ts)

    def test_no_space_unchanged(self):
        rest, ts = strip_leading_timestamp("Report.pdf")
        self.assertEqual(rest, "Report.pdf")
        self.assertIsNone(ts)

    def test_unix_underscore_prefix_training_format(self):
        """Format from Document Training Center: 01776717100_name.pdf"""
        name = "01776717100_2026-27 Avalon Transportation COI Packet.pdf"
        rest, ts = strip_leading_timestamp(name)
        self.assertEqual(rest, "2026-27 Avalon Transportation COI Packet.pdf")
        self.assertIsNotNone(ts)
        self.assertEqual(int(ts.timestamp()), 1776717100)

    def test_unix_underscore_dedup_search_name(self):
        older = "01776717057_2026-27 Avalon Transportation COI Packet.pdf"
        newer = "01776717100_2026-27 Avalon Transportation COI Packet.pdf"
        _, _ = strip_leading_timestamp(older)
        rest_new, ts_new = strip_leading_timestamp(newer)
        self.assertEqual(rest_new, "2026-27 Avalon Transportation COI Packet.pdf")
        self.assertGreater(ts_new.timestamp(), 1776717057)

    def test_second_upload_replaces_first_same_packet(self):
        """User scenario: two COI packets differing only by unix prefix."""
        first = _row("id_old", "01776717057_2026-27 Avalon Transportation COI Packet.pdf", "2025-01-01")
        rest, ts_new = strip_leading_timestamp(
            "01776717100_2026-27 Avalon Transportation COI Packet.pdf"
        )
        action, fid, reason = resolve_upload_action(
            rest,
            "01776717100_2026-27 Avalon Transportation COI Packet.pdf",
            ts_new,
            None,
            [first],
        )
        self.assertEqual(action, "replace")
        self.assertEqual(fid, "id_old")
        self.assertEqual(reason, "check_file_replaced")

    def test_older_second_upload_skipped(self):
        first = _row("id_new", "01776717100_2026-27 Avalon Transportation COI Packet.pdf", "2025-01-01")
        rest, ts_old = strip_leading_timestamp(
            "01776717057_2026-27 Avalon Transportation COI Packet.pdf"
        )
        action, _, reason = resolve_upload_action(
            rest,
            "01776717057_2026-27 Avalon Transportation COI Packet.pdf",
            ts_old,
            None,
            [first],
        )
        self.assertEqual(action, "skip")
        self.assertEqual(reason, "check_file_older")


class TestResolveUploadAction(unittest.TestCase):
    def test_no_candidates_proceeds(self):
        action, fid, reason = resolve_upload_action(
            "report.pdf", "20250526 report.pdf", datetime(2025, 5, 26), None, []
        )
        self.assertEqual(action, "proceed")
        self.assertIsNone(fid)

    def test_older_incoming_skips(self):
        older = _row("old1", "20250526 Report.pdf", "2025-05-26T10:00:00")
        action, fid, reason = resolve_upload_action(
            "report.pdf",
            "20250520 Report.pdf",
            datetime(2025, 5, 20),
            None,
            [older],
        )
        self.assertEqual(action, "skip")
        self.assertEqual(reason, "check_file_older")

    def test_newer_incoming_replaces(self):
        older = _row("old1", "20250520 Report.pdf", "2025-05-20T10:00:00")
        action, fid, reason = resolve_upload_action(
            "report.pdf",
            "20250526 Report.pdf",
            datetime(2025, 5, 26),
            None,
            [older],
        )
        self.assertEqual(action, "replace")
        self.assertEqual(fid, "old1")
        self.assertEqual(reason, "check_file_replaced")

    def test_mtime_newer_replaces(self):
        with tempfile.TemporaryDirectory() as tmp:
            existing_path = os.path.join(tmp, "existing.pdf")
            with open(existing_path, "wb") as f:
                f.write(b"x")
            old_time = datetime.now() - timedelta(days=2)
            os.utime(existing_path, (old_time.timestamp(), old_time.timestamp()))

            older = _row("old1", "Report.pdf", "2020-01-01T00:00:00", existing_path)
            new_mtime = datetime.now().timestamp()
            cmp = compare_incoming_vs_existing(
                "Report.pdf", None, new_mtime, older
            )
            self.assertEqual(cmp, 1)

    def test_pick_longest_filename_match(self):
        c1 = _row("a", "Report.pdf", "2025-01-01")
        c2 = _row("b", "20250520 Full Report Q1.pdf", "2025-01-02")
        best = pick_best_candidate([c1, c2], "report q1")
        self.assertEqual(best[0], "b")


class TestEscapeLike(unittest.TestCase):
    def test_escape_percent(self):
        self.assertEqual(escape_like_pattern("100%"), "100!%")


if __name__ == "__main__":
    unittest.main()
