import Foundation
import XCTest

/// Tracks and cleans up resources created during integration tests.
///
/// Usage:
/// ```
/// let cleaner = TestDataCleaner(token: session.token)
/// let residence = TestDataSeeder.createResidence(token: session.token)
/// cleaner.trackResidence(residence.id)
/// // ... test runs ...
/// cleaner.cleanAll()  // called in tearDown
/// ```
class TestDataCleaner {
    private let token: String
    private var residenceIds: [Int] = []
    private var taskIds: [Int] = []
    private var contractorIds: [Int] = []
    private var documentIds: [Int] = []

    init(token: String) {
        self.token = token
    }

    // MARK: - Track Resources

    func trackResidence(_ id: Int) {
        residenceIds.append(id)
    }

    func trackTask(_ id: Int) {
        taskIds.append(id)
    }

    func trackContractor(_ id: Int) {
        contractorIds.append(id)
    }

    func trackDocument(_ id: Int) {
        documentIds.append(id)
    }

    // MARK: - Seed + Track (Convenience)

    /// Create a residence and automatically track it for cleanup.
    @discardableResult
    func seedResidence(name: String? = nil) -> TestResidence {
        let residence = TestDataSeeder.createResidence(token: token, name: name)
        trackResidence(residence.id)
        return residence
    }

    /// Create a task and automatically track it for cleanup.
    @discardableResult
    func seedTask(residenceId: Int, title: String? = nil, fields: [String: Any] = [:]) -> TestTask {
        let task = TestDataSeeder.createTask(token: token, residenceId: residenceId, title: title, fields: fields)
        trackTask(task.id)
        return task
    }

    /// Create a contractor and automatically track it for cleanup.
    @discardableResult
    func seedContractor(name: String? = nil, fields: [String: Any] = [:]) -> TestContractor {
        let contractor = TestDataSeeder.createContractor(token: token, name: name, fields: fields)
        trackContractor(contractor.id)
        return contractor
    }

    /// Create a document and automatically track it for cleanup.
    @discardableResult
    func seedDocument(residenceId: Int, title: String? = nil, documentType: String = "general") -> TestDocument {
        let document = TestDataSeeder.createDocument(token: token, residenceId: residenceId, title: title, documentType: documentType)
        trackDocument(document.id)
        return document
    }

    /// Create a residence with tasks, all tracked for cleanup.
    func seedResidenceWithTasks(residenceName: String? = nil, taskCount: Int = 3) -> (residence: TestResidence, tasks: [TestTask]) {
        let result = TestDataSeeder.createResidenceWithTasks(token: token, residenceName: residenceName, taskCount: taskCount)
        trackResidence(result.residence.id)
        result.tasks.forEach { trackTask($0.id) }
        return result
    }

    /// Create a full residence with task, contractor, and document, all tracked.
    func seedFullResidence() -> (residence: TestResidence, task: TestTask, contractor: TestContractor, document: TestDocument) {
        let result = TestDataSeeder.createFullResidence(token: token)
        trackResidence(result.residence.id)
        trackTask(result.task.id)
        trackContractor(result.contractor.id)
        trackDocument(result.document.id)
        return result
    }

    // MARK: - Cleanup

    /// Delete all tracked resources in reverse dependency order.
    /// Documents and tasks first (they depend on residences), then contractors, then residences.
    /// Failures are logged but don't fail the test — cleanup is best-effort.
    func cleanAll() {
        // Delete documents first (depend on residences)
        for id in documentIds.reversed() {
            _ = TestAccountAPIClient.deleteDocument(token: token, id: id)
        }
        documentIds.removeAll()

        // Delete tasks (depend on residences)
        for id in taskIds.reversed() {
            _ = TestAccountAPIClient.deleteTask(token: token, id: id)
        }
        taskIds.removeAll()

        // Delete contractors (independent, but clean before residences)
        for id in contractorIds.reversed() {
            _ = TestAccountAPIClient.deleteContractor(token: token, id: id)
        }
        contractorIds.removeAll()

        // Delete residences last
        for id in residenceIds.reversed() {
            _ = TestAccountAPIClient.deleteResidence(token: token, id: id)
        }
        residenceIds.removeAll()
    }

    /// Number of tracked resources (for debugging).
    var trackedCount: Int {
        residenceIds.count + taskIds.count + contractorIds.count + documentIds.count
    }
}
