//
//  ModelInfoView.swift
//  oAI
//
//  Rich model information modal
//
// SPDX-License-Identifier: AGPL-3.0-or-later
// Copyright (C) 2026 Rune Olsen
//
// This file is part of oAI.
//
// oAI is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// oAI is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General
// Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with oAI. If not, see <https://www.gnu.org/licenses/>.


import SwiftUI

struct ModelInfoView: View {
    let model: ModelInfo

    @Environment(\.dismiss) var dismiss
    @Bindable private var settings = SettingsService.shared

    var body: some View {
        VStack(spacing: 0) {
            // Header
            HStack {
                Text("Model Info")
                    .font(.system(size: 18, weight: .bold))
                Spacer()
                let isFav = settings.favoriteModelIds.contains(model.id)
                Button(action: { settings.toggleFavoriteModel(model.id) }) {
                    Image(systemName: isFav ? "star.fill" : "star")
                        .font(.system(size: 18))
                        .foregroundColor(isFav ? .yellow : .secondary)
                }
                .buttonStyle(.plain)
                .help(isFav ? "Remove from favorites" : "Add to favorites")
                .padding(.trailing, 8)
                Button { dismiss() } label: {
                    Image(systemName: "xmark.circle.fill")
                        .font(.title2)
                        .foregroundStyle(.secondary)
                }
                .buttonStyle(.plain)
                .keyboardShortcut(.escape, modifiers: [])
            }
            .padding(.horizontal, 24)
            .padding(.top, 20)
            .padding(.bottom, 12)

            Divider()

            ScrollView {
                VStack(alignment: .leading, spacing: 20) {
                    // Overview
                    sectionHeader("Overview")
                    infoRow("Name", model.name)
                    infoRow("ID", model.id)
                    if let provider = model.topProvider {
                        infoRow("Provider", provider)
                    }
                    if let desc = model.description {
                        VStack(alignment: .leading, spacing: 6) {
                            Text("Description")
                                .font(.subheadline.weight(.medium))
                                .foregroundColor(.secondary)
                            Text(desc)
                                .font(.body)
                                .foregroundColor(.primary)
                                .fixedSize(horizontal: false, vertical: true)
                                .textSelection(.enabled)
                        }
                        .padding(.leading, 4)
                    }

                    Divider()

                    // Pricing
                    sectionHeader("Pricing")
                    infoRow("Input", model.promptPriceDisplay + " / 1M tokens")
                    infoRow("Output", model.completionPriceDisplay + " / 1M tokens")

                    if model.pricing.prompt > 0 {
                        VStack(alignment: .leading, spacing: 6) {
                            Text("Cost Examples")
                                .font(.caption)
                                .foregroundColor(.secondary)
                            HStack(spacing: 16) {
                                costExample(label: "1K tokens", inputTokens: 1_000)
                                costExample(label: "10K tokens", inputTokens: 10_000)
                                costExample(label: "100K tokens", inputTokens: 100_000)
                            }
                        }
                        .padding(.leading, 4)
                    }

                    Divider()

                    // Context Window
                    sectionHeader("Context Window")
                    infoRow("Max Tokens", model.contextLength.formatted())

                    if model.contextLength > 0 {
                        VStack(alignment: .leading, spacing: 4) {
                            let maxContext = 2_000_000.0
                            let fraction = min(Double(model.contextLength) / maxContext, 1.0)
                            ZStack(alignment: .leading) {
                                RoundedRectangle(cornerRadius: 4)
                                    .fill(Color.gray.opacity(0.2))
                                    .frame(height: 16)
                                GeometryReader { geo in
                                    RoundedRectangle(cornerRadius: 4)
                                        .fill(Color.blue)
                                        .frame(width: geo.size.width * fraction, height: 16)
                                }
                                .frame(height: 16)
                            }
                            Text(model.contextLengthDisplay + " tokens")
                                .font(.caption2)
                                .foregroundColor(.secondary)
                        }
                        .padding(.leading, 4)
                    }

                    Divider()

                    // Capabilities
                    sectionHeader("Capabilities")
                    HStack(spacing: 12) {
                        capabilityBadge(icon: "eye.fill", label: "Vision", active: model.capabilities.vision)
                        capabilityBadge(icon: "wrench.fill", label: "Tools", active: model.capabilities.tools)
                        capabilityBadge(icon: "globe", label: "Online", active: model.capabilities.online)
                        capabilityBadge(icon: "photo.fill", label: "Image Gen", active: model.capabilities.imageGeneration)
                        capabilityBadge(icon: "brain", label: "Thinking", active: model.capabilities.thinking)
                    }

                    // Categories (if any)
                    if !model.categories.isEmpty {
                        Divider()
                        sectionHeader("Categories")
                        FlowLayout(spacing: 8) {
                            ForEach(model.categories, id: \.rawValue) { cat in
                                HStack(spacing: 5) {
                                    Image(systemName: cat.systemImage)
                                        .font(.caption2)
                                    Text(LocalizedStringKey(cat.rawValue))
                                        .font(.caption)
                                }
                                .padding(.horizontal, 10)
                                .padding(.vertical, 6)
                                .background(cat.color.opacity(0.12))
                                .foregroundColor(cat.color)
                                .cornerRadius(6)
                                .overlay(
                                    RoundedRectangle(cornerRadius: 6)
                                        .strokeBorder(cat.color.opacity(0.35), lineWidth: 1)
                                )
                            }
                        }
                        .padding(.leading, 4)
                    }

                    // Architecture (if available)
                    if let arch = model.architecture {
                        Divider()
                        sectionHeader("Architecture")
                        if let modality = arch.modality {
                            infoRow("Modality", modality)
                        }
                        if let tokenizer = arch.tokenizer {
                            infoRow("Tokenizer", tokenizer)
                        }
                        if let instructType = arch.instructType {
                            infoRow("Instruct Type", instructType)
                        }
                    }
                }
                .padding(.horizontal, 24)
                .padding(.vertical, 16)
            }

            Divider()

            // Bottom bar
            HStack {
                Spacer()
                Button("Done") { dismiss() }
                    .keyboardShortcut(.return, modifiers: [])
                    .buttonStyle(.borderedProminent)
                    .controlSize(.regular)
                Spacer()
            }
            .padding(.horizontal, 24)
            .padding(.vertical, 12)
        }
        .frame(minWidth: 550, idealWidth: 650, minHeight: 550, idealHeight: 750)
    }

    // MARK: - Layout Helpers

    private func sectionHeader(_ title: LocalizedStringKey) -> some View {
        Text(title)
            .font(.system(size: 13, weight: .semibold))
            .foregroundStyle(.secondary)
            .textCase(.uppercase)
    }

    private func infoRow(_ label: LocalizedStringKey, _ value: String) -> some View {
        HStack {
            Text(label)
                .font(.body)
            Spacer()
            Text(value)
                .font(.body)
                .foregroundColor(.secondary)
                .textSelection(.enabled)
        }
        .padding(.leading, 4)
    }

    @ViewBuilder
    private func costExample(label: LocalizedStringKey, inputTokens: Int) -> some View {
        let cost = (Double(inputTokens) * model.pricing.prompt / 1_000_000) +
                   (Double(inputTokens) * model.pricing.completion / 1_000_000)
        VStack(spacing: 2) {
            Text(label)
                .font(.caption2)
                .foregroundColor(.secondary)
            Text(String(format: "$%.4f", cost))
                .font(.caption.monospacedDigit())
                .foregroundColor(.primary)
        }
        .padding(.horizontal, 8)
        .padding(.vertical, 4)
        .background(Color.gray.opacity(0.1))
        .cornerRadius(4)
    }

    @ViewBuilder
    private func capabilityBadge(icon: String, label: LocalizedStringKey, active: Bool) -> some View {
        VStack(spacing: 4) {
            Image(systemName: icon)
                .font(.title3)
                .foregroundColor(active ? .blue : .gray.opacity(0.4))
            Text(label)
                .font(.caption2)
                .foregroundColor(active ? .primary : .secondary)
        }
        .frame(maxWidth: .infinity)
        .padding(.vertical, 8)
        .background(active ? Color.blue.opacity(0.1) : Color.gray.opacity(0.05))
        .cornerRadius(8)
    }
}

// MARK: - Flow Layout

struct FlowLayout: Layout {
    var spacing: CGFloat = 8

    func sizeThatFits(proposal: ProposedViewSize, subviews: Subviews, cache: inout Void) -> CGSize {
        let rows = rows(for: subviews, width: proposal.width ?? .infinity)
        let height = rows.map { row in
            row.map { $0.sizeThatFits(.unspecified).height }.max() ?? 0
        }.reduce(0, +) + CGFloat(max(0, rows.count - 1)) * spacing
        return CGSize(width: proposal.width ?? 0, height: height)
    }

    func placeSubviews(in bounds: CGRect, proposal: ProposedViewSize, subviews: Subviews, cache: inout Void) {
        let rows = rows(for: subviews, width: bounds.width)
        var y = bounds.minY
        for row in rows {
            var x = bounds.minX
            let rowH = row.map { $0.sizeThatFits(.unspecified).height }.max() ?? 0
            for sub in row {
                let size = sub.sizeThatFits(.unspecified)
                sub.place(at: CGPoint(x: x, y: y), proposal: ProposedViewSize(size))
                x += size.width + spacing
            }
            y += rowH + spacing
        }
    }

    private func rows(for subviews: Subviews, width: CGFloat) -> [[LayoutSubview]] {
        var rows: [[LayoutSubview]] = [[]]
        var rowWidth: CGFloat = 0
        for sub in subviews {
            let w = sub.sizeThatFits(.unspecified).width
            if rowWidth + w > width, !rows.last!.isEmpty {
                rows.append([])
                rowWidth = 0
            }
            rows[rows.count - 1].append(sub)
            rowWidth += w + spacing
        }
        return rows
    }
}

#Preview {
    ModelInfoView(model: ModelInfo(
        id: "anthropic/claude-sonnet-4",
        name: "Claude Sonnet 4",
        description: "Balanced intelligence and speed. This is a longer description to test how the modal handles multi-line text that wraps across several lines in the description field.",
        contextLength: 200_000,
        pricing: .init(prompt: 3.0, completion: 15.0),
        capabilities: .init(vision: true, tools: true, online: false),
        architecture: .init(tokenizer: "claude", instructType: "claude", modality: "text+image->text"),
        topProvider: "anthropic"
    ))
}
