import Foundation
import CoreData
import Combine
import CoreSpotlight

class LinkViewModel: ObservableObject {
    @Published var links: [Link] = []
    @Published var filteredLinks: [Link] = []
    @Published var searchText: String = "" {
        didSet {
            filterLinks()
        }
    }
    @Published var selectedSortOption: SortOption = .alias {
        didSet {
            sortLinks()
        }
    }
    @Published var sortAscending: Bool = true {
        didSet { sortLinks() }
    }
    @Published var selectedTag: Tag? {
        didSet {
            filterLinks()
        }
    }
    @Published var isLoading: Bool = false
    @Published var errorMessage: String?

    private var cancellables = Set<AnyCancellable>()
    private let persistenceController = PersistenceController.shared

    enum SortOption: String, CaseIterable {
        case alias = "alias"
        case type = "linkType"
        case clicks = "clickCount"
        case dateCreated = "createdAt"
        case dateUpdated = "updatedAt"

        var displayName: String {
            switch self {
            case .alias:
                return NSLocalizedString("alias", comment: "Sort by alias")
            case .type:
                return NSLocalizedString("type", comment: "Sort by type")
            case .clicks:
                return NSLocalizedString("clicks", comment: "Sort by clicks")
            case .dateCreated:
                return NSLocalizedString("date_created", comment: "Sort by date created")
            case .dateUpdated:
                return NSLocalizedString("date_updated", comment: "Sort by date updated")
            }
        }
    }

    init() {
        fetchLinks()
        initializeSpotlightSearch()
    }

    private func initializeSpotlightSearch() {
        // Initialize Spotlight search indexing when the app starts
        DispatchQueue.global(qos: .background).async {
            SpotlightSearchManager.shared.initializeSpotlightIndexing()
        }
    }

    /// Manually refresh Spotlight search index
    func refreshSpotlightIndex() {
        DispatchQueue.global(qos: .background).async {
            SpotlightSearchManager.shared.initializeSpotlightIndexing()
        }
    }

    /// Check Spotlight search status for debugging
    func checkSpotlightStatus(completion: @escaping (Int) -> Void) {
        SpotlightSearchManager.shared.getIndexedItemsStatus(completion: completion)
    }

    func fetchLinks() {
        isLoading = true
        let context = persistenceController.container.viewContext
        let request: NSFetchRequest<Link> = Link.fetchRequest()
        request.sortDescriptors = [NSSortDescriptor(keyPath: \Link.alias, ascending: true)]

        do {
            links = try context.fetch(request)
            filterLinks()
            isLoading = false
        } catch {
            errorMessage = error.localizedDescription
            isLoading = false
        }
    }

    func createLink(alias: String, originalURL: String?, text: String?, linkType: LinkType, description: String?, tags: [Tag]) -> Bool {
        let context = persistenceController.container.viewContext

        // Check if alias already exists
        if aliasExists(alias) {
            errorMessage = NSLocalizedString("alias_already_exists", comment: "Alias already exists")
            return false
        }

        let newLink = Link(context: context)
        newLink.alias = alias
        newLink.originalURL = originalURL
        newLink.text = text
        newLink.linkType = linkType.rawValue
        newLink.linkDescription = description
        newLink.clickCount = 0
        newLink.createdAt = Date()
        newLink.updatedAt = Date()

        // Add tags
        for tag in tags {
            newLink.addToTags(tag)
        }

        // Create change log
        let changeLog = ChangeLog(context: context)
        changeLog.changeType = "CREATE"
        changeLog.changeDescription = "Link created"
        changeLog.changedAt = Date()
        changeLog.link = newLink

        do {
            try context.save()

            // Index the new link in Spotlight search
            SpotlightSearchManager.shared.indexLink(newLink)

            fetchLinks()
            return true
        } catch {
            errorMessage = error.localizedDescription
            return false
        }
    }

    func updateLink(_ link: Link, alias: String, originalURL: String?, text: String?, linkType: LinkType, description: String?, tags: [Tag]) -> Bool {
        let context = persistenceController.container.viewContext

        // Check if alias already exists (excluding current link)
        if alias != link.alias && aliasExists(alias) {
            errorMessage = NSLocalizedString("alias_already_exists", comment: "Alias already exists")
            return false
        }

        link.alias = alias
        link.originalURL = originalURL
        link.text = text
        link.linkType = linkType.rawValue
        link.linkDescription = description
        link.updatedAt = Date()

        // Update tags
        link.removeFromTags(link.tags ?? NSSet())
        for tag in tags {
            link.addToTags(tag)
        }

        // Create change log
        let changeLog = ChangeLog(context: context)
        changeLog.changeType = "UPDATE"
        changeLog.changeDescription = "Link updated"
        changeLog.changedAt = Date()
        changeLog.link = link

        do {
            try context.save()

            // Re-index the updated link in Spotlight search
            SpotlightSearchManager.shared.indexLink(link)

            fetchLinks()
            return true
        } catch {
            errorMessage = error.localizedDescription
            return false
        }
    }

    func deleteLink(_ link: Link) {
        let context = persistenceController.container.viewContext
        let aliasToRemove = link.alias

        context.delete(link)

        do {
            try context.save()

            // Remove the link from Spotlight search index
            SpotlightSearchManager.shared.removeLink(withAlias: aliasToRemove)

            fetchLinks()
        } catch {
            errorMessage = error.localizedDescription
        }
    }

    func recordClick(for link: Link) {
        let context = persistenceController.container.viewContext

        // Create click log
        let clickLog = ClickLog(context: context)
        clickLog.clickedAt = Date()
        clickLog.link = link

        // Increment click count
        link.clickCount += 1

        do {
            try context.save()
            fetchLinks()
        } catch {
            errorMessage = error.localizedDescription
        }
    }

    func aliasExists(_ alias: String) -> Bool {
        let context = persistenceController.container.viewContext
        let request: NSFetchRequest<Link> = Link.fetchRequest()
        request.predicate = NSPredicate(format: "alias == %@", alias)
        request.fetchLimit = 1

        do {
            let count = try context.count(for: request)
            return count > 0
        } catch {
            return false
        }
    }

    private func filterLinks() {
        var filtered = links

        // Filter by search text (alias only for Quick Go)
        if !searchText.isEmpty {
            filtered = filtered.filter { link in
                link.alias.localizedCaseInsensitiveContains(searchText)
            }
        }

        // Filter by selected tag
        if let selectedTag = selectedTag {
            filtered = filtered.filter { link in
                link.sortedTags.contains(selectedTag)
            }
        }

        filteredLinks = filtered
        sortLinks()
    }

    private func sortLinks() {
        let ascending = sortAscending
        switch selectedSortOption {
        case .alias:
            filteredLinks.sort { ascending ? ($0.alias < $1.alias) : ($0.alias > $1.alias) }
        case .type:
            filteredLinks.sort { ascending ? ($0.linkType < $1.linkType) : ($0.linkType > $1.linkType) }
        case .clicks:
            filteredLinks.sort { ascending ? ($0.clickCount < $1.clickCount) : ($0.clickCount > $1.clickCount) }
        case .dateCreated:
            filteredLinks.sort { ascending ? ($0.createdAt < $1.createdAt) : ($0.createdAt > $1.createdAt) }
        case .dateUpdated:
            filteredLinks.sort { ascending ? ($0.updatedAt < $1.updatedAt) : ($0.updatedAt > $1.updatedAt) }
        }
    }

    func openLink(_ link: Link, with parameters: [String: String] = [:]) {
        recordClick(for: link)

        guard let urlString = link.originalURL else { return }

        var processedURL = urlString

        // Process template parameters
        if link.isTemplate {
            processedURL = URLTemplateProcessor.processTemplate(urlString, with: parameters)
        }

        guard let url = URL(string: processedURL) else { return }

        if UIApplication.shared.canOpenURL(url) {
            UIApplication.shared.open(url)
        }
    }
}

// MARK: - Search functionality
extension LinkViewModel {
    func performQuickSearch(_ query: String) {
        searchText = query

        // If user presses enter with search text and no results, open as URL
        if filteredLinks.isEmpty && !query.isEmpty {
            if let url = URL(string: query.hasPrefix("http") ? query : "https://\(query)") {
                if UIApplication.shared.canOpenURL(url) {
                    UIApplication.shared.open(url)
                }
            }
        }
    }
}

// Import UIKit for UIApplication
import UIKit
