"""Tests para vault_dedupe_report."""

from __future__ import annotations

import os
import sqlite3
import sys
from pathlib import Path

import pytest

sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
from vault_dedupe_report import vault_dedupe_report


# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------

def _make_db(tmp_path: Path, rows: list[tuple]) -> Path:
    """Crea vault_index.db con la tabla files y las filas dadas.

    rows: lista de (rel_path, size, sha256)
    """
    db_path = tmp_path / "vault_index.db"
    conn = sqlite3.connect(str(db_path))
    conn.execute(
        """
        CREATE TABLE files (
            rel_path  TEXT PRIMARY KEY,
            size      INTEGER,
            mtime     REAL,
            sha256    TEXT,
            mime      TEXT,
            ext       TEXT,
            bucket    TEXT,
            sub_bucket TEXT,
            indexed_at REAL
        );
        """
    )
    conn.executemany(
        "INSERT INTO files (rel_path, size, sha256) VALUES (?, ?, ?);",
        rows,
    )
    conn.commit()
    conn.close()
    return db_path


# ---------------------------------------------------------------------------
# Tests
# ---------------------------------------------------------------------------

def test_no_duplicates(tmp_path):
    """test_no_duplicates — 3 archivos con sha256 distintos -> groups=[]."""
    _make_db(tmp_path, [
        ("a/file1.txt", 100, "aaa111"),
        ("a/file2.txt", 200, "bbb222"),
        ("a/file3.txt", 300, "ccc333"),
    ])
    result = vault_dedupe_report(str(tmp_path), db_path=str(tmp_path / "vault_index.db"))

    assert result["groups"] == []
    assert result["total_groups"] == 0
    assert result["total_duplicates"] == 0
    assert result["total_reclaimable_bytes"] == 0
    assert result["scanned_files"] == 3
    assert result["vault_path"] == str(tmp_path)


def test_basic_duplicates(tmp_path):
    """test_basic_duplicates — 2 archivos mismo sha256 -> 1 group, count=2, reclaimable=size."""
    _make_db(tmp_path, [
        ("data/orig.jpg", 500, "deadbeef"),
        ("backup/orig.jpg", 500, "deadbeef"),
    ])
    result = vault_dedupe_report(str(tmp_path), db_path=str(tmp_path / "vault_index.db"))

    assert result["total_groups"] == 1
    assert result["total_duplicates"] == 1
    assert result["total_reclaimable_bytes"] == 500

    g = result["groups"][0]
    assert g["sha256"] == "deadbeef"
    assert g["size"] == 500
    assert g["count"] == 2
    assert g["reclaimable_bytes"] == 500
    assert sorted(g["files"]) == ["backup/orig.jpg", "data/orig.jpg"]


def test_three_in_group(tmp_path):
    """test_three_in_group — 3 archivos mismo sha256 -> count=3, reclaimable=size*2."""
    size = 1000
    _make_db(tmp_path, [
        ("a/f1.bin", size, "cafebabe"),
        ("b/f2.bin", size, "cafebabe"),
        ("c/f3.bin", size, "cafebabe"),
    ])
    result = vault_dedupe_report(str(tmp_path), db_path=str(tmp_path / "vault_index.db"))

    assert result["total_groups"] == 1
    assert result["total_duplicates"] == 2
    assert result["total_reclaimable_bytes"] == size * 2

    g = result["groups"][0]
    assert g["count"] == 3
    assert g["reclaimable_bytes"] == size * 2
    assert g["files"] == sorted(["a/f1.bin", "b/f2.bin", "c/f3.bin"])


def test_min_size_filter(tmp_path):
    """test_min_size_filter — duplicados de tamano 50, min_size=100 -> groups=[]."""
    _make_db(tmp_path, [
        ("x/small1.txt", 50, "tiny123"),
        ("y/small2.txt", 50, "tiny123"),
    ])
    result = vault_dedupe_report(
        str(tmp_path),
        min_size=100,
        db_path=str(tmp_path / "vault_index.db"),
    )

    assert result["groups"] == []
    assert result["total_groups"] == 0
    assert result["total_reclaimable_bytes"] == 0
    assert result["scanned_files"] == 0


def test_multiple_groups_ordered(tmp_path):
    """test_multiple_groups_ordered — 2 grupos con distinto ahorro -> orden DESC."""
    # grupo A: 2 copias de 200 bytes -> reclaimable=200
    # grupo B: 3 copias de 500 bytes -> reclaimable=1000
    # el grupo B debe salir primero
    _make_db(tmp_path, [
        ("p/a1.dat", 200, "groupA"),
        ("q/a2.dat", 200, "groupA"),
        ("r/b1.dat", 500, "groupB"),
        ("s/b2.dat", 500, "groupB"),
        ("t/b3.dat", 500, "groupB"),
        ("u/uniq.dat", 999, "unique1"),
    ])
    result = vault_dedupe_report(str(tmp_path), db_path=str(tmp_path / "vault_index.db"))

    assert result["total_groups"] == 2
    assert result["total_duplicates"] == 3          # (2-1) + (3-1)
    assert result["total_reclaimable_bytes"] == 1200  # 200 + 1000
    assert result["scanned_files"] == 6              # 6 filas con sha256 != '' (incluye el unico)

    # Primer grupo debe ser el de mayor ahorro (B: 1000)
    assert result["groups"][0]["sha256"] == "groupB"
    assert result["groups"][0]["reclaimable_bytes"] == 1000
    assert result["groups"][1]["sha256"] == "groupA"
    assert result["groups"][1]["reclaimable_bytes"] == 200
