//
//  AppIntentHandlers.swift
//  Runner
//
//  Created by LittleSheep on 2026/1/16.
//

import AppIntents
import UIKit

@available(iOS 16.0, *)
struct OpenChatIntent: AppIntent {
    static var title: LocalizedStringResource = "intent_open_chat_title"
    static var description = IntentDescription("intent_open_chat_desc")
    static var isDiscoverable = true
    static var openAppWhenRun = true

    @Parameter(title: "Channel ID")
    var channelId: String?

    func perform() async throws -> some IntentResult & OpensIntent {
        guard let channelId = channelId, !channelId.isEmpty else {
            throw AppIntentError.requiredParameter("Channel ID")
        }

        DeepLinkHandler.shared.handle(url: URL(string: "solian://chat/\(channelId)")!)

        return .result(value: "Opening chat \(channelId)")
    }
}

@available(iOS 16.0, *)
struct OpenPostIntent: AppIntent {
    static var title: LocalizedStringResource = "intent_open_post_title"
    static var description = IntentDescription("intent_open_post_desc")
    static var isDiscoverable = true
    static var openAppWhenRun = true

    @Parameter(title: "Post ID")
    var postId: String?

    func perform() async throws -> some IntentResult & OpensIntent {
        guard let postId = postId, !postId.isEmpty else {
            throw AppIntentError.requiredParameter("Post ID")
        }

        DeepLinkHandler.shared.handle(url: URL(string: "solian://posts/\(postId)")!)

        return .result(value: "Opening post \(postId)")
    }
}

@available(iOS 16.0, *)
struct OpenComposeIntent: AppIntent {
    static var title: LocalizedStringResource = "intent_open_compose_title"
    static var description = IntentDescription("intent_open_compose_desc")
    static var isDiscoverable = true
    static var openAppWhenRun = true

    func perform() async throws -> some IntentResult & OpensIntent {
        DeepLinkHandler.shared.handle(url: URL(string: "solian://compose")!)

        return .result(value: "Opening compose screen")
    }
}

@available(iOS 16.0, *)
struct ComposePostIntent: AppIntent {
    static var title: LocalizedStringResource = "intent_compose_post_title"
    static var description = IntentDescription("intent_compose_post_desc")
    static var isDiscoverable = true
    static var openAppWhenRun = true

    func perform() async throws -> some IntentResult & OpensIntent {
        DeepLinkHandler.shared.handle(url: URL(string: "solian://compose")!)

        return .result(value: "Opening compose screen")
    }
}

@available(iOS 16.0, *)
struct SearchContentIntent: AppIntent {
    static var title: LocalizedStringResource = "intent_search_title"
    static var description = IntentDescription("intent_search_desc")
    static var isDiscoverable = true
    static var openAppWhenRun = true

    @Parameter(title: "Search Query")
    var query: String?

    func perform() async throws -> some IntentResult & OpensIntent {
        guard let query = query, !query.isEmpty else {
            throw AppIntentError.requiredParameter("Search Query")
        }

        let encodedQuery = query.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? query
        DeepLinkHandler.shared.handle(url: URL(string: "solian://search?q=\(encodedQuery)")!)

        return .result(value: "Searching for \"\(query)\"")
    }
}

@available(iOS 16.0, *)
struct ViewNotificationsIntent: AppIntent {
    static var title: LocalizedStringResource = "intent_notifications_title"
    static var description = IntentDescription("intent_notifications_desc")
    static var isDiscoverable = true
    static var openAppWhenRun = true

    func perform() async throws -> some IntentResult & OpensIntent {
        DeepLinkHandler.shared.handle(url: URL(string: "solian://notifications")!)

        return .result(value: "Opening notifications")
    }
}

@available(iOS 16.0, *)
struct CheckNotificationsIntent: AppIntent {
    static var title: LocalizedStringResource = "intent_check_notifications_title"
    static var description = IntentDescription("intent_check_notifications_desc")
    static var isDiscoverable = true
    static var openAppWhenRun = false

    func perform() async throws -> some IntentResult & ProvidesDialog {
        do {
            let count = try await NetworkService.shared.getNotificationCount()

            let message: String
            if count == 0 {
                message = "You have no new notifications"
            } else if count == 1 {
                message = "You have 1 new notification"
            } else {
                message = "You have \(count) new notifications"
            }

            return .result(
                value: message,
                dialog: "\(message)"
            )
        } catch {
            throw AppIntentError.networkError("Failed to check notifications: \(error.localizedDescription)")
        }
    }
}

@available(iOS 16.0, *)
struct SendMessageIntent: AppIntent {
    static var title: LocalizedStringResource = "intent_send_message_title"
    static var description = IntentDescription("intent_send_message_desc")
    static var isDiscoverable = true
    static var openAppWhenRun = false

    @Parameter(title: "Channel ID")
    var channelId: String?

    @Parameter(title: "Message Content")
    var content: String?

    func perform() async throws -> some IntentResult & ProvidesDialog {
        guard let channelId = channelId, !channelId.isEmpty else {
            throw AppIntentError.requiredParameter("Channel ID")
        }

        guard let content = content, !content.isEmpty else {
            throw AppIntentError.requiredParameter("Message Content")
        }

        do {
            try await NetworkService.shared.sendMessage(channelId: channelId, content: content)

            return .result(
                value: "Message sent to channel \(channelId)",
                dialog: "Message sent successfully"
            )
        } catch {
            throw AppIntentError.networkError("Failed to send message: \(error.localizedDescription)")
        }
    }
}

@available(iOS 16.0, *)
struct ReadMessagesIntent: AppIntent {
    static var title: LocalizedStringResource = "intent_read_messages_title"
    static var description = IntentDescription("intent_read_messages_desc")
    static var isDiscoverable = true
    static var openAppWhenRun = false

    @Parameter(title: "Channel ID")
    var channelId: String?

    @Parameter(title: "Number of Messages", default: "5")
    var limit: String?

    func perform() async throws -> some IntentResult & ProvidesDialog {
        guard let channelId = channelId, !channelId.isEmpty else {
            throw AppIntentError.requiredParameter("Channel ID")
        }

        let limitValue = Int(limit ?? "5") ?? 5
        let safeLimit = max(1, min(20, limitValue))

        do {
            let messages = try await NetworkService.shared.getMessages(
                channelId: channelId,
                offset: 0,
                take: safeLimit
            )

            if messages.isEmpty {
                return .result(
                    value: "No messages found in channel \(channelId)",
                    dialog: "No messages found"
                )
            }

            let formattedMessages = messages.compactMap { message -> String? in
                let senderName = message.sender?.account?.name ?? "Unknown"
                let content = message.content ?? ""
                return "\(senderName): \(content)"
            }.joined(separator: "\n")

            return .result(
                value: formattedMessages,
                dialog: "Found \(messages.count) messages"
            )
        } catch {
            throw AppIntentError.networkError("Failed to read messages: \(error.localizedDescription)")
        }
    }
}

@available(iOS 16.0, *)
struct CheckUnreadChatsIntent: AppIntent {
    static var title: LocalizedStringResource = "intent_unread_chats_title"
    static var description = IntentDescription("intent_unread_chats_desc")
    static var isDiscoverable = true
    static var openAppWhenRun = false

    func perform() async throws -> some IntentResult & ProvidesDialog {
        do {
            let count = try await NetworkService.shared.getUnreadChatsCount()

            let message: String
            if count == 0 {
                message = "You have no unread messages"
            } else if count == 1 {
                message = "You have 1 unread message"
            } else {
                message = "You have \(count) unread messages"
            }

            return .result(
                value: message,
                dialog: "\(message)"
            )
        } catch {
            throw AppIntentError.networkError("Failed to check unread chats: \(error.localizedDescription)")
        }
    }
}

@available(iOS 16.0, *)
struct MarkNotificationsReadIntent: AppIntent {
    static var title: LocalizedStringResource = "intent_mark_read_title"
    static var description = IntentDescription("intent_mark_read_desc")
    static var isDiscoverable = true
    static var openAppWhenRun = false

    func perform() async throws -> some IntentResult & ProvidesDialog {
        do {
            try await NetworkService.shared.markNotificationsRead()

            return .result(
                value: "All notifications marked as read",
                dialog: "All notifications marked as read"
            )
        } catch {
            throw AppIntentError.networkError("Failed to mark notifications: \(error.localizedDescription)")
        }
    }
}

enum AppIntentError: Error, CustomLocalizedStringResourceConvertible {
    case requiredParameter(String)
    case networkError(String)

    var localizedStringResource: LocalizedStringResource {
        switch self {
        case .requiredParameter(let param):
            return "\(param) is required"
        case .networkError(let message):
            return "Network error: \(message)"
        }
    }
}
