"""Tests for the indexing pipeline."""

import argparse
from pathlib import Path

import pytest

from takeseek.db import Database
from takeseek.index import run_pipeline, _auto_tags, index_file, IndexFileResult


class TestAutoTags:
    def test_4k_tag(self):
        class Meta:
            height = 2160
            codec = "h265"
        tags = _auto_tags(Meta(), Path("/videos/nature/clip.mp4"))
        assert "4k" in tags
        assert "h265" in tags
        assert "nature" in tags

    def test_1080p_tag(self):
        class Meta:
            height = 1080
            codec = "h264"
        tags = _auto_tags(Meta(), Path("/videos/urban/clip.mp4"))
        assert "1080p" in tags

    def test_720p_tag(self):
        class Meta:
            height = 720
            codec = None
        tags = _auto_tags(Meta(), Path("/tmp/clip.mp4"))
        assert "720p" in tags

    def test_no_height(self):
        class Meta:
            height = None
            codec = None
        tags = _auto_tags(Meta(), Path("/clip.mp4"))
        # Should not crash, just return fewer tags
        assert isinstance(tags, list)


class TestIndexFile:
    """Tests for the extracted index_file() function."""

    def test_metadata_only(self, test_video, tmp_path):
        db_path = tmp_path / "index_file_test.db"
        db = Database(db_path)

        result = index_file(db, test_video, do_transcribe=False)

        assert isinstance(result, IndexFileResult)
        assert result.status == "indexed"
        assert result.index_status == "metadata"
        assert result.clip_id is not None
        assert result.error is None
        assert result.transcript_segments == 0
        assert result.frame_descriptions == 0

        # Verify DB state
        clip = db.get_clip_by_id(result.clip_id)
        assert clip is not None
        assert clip["index_status"] == "metadata"
        assert clip["width"] == 320
        assert clip["height"] == 240
        db.close()

    def test_skip_if_done(self, test_video, tmp_path):
        db_path = tmp_path / "index_file_skip.db"
        db = Database(db_path)

        # First run
        result1 = index_file(db, test_video, do_transcribe=False)
        assert result1.status == "indexed"

        # Second run with skip_if_done
        result2 = index_file(db, test_video, do_transcribe=False, skip_if_done=True)
        assert result2.status == "skipped"
        assert result2.clip_id == result1.clip_id
        db.close()

    def test_nonexistent_file(self, tmp_path):
        db_path = tmp_path / "index_file_noexist.db"
        db = Database(db_path)

        result = index_file(db, tmp_path / "nonexistent.mp4")

        assert result.status == "error"
        assert result.clip_id is None
        assert result.error is not None
        db.close()

    def test_progress_callback(self, test_video, tmp_path):
        db_path = tmp_path / "index_file_progress.db"
        db = Database(db_path)

        messages = []
        result = index_file(
            db, test_video,
            do_transcribe=False,
            on_progress=lambda msg: messages.append(msg),
        )

        assert result.status == "indexed"
        assert len(messages) > 0
        assert any("metadata" in m.lower() for m in messages)
        db.close()


class TestPipeline:
    def test_metadata_only(self, test_video, tmp_path):
        db_path = tmp_path / "pipeline_test.db"
        args = argparse.Namespace(
            paths=[str(test_video)],
            db=str(db_path),
            metadata_only=True,
            new_only=False,
            whisper_model="base",
            verbose=False,
        )

        result = run_pipeline(args)
        assert result == 0

        db = Database(db_path)
        clips = db.list_clips()
        assert len(clips) == 1
        assert clips[0]["index_status"] == "metadata"
        assert clips[0]["width"] == 320
        assert clips[0]["height"] == 240

        tags = db.get_tags(clips[0]["id"])
        assert "240p" not in tags  # 240 is below 480p threshold
        db.close()

    def test_new_only_skips(self, test_video, tmp_path):
        db_path = tmp_path / "pipeline_test.db"
        args = argparse.Namespace(
            paths=[str(test_video)],
            db=str(db_path),
            metadata_only=True,
            new_only=False,
            whisper_model="base",
            verbose=False,
        )

        # First run
        run_pipeline(args)

        # Second run with --new-only
        args.new_only = True
        result = run_pipeline(args)
        assert result == 0

    def test_nonexistent_path(self, tmp_path):
        db_path = tmp_path / "pipeline_test.db"
        args = argparse.Namespace(
            paths=[str(tmp_path / "nonexistent_video.mp4")],
            db=str(db_path),
            metadata_only=True,
            new_only=False,
            whisper_model="base",
            verbose=False,
        )

        result = run_pipeline(args)
        assert result == 1  # No files found
