import SwiftLintCore
import TestHelpers
import Testing

@testable import SwiftLintBuiltInRules

@Suite(.rulesRegistered)
struct FileTypesOrderRuleTests {
    @Test
    func fileTypesOrderReversedOrder() { // swiftlint:disable:this function_body_length
        // Test with reversed `order` entries
        let nonTriggeringExamples = #examples([
            FileTypesOrderRuleExamples.defaultOrderParts.reversed().joined(separator: "\n\n").asExample()
        ])
        let triggeringExamples = #examples([
            """
            // Supporting Types
            ↓protocol TestViewControllerDelegate {
                func didPressTrackedButton()
            }

            class TestViewController: UIViewController {}
            """,
            """
            ↓class TestViewController: UIViewController {}

            // Extensions
            extension TestViewController: UITableViewDataSource {
                func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
                    return 1
                }

                func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
                    return UITableViewCell()
                }
            }
            """,
            """
            // Supporting Types
            ↓protocol TestViewControllerDelegate {
                func didPressTrackedButton()
            }

            class TestViewController: UIViewController {}

            // Supporting Types
            protocol TestViewControllerDelegate {
                func didPressTrackedButton()
            }
            """,
            """
            ↓struct ContentView: View {
               var body: some View {
                   Text("Hello, World!")
               }
            }

            struct ContentView_Previews: PreviewProvider {
               static var previews: some View { ContentView() }
            }
            """,
            """
            ↓struct ContentView: View {
               var body: some View {
                   Text("Hello, World!")
               }
            }

            struct ContentView_LibraryContent: LibraryContentProvider {
                var views: [LibraryItem] {
                    LibraryItem(ContentView())
                }
            }
            """,
        ])

        let reversedOrderDescription = FileTypesOrderRule.description
            .with(triggeringExamples: triggeringExamples)
            .with(nonTriggeringExamples: nonTriggeringExamples)

        verifyRule(
            reversedOrderDescription,
            ruleConfiguration: [
                "order": ["library_content_provider", "preview_provider", "extension", "main_type", "supporting_type"]
            ]
        )
    }

    @Test
    func fileTypesOrderGroupedOrder() {
        // Test with grouped `order` entries
        let nonTriggeringExamples = #examples([
            """
            class TestViewController: UIViewController {}

            // Supporting Type
            protocol TestViewControllerDelegate {
                func didPressTrackedButton()
            }

            // Extension
            extension TestViewController: UITableViewDataSource {
                func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
                    return 1
                }
            }

            // Supporting Type
            protocol TestViewControllerDelegate2 {
                func didPressTrackedButton()
            }

            // Extension
            extension TestViewController: UITableViewDelegate {
                func someMethod() {}
            }
            """,
        ])
        let triggeringExamples = #examples([
            """
            // Supporting Types
            ↓protocol TestViewControllerDelegate {
                func didPressTrackedButton()
            }

            class TestViewController: UIViewController {}
            """,
            """
            // Extensions
            ↓extension TestViewController: UITableViewDataSource {
                func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
                    return 1
                }

                func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
                    return UITableViewCell()
                }
            }

            class TestViewController: UIViewController {}
            """,
        ])

        let groupedOrderDescription = FileTypesOrderRule.description
            .with(triggeringExamples: triggeringExamples)
            .with(nonTriggeringExamples: nonTriggeringExamples)

        verifyRule(
            groupedOrderDescription,
            ruleConfiguration: [
                "order": ["main_type", ["extension", "supporting_type"] as Any, "preview_provider"] as Any
            ]
        )
    }

    @Test
    func conditionalCompilationKeepsSupportingTypeViolationReason() {
        let example = Example(code: """
        extension Main {}

        #if canImport(Darwin)
        typealias Helper = Int
        #endif

        struct Main {
            let value: Int
        }
        """)

        let violations = ruleViolations(example)
        #expect(
            violations.first?.reason
                == "An 'extension' should not be placed amongst the file type(s) 'supporting_type'"
        )
    }

    private func ruleViolations(_ example: Example, ruleConfiguration: Any? = nil) -> [StyleViolation] {
        guard let config = makeConfig(ruleConfiguration, FileTypesOrderRule.identifier) else {
            return []
        }
        return violations(example, config: config)
    }
}
