"""Tests for models."""

from __future__ import annotations

from pathlib import Path

from file_organizer.models import (
    EXTENSION_CATEGORIES,
    FileAction,
    FileCategory,
    OrganizeMode,
    OrganizePlan,
    UndoLog,
)


class TestFileCategory:
    def test_known_extensions(self) -> None:
        assert EXTENSION_CATEGORIES[".jpg"] == FileCategory.IMAGES
        assert EXTENSION_CATEGORIES[".pdf"] == FileCategory.DOCUMENTS
        assert EXTENSION_CATEGORIES[".mp4"] == FileCategory.VIDEOS
        assert EXTENSION_CATEGORIES[".mp3"] == FileCategory.AUDIO
        assert EXTENSION_CATEGORIES[".zip"] == FileCategory.ARCHIVES
        assert EXTENSION_CATEGORIES[".py"] == FileCategory.CODE
        assert EXTENSION_CATEGORIES[".exe"] == FileCategory.EXECUTABLES

    def test_unknown_extension(self) -> None:
        assert EXTENSION_CATEGORIES.get(".xyz", FileCategory.OTHER) == FileCategory.OTHER


class TestFileAction:
    def test_creation(self) -> None:
        action = FileAction(
            source=Path("/tmp/src.txt"),
            destination=Path("/tmp/dst.txt"),
            size_bytes=1024,
        )
        assert action.source == Path("/tmp/src.txt")
        assert action.destination == Path("/tmp/dst.txt")
        assert action.size_bytes == 1024

    def test_serialization(self) -> None:
        action = FileAction(
            source=Path("/tmp/src.txt"),
            destination=Path("/tmp/dst.txt"),
            size_bytes=1024,
            timestamp=1234567890.0,
        )
        data = action.to_dict()
        restored = FileAction.from_dict(data)
        assert restored.source == action.source
        assert restored.destination == action.destination
        assert restored.size_bytes == action.size_bytes
        assert restored.timestamp == action.timestamp


class TestOrganizePlan:
    def test_creation(self) -> None:
        plan = OrganizePlan(mode=OrganizeMode.TYPE, source_dir=Path("/tmp"))
        assert plan.mode == OrganizeMode.TYPE
        assert plan.total_files() == 0
        assert plan.total_size() == 0

    def test_add_action(self) -> None:
        plan = OrganizePlan(mode=OrganizeMode.TYPE, source_dir=Path("/tmp"))
        plan.add_action(Path("/tmp/a.txt"), Path("/tmp/Images/a.txt"), 100)
        plan.add_action(Path("/tmp/b.txt"), Path("/tmp/Images/b.txt"), 200)
        assert plan.total_files() == 2
        assert plan.total_size() == 300

    def test_serialization(self) -> None:
        plan = OrganizePlan(mode=OrganizeMode.DATE, source_dir=Path("/tmp"))
        plan.add_action(Path("/tmp/a.txt"), Path("/tmp/2024-01/a.txt"), 100)
        data = plan.to_dict()
        restored = OrganizePlan.from_dict(data)
        assert restored.mode == OrganizeMode.DATE
        assert restored.total_files() == 1
        assert restored.actions[0].size_bytes == 100


class TestUndoLog:
    def test_creation(self) -> None:
        plan = OrganizePlan(mode=OrganizeMode.TYPE, source_dir=Path("/tmp"))
        log = UndoLog(plan=plan)
        assert log.success is True
        assert log.error is None

    def test_json_serialization(self) -> None:
        plan = OrganizePlan(mode=OrganizeMode.SIZE, source_dir=Path("/tmp"))
        plan.add_action(Path("/tmp/a.txt"), Path("/tmp/Large/a.txt"), 100)
        log = UndoLog(plan=plan, success=True)
        json_str = log.to_json()
        restored = UndoLog.from_json(json_str)
        assert restored.plan.mode == OrganizeMode.SIZE
        assert restored.success is True
        assert restored.plan.total_files() == 1
