@testable import APIClient
import Foundation
import Testing

struct HookDisplayLogicTests {
    // Helper to create hooks with specific status and source
    private func makeHook(
        id: String = UUID().uuidString,
        status: Hook.Status = .complete,
        creationSource: Hook.CreationSource = .userUpload
    ) -> Hook {
        Hook(
            id: id,
            endClipTimestamp: 30.0,
            originalClipId: "clip123",
            startClipTimestamp: 0.0,
            status: status,
            title: "Test Hook",
            userId: 123,
            videoDuration: 30.0,
            creationSource: creationSource
        )
    }

    // MARK: - isPublicDisplayable Tests

    @Test("isPublicDisplayable returns true only for passed moderation with user upload")
    func testIsPublicDisplayableTrue() {
        let hook = makeHook(
            status: .renderedPassedModeration,
            creationSource: .userUpload
        )
        #expect(hook.isPublicDisplayable == true)
    }

    @Test("isPublicDisplayable returns false when passed moderation but not user upload")
    func testIsPublicDisplayableFalseWrongSource() {
        let hook = makeHook(
            status: .renderedPassedModeration,
            creationSource: .backfillVideoCover
        )
        #expect(hook.isPublicDisplayable == false)
    }

    @Test("isPublicDisplayable returns false when user upload but not passed moderation")
    func testIsPublicDisplayableFalseWrongStatus() {
        let statusesToTest: [Hook.Status] = [
            .submitted,
            .queued,
            .streaming,
            .complete,
            .error,
            .undefined,
            .failed,
            .renderedFailedModeration,
            .processing,
            .rendering,
        ]

        for status in statusesToTest {
            let hook = makeHook(
                status: status,
                creationSource: .userUpload
            )
            #expect(hook.isPublicDisplayable == false)
        }
    }

    @Test("isPublicDisplayable returns false for failed moderation with user upload")
    func testIsPublicDisplayableFalseFailedModeration() {
        let hook = makeHook(
            status: .renderedFailedModeration,
            creationSource: .userUpload
        )
        #expect(hook.isPublicDisplayable == false)
    }

    // MARK: - isUserDisplayable Tests

    @Test("isUserDisplayable returns true for user uploads regardless of status")
    func testIsUserDisplayableTrue() {
        let statusesToTest: [Hook.Status] = [
            .submitted,
            .queued,
            .streaming,
            .complete,
            .error,
            .undefined,
            .failed,
            .renderedPassedModeration,
            .renderedFailedModeration,
            .processing,
            .rendering,
        ]

        for status in statusesToTest {
            let hook = makeHook(
                status: status,
                creationSource: .userUpload
            )
            #expect(hook.isUserDisplayable == true)
        }
    }

    @Test("isUserDisplayable returns false for backfill video cover")
    func testIsUserDisplayableFalse() {
        let statusesToTest: [Hook.Status] = [
            .complete,
            .renderedPassedModeration,
            .renderedFailedModeration,
        ]

        for status in statusesToTest {
            let hook = makeHook(
                status: status,
                creationSource: .backfillVideoCover
            )
            #expect(hook.isUserDisplayable == false)
        }
    }

    // MARK: - Array Extension Tests

    @Test("publicDisplayableHooks filters correctly")
    func testPublicDisplayableHooksFilter() {
        let hooks = [
            // Should be included (passed moderation + user upload)
            makeHook(id: "1", status: .renderedPassedModeration, creationSource: .userUpload),
            makeHook(id: "2", status: .renderedPassedModeration, creationSource: .userUpload),

            // Should be excluded (wrong status)
            makeHook(id: "3", status: .complete, creationSource: .userUpload),
            makeHook(id: "4", status: .renderedFailedModeration, creationSource: .userUpload),
            makeHook(id: "5", status: .rendering, creationSource: .userUpload),

            // Should be excluded (wrong source)
            makeHook(id: "6", status: .renderedPassedModeration, creationSource: .backfillVideoCover),

            // Should be excluded (both wrong)
            makeHook(id: "7", status: .complete, creationSource: .backfillVideoCover),
        ]

        let filtered = hooks.publicDisplayableHooks

        #expect(filtered.count == 2)
        #expect(filtered.map { $0.id }.sorted() == ["1", "2"])
    }

    @Test("userDisplayableHooks filters correctly")
    func testUserDisplayableHooksFilter() {
        let hooks = [
            // Should be included (user upload with any status)
            makeHook(id: "1", status: .renderedPassedModeration, creationSource: .userUpload),
            makeHook(id: "2", status: .renderedFailedModeration, creationSource: .userUpload),
            makeHook(id: "3", status: .complete, creationSource: .userUpload),
            makeHook(id: "4", status: .rendering, creationSource: .userUpload),
            makeHook(id: "5", status: .error, creationSource: .userUpload),

            // Should be excluded (backfill)
            makeHook(id: "6", status: .renderedPassedModeration, creationSource: .backfillVideoCover),
            makeHook(id: "7", status: .complete, creationSource: .backfillVideoCover),
        ]

        let filtered = hooks.userDisplayableHooks

        #expect(filtered.count == 5)
        #expect(filtered.map { $0.id }.sorted() == ["1", "2", "3", "4", "5"])
    }

    @Test("empty array returns empty for both filters")
    func testEmptyArrayFilters() {
        let hooks: [Hook] = []

        #expect(hooks.publicDisplayableHooks.isEmpty)
        #expect(hooks.userDisplayableHooks.isEmpty)
    }

    @Test("array with no displayable hooks returns empty")
    func testNoDisplayableHooks() {
        let hooks = [
            makeHook(status: .complete, creationSource: .backfillVideoCover),
            makeHook(status: .rendering, creationSource: .backfillVideoCover),
        ]

        #expect(hooks.publicDisplayableHooks.isEmpty)
        #expect(hooks.userDisplayableHooks.isEmpty)
    }
}
