#!/usr/bin/env python3
"""
Automated tests for the showcase (portfolio) system.

Run with: python test_showcase.py
Or with pytest: pytest test_showcase.py -v
"""

import os
import sys
import tempfile
import unittest
from pathlib import Path

# Create temporary showcase database for testing
TEST_SHOWCASE_DB = tempfile.mktemp(suffix="_showcase.db")

# Patch the SHOWCASE_DB_PATH before importing
import database
database.SHOWCASE_DB_PATH = Path(TEST_SHOWCASE_DB)

from database import (
    init_showcase_db,
    add_showcase_video,
    remove_showcase_video,
    get_showcase_video,
    get_showcase_video_by_task,
    get_showcase_videos,
    get_showcase_videos_count,
    get_random_showcase_videos,
    set_showcase_video_active,
    set_showcase_video_artifacts,
    set_showcase_video_rating,
)


class TestShowcaseDatabase(unittest.TestCase):
    """Tests for showcase database operations."""

    @classmethod
    def setUpClass(cls):
        """Initialize test showcase database."""
        init_showcase_db()

    @classmethod
    def tearDownClass(cls):
        """Clean up test database."""
        if os.path.exists(TEST_SHOWCASE_DB):
            os.unlink(TEST_SHOWCASE_DB)

    def test_init_showcase_db(self):
        """Test showcase database initialization."""
        # Should not raise any errors
        init_showcase_db()
        self.assertTrue(os.path.exists(TEST_SHOWCASE_DB))

    def test_add_showcase_video(self):
        """Test adding a video to showcase."""
        video_id = add_showcase_video(
            video_path="/mnt/video/wb_12345/20260101_000001_test/videos/video.mp4",
            task_id="20260101_000001_test",
            product_id="12345",
            rating=5,
            has_artifacts=False,
            added_by=123
        )
        self.assertIsNotNone(video_id)
        self.assertIsInstance(video_id, int)

    def test_add_duplicate_video(self):
        """Test adding duplicate video returns None."""
        path = "/mnt/video/wb_12345/20260101_000002_dup/videos/video.mp4"
        first_id = add_showcase_video(video_path=path, task_id="20260101_000002_dup")
        second_id = add_showcase_video(video_path=path, task_id="20260101_000002_dup")
        self.assertIsNotNone(first_id)
        self.assertIsNone(second_id)

    def test_get_showcase_video(self):
        """Test getting a showcase video by ID."""
        video_id = add_showcase_video(
            video_path="/mnt/video/wb_12345/20260101_000003_get/videos/video.mp4",
            task_id="20260101_000003_get",
            product_id="12345",
            rating=4
        )
        video = get_showcase_video(video_id)
        self.assertIsNotNone(video)
        self.assertEqual(video["task_id"], "20260101_000003_get")
        self.assertEqual(video["rating"], 4)

    def test_get_showcase_video_nonexistent(self):
        """Test getting non-existent video returns None."""
        video = get_showcase_video(999999)
        self.assertIsNone(video)

    def test_get_showcase_video_by_task(self):
        """Test getting showcase video by task_id."""
        add_showcase_video(
            video_path="/mnt/video/wb_12345/20260101_000004_task/videos/video.mp4",
            task_id="20260101_000004_task",
            product_id="12345"
        )
        video = get_showcase_video_by_task("20260101_000004_task")
        self.assertIsNotNone(video)
        self.assertEqual(video["task_id"], "20260101_000004_task")

    def test_get_showcase_video_by_task_nonexistent(self):
        """Test getting non-existent task returns None."""
        video = get_showcase_video_by_task("nonexistent_task")
        self.assertIsNone(video)

    def test_remove_showcase_video(self):
        """Test removing a video from showcase."""
        video_id = add_showcase_video(
            video_path="/mnt/video/wb_12345/20260101_000005_rm/videos/video.mp4",
            task_id="20260101_000005_rm"
        )
        result = remove_showcase_video(video_id)
        self.assertTrue(result)

        # Verify it's gone
        video = get_showcase_video(video_id)
        self.assertIsNone(video)

    def test_remove_nonexistent_video(self):
        """Test removing non-existent video returns False."""
        result = remove_showcase_video(999999)
        self.assertFalse(result)

    def test_get_showcase_videos(self):
        """Test getting list of showcase videos."""
        # Add a few videos
        add_showcase_video(
            video_path="/mnt/video/wb_12345/20260101_000006_list1/videos/video.mp4",
            task_id="20260101_000006_list1",
            rating=5
        )
        add_showcase_video(
            video_path="/mnt/video/wb_12345/20260101_000007_list2/videos/video.mp4",
            task_id="20260101_000007_list2",
            rating=3
        )

        videos = get_showcase_videos()
        self.assertIsInstance(videos, list)
        self.assertGreater(len(videos), 0)

    def test_get_showcase_videos_with_limit(self):
        """Test getting limited list of showcase videos."""
        videos = get_showcase_videos(limit=2)
        self.assertLessEqual(len(videos), 2)

    def test_get_showcase_videos_excludes_artifacts(self):
        """Test that videos with artifacts are excluded by default."""
        add_showcase_video(
            video_path="/mnt/video/wb_12345/20260101_000008_art/videos/video.mp4",
            task_id="20260101_000008_art",
            has_artifacts=True
        )

        videos = get_showcase_videos(exclude_artifacts=True)
        artifact_tasks = [v["task_id"] for v in videos if v["task_id"] == "20260101_000008_art"]
        self.assertEqual(len(artifact_tasks), 0)

    def test_get_showcase_videos_includes_artifacts(self):
        """Test getting videos including those with artifacts."""
        add_showcase_video(
            video_path="/mnt/video/wb_12345/20260101_000009_art2/videos/video.mp4",
            task_id="20260101_000009_art2",
            has_artifacts=True
        )

        videos = get_showcase_videos(exclude_artifacts=False)
        artifact_tasks = [v["task_id"] for v in videos if v["task_id"] == "20260101_000009_art2"]
        self.assertEqual(len(artifact_tasks), 1)

    def test_get_showcase_videos_count(self):
        """Test getting count of showcase videos."""
        count = get_showcase_videos_count()
        self.assertIsInstance(count, int)
        self.assertGreaterEqual(count, 0)

    def test_get_random_showcase_videos(self):
        """Test getting random showcase videos."""
        # Add several videos first
        for i in range(10, 15):
            add_showcase_video(
                video_path=f"/mnt/video/wb_12345/20260101_0000{i}_rand/videos/video.mp4",
                task_id=f"20260101_0000{i}_rand"
            )

        videos = get_random_showcase_videos(count=3)
        self.assertLessEqual(len(videos), 3)

    def test_get_random_excludes_artifacts(self):
        """Test random selection excludes artifacts by default."""
        add_showcase_video(
            video_path="/mnt/video/wb_12345/20260101_000016_randart/videos/video.mp4",
            task_id="20260101_000016_randart",
            has_artifacts=True
        )

        # Run multiple times to check
        for _ in range(5):
            videos = get_random_showcase_videos(count=100, exclude_artifacts=True)
            artifact_tasks = [v for v in videos if v["task_id"] == "20260101_000016_randart"]
            self.assertEqual(len(artifact_tasks), 0)

    def test_set_showcase_video_active(self):
        """Test setting video active status."""
        video_id = add_showcase_video(
            video_path="/mnt/video/wb_12345/20260101_000017_active/videos/video.mp4",
            task_id="20260101_000017_active"
        )

        # Deactivate
        result = set_showcase_video_active(video_id, False)
        self.assertTrue(result)

        video = get_showcase_video(video_id)
        self.assertEqual(video["is_active"], 0)

        # Reactivate
        set_showcase_video_active(video_id, True)
        video = get_showcase_video(video_id)
        self.assertEqual(video["is_active"], 1)

    def test_set_showcase_video_artifacts(self):
        """Test setting video artifacts flag."""
        video_id = add_showcase_video(
            video_path="/mnt/video/wb_12345/20260101_000018_artflag/videos/video.mp4",
            task_id="20260101_000018_artflag"
        )

        # Set artifacts flag
        result = set_showcase_video_artifacts(video_id, True)
        self.assertTrue(result)

        video = get_showcase_video(video_id)
        self.assertEqual(video["has_artifacts"], 1)

        # Clear artifacts flag
        set_showcase_video_artifacts(video_id, False)
        video = get_showcase_video(video_id)
        self.assertEqual(video["has_artifacts"], 0)

    def test_set_showcase_video_rating(self):
        """Test setting video rating."""
        video_id = add_showcase_video(
            video_path="/mnt/video/wb_12345/20260101_000019_rating/videos/video.mp4",
            task_id="20260101_000019_rating"
        )

        result = set_showcase_video_rating(video_id, 5)
        self.assertTrue(result)

        video = get_showcase_video(video_id)
        self.assertEqual(video["rating"], 5)

    def test_set_showcase_video_rating_clamps(self):
        """Test rating is clamped to 0-5 range."""
        video_id = add_showcase_video(
            video_path="/mnt/video/wb_12345/20260101_000020_clamp/videos/video.mp4",
            task_id="20260101_000020_clamp"
        )

        # Try setting rating > 5
        set_showcase_video_rating(video_id, 10)
        video = get_showcase_video(video_id)
        self.assertEqual(video["rating"], 5)

        # Try setting rating < 0
        set_showcase_video_rating(video_id, -5)
        video = get_showcase_video(video_id)
        self.assertEqual(video["rating"], 0)


class TestImportParsing(unittest.TestCase):
    """Tests for import script parsing logic."""

    def test_parse_simple_path(self):
        """Test parsing simple video path."""
        line = "/mnt/video/wb_14797921/20260121_150943_gnqe/videos/video.mp4"

        # Simulate parsing
        path = line.split(" -- ")[0].strip()
        note = line.split(" -- ")[1].strip() if " -- " in line else None

        self.assertEqual(path, "/mnt/video/wb_14797921/20260121_150943_gnqe/videos/video.mp4")
        self.assertIsNone(note)

    def test_parse_path_with_note(self):
        """Test parsing path with note."""
        line = "/mnt/video/wb_14797921/20260121_150943_gnqe/videos/video.mp4 -- отлично"

        path = line.split(" -- ")[0].strip()
        note = line.split(" -- ")[1].strip() if " -- " in line else None

        self.assertEqual(path, "/mnt/video/wb_14797921/20260121_150943_gnqe/videos/video.mp4")
        self.assertEqual(note, "отлично")

    def test_parse_path_with_artifacts(self):
        """Test parsing path marked as having artifacts."""
        line = "/mnt/video/wb_10733325/20260119_012331_lysw/videos/video.mp4 -- артефакты"

        path = line.split(" -- ")[0].strip()
        note = line.split(" -- ")[1].strip() if " -- " in line else None
        has_artifacts = "артефакты" in (note or "")
        rating = 5 if "отлично" in (note or "") else 0

        self.assertTrue(has_artifacts)
        self.assertEqual(rating, 0)

    def test_parse_path_excellent(self):
        """Test parsing path marked as excellent."""
        line = "/mnt/video/wb_204198511/20260118_222559_ztc9/videos/video.mp4 -- отлично"

        note = line.split(" -- ")[1].strip() if " -- " in line else None
        has_artifacts = "артефакты" in (note or "")
        rating = 5 if "отлично" in (note or "") else 0

        self.assertFalse(has_artifacts)
        self.assertEqual(rating, 5)

    def test_extract_ids_from_path(self):
        """Test extracting product_id and task_id from path."""
        path = "/mnt/video/wb_14797921/20260121_150943_gnqe/videos/video.mp4"

        # Extract using path parts
        parts = path.split("/")
        # parts: ['', 'mnt', 'video', 'wb_14797921', '20260121_150943_gnqe', 'videos', 'video.mp4']
        product_dir = parts[3]  # 'wb_14797921'
        task_id = parts[4]  # '20260121_150943_gnqe'

        product_id = product_dir.replace("wb_", "")

        self.assertEqual(product_id, "14797921")
        self.assertEqual(task_id, "20260121_150943_gnqe")


def run_tests():
    """Run all tests and return results."""
    loader = unittest.TestLoader()
    suite = unittest.TestSuite()

    # Add test classes
    suite.addTests(loader.loadTestsFromTestCase(TestShowcaseDatabase))
    suite.addTests(loader.loadTestsFromTestCase(TestImportParsing))

    # Run tests
    runner = unittest.TextTestRunner(verbosity=2)
    result = runner.run(suite)

    return result


if __name__ == "__main__":
    result = run_tests()

    # Print summary
    print("\n" + "=" * 60)
    print(f"Tests run: {result.testsRun}")
    print(f"Failures: {len(result.failures)}")
    print(f"Errors: {len(result.errors)}")

    if result.wasSuccessful():
        print("\n✅ All tests passed!")
        sys.exit(0)
    else:
        print("\n❌ Some tests failed!")
        sys.exit(1)
