import MarkdownUI
import SwiftUI

struct SybilChatTranscriptView: View {
    var messages: [Message]
    var isLoading: Bool
    var isSending: Bool
    var topContentInset: CGFloat = 0
    var bottomContentInset: CGFloat = 0

    private var hasPendingAssistant: Bool {
        messages.contains { message in
            message.id.hasPrefix("temp-assistant-") && message.content.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
        }
    }

    var body: some View {
        ScrollView {
            LazyVStack(alignment: .leading, spacing: 26) {
                if isSending && !hasPendingAssistant {
                    HStack(spacing: 8) {
                        ProgressView()
                            .controlSize(.small)
                            .tint(SybilTheme.textMuted)
                        Text("Assistant is typing…")
                            .font(.sybil(.footnote))
                            .foregroundStyle(SybilTheme.textMuted)
                    }
                    .scaleEffect(x: 1, y: -1)
                }

                ForEach(messages.reversed()) { message in
                    MessageBubble(message: message, isSending: isSending)
                        .frame(maxWidth: .infinity)
                        .scaleEffect(x: 1, y: -1)
                }

                if isLoading && messages.isEmpty {
                    Text("Loading messages…")
                        .font(.sybil(.footnote))
                        .foregroundStyle(SybilTheme.textMuted)
                        .padding(.top, 24)
                        .scaleEffect(x: 1, y: -1)
                }
            }
            .frame(maxWidth: .infinity, alignment: .leading)
            .padding(.horizontal, 14)
            .padding(.top, 18 + bottomContentInset)
            .padding(.bottom, 18 + topContentInset)
        }
        .frame(maxWidth: .infinity, alignment: .leading)
        .scrollDismissesKeyboard(.interactively)
        .scaleEffect(x: 1, y: -1)
    }
}

private struct MessageBubble: View {
    var message: Message
    var isSending: Bool

    private var toolCallMetadata: ToolCallMetadata? {
        message.toolCallMetadata
    }

    private var isUser: Bool {
        message.role == .user
    }

    private var isPendingAssistant: Bool {
        message.id.hasPrefix("temp-assistant-") &&
            isSending &&
            message.content.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
    }

    var body: some View {
        HStack(alignment: .top, spacing: 0) {
            leadingSpacer

            if let toolCallMetadata {
                ToolCallActivityChip(
                    metadata: toolCallMetadata,
                    fallbackContent: message.content,
                    createdAt: message.createdAt
                )
            } else {
                VStack(alignment: .leading, spacing: 8) {
                    if !message.attachments.isEmpty {
                        SybilAttachmentListView(
                            attachments: message.attachments,
                            tone: isUser ? .user : .assistant
                        )
                    }

                    if isPendingAssistant {
                        HStack(spacing: 8) {
                            ProgressView()
                                .controlSize(.small)
                                .tint(SybilTheme.primary)
                            Text("Thinking…")
                                .font(.sybil(.footnote))
                                .foregroundStyle(SybilTheme.textMuted)
                        }
                        .padding(.vertical, 2)
                    } else if !message.content.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
                        Markdown(message.content)
                            .tint(SybilTheme.primary)
                            .foregroundStyle(isUser ? SybilTheme.text : SybilTheme.text.opacity(0.95))
                            .markdownTheme(.sybilReadable)
                    }
                }
                .padding(.horizontal, isUser ? 14 : 2)
                .padding(.vertical, isUser ? 13 : 2)
                .textSelection(.enabled)
                .background(
                    Group {
                        if isUser {
                            RoundedRectangle(cornerRadius: 16)
                                .fill(SybilTheme.userBubbleGradient)
                                .overlay(
                                    RoundedRectangle(cornerRadius: 16)
                                        .stroke(SybilTheme.primary.opacity(0.45), lineWidth: 1)
                                )
                        } else {
                            RoundedRectangle(cornerRadius: 0)
                                .fill(Color.clear)
                        }
                    }
                )
                .frame(maxWidth: isUser ? 420 : nil, alignment: isUser ? .trailing : .leading)
            }

            trailingSpacer
        }
        .frame(maxWidth: .infinity, alignment: isUser ? .trailing : .leading)
    }

    @ViewBuilder
    private var leadingSpacer: some View {
        if isUser {
            Spacer(minLength: 44)
        }
    }

    @ViewBuilder
    private var trailingSpacer: some View {
        if !isUser {
            Spacer(minLength: 0)
        }
    }
}

private struct ToolCallActivityChip: View {
    var metadata: ToolCallMetadata
    var fallbackContent: String
    var createdAt: Date

    private var summary: String {
        if let text = metadata.summary?.trimmingCharacters(in: .whitespacesAndNewlines), !text.isEmpty {
            return text
        }
        if (metadata.status ?? "").lowercased() == "failed",
           let error = metadata.error?.trimmingCharacters(in: .whitespacesAndNewlines),
           !error.isEmpty {
            return "Tool failed: \(error)"
        }
        if let preview = metadata.resultPreview?.trimmingCharacters(in: .whitespacesAndNewlines), !preview.isEmpty {
            return preview
        }
        if !fallbackContent.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
            return fallbackContent
        }
        return "Ran tool '\(metadata.toolName ?? "unknown_tool")'."
    }

    private var toolLabel: String {
        let raw = metadata.toolName?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
        guard !raw.isEmpty else { return "Tool call" }
        return raw
            .replacingOccurrences(of: "_", with: " ")
            .split(separator: " ")
            .map { word in
                word.prefix(1).uppercased() + word.dropFirst()
            }
            .joined(separator: " ")
    }

    private var iconName: String {
        let name = (metadata.toolName ?? "").lowercased()
        if name.contains("search") {
            return "globe"
        }
        if name.contains("url") || name.contains("fetch") || name.contains("http") {
            return "link"
        }
        return "wrench.and.screwdriver"
    }

    private var isFailed: Bool {
        (metadata.status ?? "").lowercased() == "failed"
    }

    private var detailLabel: String {
        var pieces: [String] = [isFailed ? "Failed" : "Completed"]
        if let durationMs = metadata.durationMs, durationMs > 0 {
            pieces.append("\(durationMs) ms")
        }
        pieces.append(createdAt.sybilShortTimeLabel)
        return pieces.joined(separator: " • ")
    }

    var body: some View {
        HStack(alignment: .top, spacing: 11) {
            ZStack {
                RoundedRectangle(cornerRadius: 9)
                    .fill((isFailed ? SybilTheme.danger : SybilTheme.accent).opacity(0.13))
                    .overlay(
                        RoundedRectangle(cornerRadius: 9)
                            .stroke((isFailed ? SybilTheme.danger : SybilTheme.accent).opacity(0.34), lineWidth: 1)
                    )
                Image(systemName: iconName)
                    .font(.system(size: 14, weight: .semibold))
                    .foregroundStyle(isFailed ? SybilTheme.danger : SybilTheme.accent)
            }
            .frame(width: 30, height: 30)

            VStack(alignment: .leading, spacing: 4) {
                Text(summary)
                    .font(.sybil(.subheadline))
                    .foregroundStyle(isFailed ? SybilTheme.danger.opacity(0.96) : SybilTheme.text.opacity(0.94))
                    .lineSpacing(3)
                    .fixedSize(horizontal: false, vertical: true)

                HStack(spacing: 6) {
                    Text(toolLabel)
                        .font(.sybil(.caption2, weight: .semibold))
                        .foregroundStyle(isFailed ? SybilTheme.danger.opacity(0.84) : SybilTheme.accent.opacity(0.90))
                        .lineLimit(1)

                    Text(detailLabel)
                        .font(.sybil(.caption2))
                        .foregroundStyle(SybilTheme.textMuted)
                        .lineLimit(1)
                }
            }
        }
        .textSelection(.enabled)
        .padding(.horizontal, 12)
        .padding(.vertical, 10)
        .background(
            RoundedRectangle(cornerRadius: 12)
                .fill(isFailed ? SybilTheme.failedToolCallGradient : SybilTheme.toolCallGradient)
                .overlay(
                    RoundedRectangle(cornerRadius: 12)
                        .stroke((isFailed ? SybilTheme.danger : SybilTheme.accent).opacity(0.34), lineWidth: 1)
                )
        )
        .frame(maxWidth: 520, alignment: .leading)
    }
}
