//
//  FavoritesWidget.swift
//  FavoritesWidget
//
//  Created by Platon on 08.08.2025.
//

import WidgetKit
import SwiftUI
import ActivityKit

private let appGroupId = "group.mobilemkch"

struct FavoriteThreadWidget: Identifiable, Codable {
    let id: Int
    let title: String
    let board: String
    let boardDescription: String
    let addedDate: Date
}

struct ThreadDTO: Codable, Identifiable {
    let id: Int
    let title: String
    let board: String
}

struct SimpleEntry: TimelineEntry {
    let date: Date
    let favorites: [FavoriteThreadWidget]
    let offline: Bool
}

struct Provider: AppIntentTimelineProvider {
    func placeholder(in context: Context) -> SimpleEntry {
        SimpleEntry(date: Date(), favorites: sample(), offline: false)
    }

    func snapshot(for configuration: ConfigurationAppIntent, in context: Context) async -> SimpleEntry {
        let favs = loadFavorites()
        if favs.isEmpty {
            return SimpleEntry(date: Date(), favorites: await loadFromNetwork(board: configuration.boardCode), offline: false)
        }
        return SimpleEntry(date: Date(), favorites: favs, offline: loadOffline())
    }
    
    func timeline(for configuration: ConfigurationAppIntent, in context: Context) async -> Timeline<SimpleEntry> {
        var favorites = loadFavorites()
        var offline = loadOffline()
        if favorites.isEmpty {
            favorites = await loadFromNetwork(board: configuration.boardCode)
            offline = false
        }
        let entry = SimpleEntry(date: Date(), favorites: favorites, offline: offline)
        let refresh = Calendar.current.date(byAdding: .minute, value: 15, to: Date()) ?? Date().addingTimeInterval(900)
        return Timeline(entries: [entry], policy: .after(refresh))
    }
    
    private func loadFavorites() -> [FavoriteThreadWidget] {
        guard let defaults = UserDefaults(suiteName: appGroupId),
              let data = defaults.data(forKey: "favoriteThreads"),
              let items = try? JSONDecoder().decode([FavoriteThreadWidget].self, from: data) else {
            return []
        }
        return items
    }
    
    private func loadOffline() -> Bool {
        let defaults = UserDefaults(suiteName: appGroupId)
        return defaults?.bool(forKey: "offlineMode") ?? false
    }
    
    private func sample() -> [FavoriteThreadWidget] {
        [FavoriteThreadWidget(id: 1, title: "Пример треда", board: "b", boardDescription: "Болталка", addedDate: Date())]
    }

    private func loadFromNetwork(board: String) async -> [FavoriteThreadWidget] {
        guard let url = URL(string: "https://mkch.pooziqo.xyz/api/board/\(board)") else { return [] }
        var req = URLRequest(url: url)
        req.setValue("MobileMkch/2.1.1-widget", forHTTPHeaderField: "User-Agent")
        do {
            let (data, _) = try await URLSession.shared.data(for: req)
            let threads = try JSONDecoder().decode([ThreadDTO].self, from: data)
            return Array(threads.prefix(3)).map { t in
                FavoriteThreadWidget(id: t.id, title: t.title, board: t.board, boardDescription: "", addedDate: Date())
            }
        } catch {
            return []
        }
    }
}

struct FavoritesWidgetEntryView : View {
    var entry: Provider.Entry
    @Environment(\.widgetFamily) private var family

    var body: some View {
        VStack(alignment: .leading, spacing: spacing) {
            header
            content
            Spacer(minLength: 0)
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
        .padding(padding)
        .foregroundStyle(.primary)
        .containerBackground(.background, for: .widget)
    }
    
    private var spacing: CGFloat { family == .systemSmall ? 4 : 6 }
    private var padding: CGFloat { family == .systemSmall ? 8 : 12 }
    private var titleFont: Font { family == .systemSmall ? .caption2 : .caption }
    private var headerFont: Font { family == .systemSmall ? .footnote : .headline }
    private var maxItems: Int { family == .systemSmall ? 1 : 3 }
    
    @ViewBuilder private var header: some View {
        HStack(spacing: 6) {
            Text("Избранное")
                .font(headerFont)
                .lineLimit(1)
                .minimumScaleFactor(0.8)
            Spacer()
            if entry.offline {
                Image(systemName: "wifi.slash").foregroundColor(.orange)
            }
        }
    }
    
    @ViewBuilder private var content: some View {
        if entry.favorites.isEmpty {
            Text("Пусто")
                .foregroundColor(.secondary)
                .font(titleFont)
        } else {
            ForEach(entry.favorites.prefix(maxItems)) { fav in
                if family == .systemSmall {
                    HStack(spacing: 6) {
                        BoardTag(code: fav.board)
                        Text(fav.title)
                            .font(titleFont)
                            .lineLimit(1)
                            .truncationMode(.tail)
                    }
                } else {
                    VStack(alignment: .leading, spacing: 2) {
                        BoardTag(code: fav.board)
                        Text(fav.title)
                            .font(titleFont)
                            .lineLimit(2)
                            .truncationMode(.tail)
                            .multilineTextAlignment(.leading)
                    }
                }
            }
        }
    }
}

private struct BoardTag: View {
    let code: String
    var body: some View {
        Text("/\(code)/")
            .font(.caption2)
            .foregroundColor(.blue)
            .padding(.horizontal, 6)
            .padding(.vertical, 2)
            .background(Color.blue.opacity(0.12))
            .clipShape(RoundedRectangle(cornerRadius: 4, style: .continuous))
    }
}

struct FavoritesWidget: Widget {
    let kind: String = "FavoritesWidget"

    var body: some WidgetConfiguration {
        AppIntentConfiguration(kind: kind, intent: ConfigurationAppIntent.self, provider: Provider()) { entry in
            FavoritesWidgetEntryView(entry: entry)
        }
        .configurationDisplayName("Избранное MobileMkch")
        .description("Показывает избранные треды или топ по выбранной доске.")
    }
}

@available(iOS 16.1, *)
struct ThreadActivityAttributes: ActivityAttributes {
    public struct ContentState: Codable, Hashable {
        var latestCommentText: String
        var commentsCount: Int
        var showTitle: Bool
        var showLastComment: Bool
        var showCommentCount: Bool
        var currentTitle: String
        var currentBoard: String
    }

    var threadId: Int
    var title: String
    var board: String
}

@available(iOS 16.1, *)
struct ThreadLiveActivity: Widget {
    var body: some WidgetConfiguration {
        ActivityConfiguration(for: ThreadActivityAttributes.self) { context in
            ThreadLiveActivityView(context: context)
        } dynamicIsland: { context in
            DynamicIsland {
                DynamicIslandExpandedRegion(.leading) {
                    Text("/\(context.state.currentBoard)/")
                        .font(.caption)
                        .foregroundColor(.blue)
                }
                DynamicIslandExpandedRegion(.center) {
                    VStack(alignment: .leading, spacing: 4) {
                        if context.state.showTitle {
                            Text(context.state.currentTitle)
                                .font(.footnote)
                                .lineLimit(2)
                        }
                        if context.state.showLastComment && !context.state.latestCommentText.isEmpty {
                            Text(context.state.latestCommentText)
                                .font(.caption2)
                                .lineLimit(2)
                                .foregroundColor(.secondary)
                        }
                    }
                }
                DynamicIslandExpandedRegion(.trailing) {
                    if context.state.showCommentCount {
                        Label("\(context.state.commentsCount)", systemImage: "text.bubble")
                            .font(.caption)
                    }
                }
            } compactLeading: {
                Text("/\(context.state.currentBoard)/")
                    .font(.caption2)
            } compactTrailing: {
                if context.state.showCommentCount {
                    Text("\(context.state.commentsCount)")
                        .font(.caption2)
                }
            } minimal: {
                Image(systemName: "text.bubble")
            }
        }
    }
}

@available(iOS 16.1, *)
private struct ThreadLiveActivityView: View {
    let context: ActivityViewContext<ThreadActivityAttributes>
    var body: some View {
        VStack(alignment: .leading, spacing: 6) {
            HStack(spacing: 6) {
                Text("/\(context.state.currentBoard)/")
                    .font(.caption)
                    .foregroundColor(.blue)
                if context.state.showCommentCount {
                    Label("\(context.state.commentsCount)", systemImage: "text.bubble")
                        .font(.caption)
                }
                Spacer()
            }
            if context.state.showTitle {
                Text(context.state.currentTitle)
                    .font(.footnote)
                    .lineLimit(2)
            }
            if context.state.showLastComment && !context.state.latestCommentText.isEmpty {
                Text(context.state.latestCommentText)
                    .font(.caption2)
                    .foregroundColor(.secondary)
                    .lineLimit(2)
            }
        }
        .padding(12)
    }
}
