import SwiftUI

struct ChatScreen: View {
    let taskId: Int
    let userType: String // "customer" or "worker"
    var otherPartyName: String?

    @EnvironmentObject var appState: AppState
    @Environment(\.dismiss) var dismiss
    @StateObject private var chatService = ChatService()

    @State private var messages: [ChatMessage] = []
    @State private var messageText = ""
    @State private var isLoading = true
    @State private var isSending = false
    @State private var error: String?
    @State private var otherUserTyping = false
    @State private var otherUserName: String?
    @State private var chatEnded = false
    @State private var showCloseChatAlert = false
    @State private var showingMyTasks = false

    // Polling timer
    private let pollTimer = Timer.publish(every: 3, on: .main, in: .common).autoconnect()

    var body: some View {
        VStack(spacing: 0) {
            // Chat ended banner
            if chatEnded {
                Text("This chat has ended")
                    .font(.callout.bold())
                    .frame(maxWidth: .infinity)
                    .padding(12)
                    .background(Color.payfritGreen.opacity(0.2))
            }

            // Error banner
            if let error = error {
                Text(error)
                    .font(.caption)
                    .foregroundColor(.red)
                    .frame(maxWidth: .infinity)
                    .padding(8)
                    .background(Color.red.opacity(0.1))
                    .onTapGesture { self.error = nil }
            }

            // Messages
            messageListView

            // Typing indicator
            if otherUserTyping {
                HStack {
                    Text("\(otherUserName ?? "Other user") is typing...")
                        .font(.caption)
                        .foregroundColor(.secondary)
                        .italic()
                    Spacer()
                }
                .padding(.horizontal, 16)
                .padding(.vertical, 4)
            }

            // Input
            if !chatEnded {
                inputArea
            }
        }
        .navigationTitle(userType == "customer" ? "Chat with Staff" : "Chat with Customer")
        .toolbar {
            ToolbarItem(placement: .navigationBarTrailing) {
                if chatService.isConnected {
                    Image(systemName: "wifi")
                        .foregroundColor(.green)
                        .font(.caption)
                } else {
                    Image(systemName: "wifi.slash")
                        .foregroundColor(.payfritGreen)
                        .font(.caption)
                }
            }
            if userType == "worker" && !chatEnded {
                ToolbarItem(placement: .navigationBarTrailing) {
                    Button { showCloseChatAlert = true } label: {
                        Image(systemName: "xmark.circle")
                    }
                }
            }
        }
        .alert("Close Chat", isPresented: $showCloseChatAlert) {
            Button("Cancel", role: .cancel) { }
            Button("Close", role: .destructive) { closeChatAction() }
        } message: {
            Text("Are you sure you want to close this chat?")
        }
        .overlay(alignment: .bottomTrailing) {
            Button { showingMyTasks = true } label: {
                Image(systemName: "checkmark.circle.fill")
                    .font(.title3)
                    .padding(12)
                    .background(Color.payfritGreen)
                    .foregroundColor(.white)
                    .clipShape(Circle())
                    .shadow(radius: 4)
            }
            .padding(.trailing, 16)
            .padding(.bottom, chatEnded ? 16 : 60)
        }
        .navigationDestination(isPresented: $showingMyTasks) {
            MyTasksScreen()
        }
        .task {
            otherUserName = otherPartyName
            await initializeChat()
        }
        .onReceive(pollTimer) { _ in
            if !chatEnded && !chatService.isConnected {
                pollNewMessages()
            }
        }
        .onDisappear {
            chatService.disconnect()
        }
    }

    // MARK: - Message List

    @ViewBuilder
    private var messageListView: some View {
        if isLoading {
            Spacer()
            ProgressView()
            Spacer()
        } else if messages.isEmpty {
            Spacer()
            VStack(spacing: 16) {
                Image(systemName: "bubble.left.and.bubble.right")
                    .font(.system(size: 48))
                    .foregroundColor(.secondary)
                Text("No messages yet")
                    .foregroundColor(.secondary)
                Text("Start the conversation!")
                    .font(.caption)
                    .foregroundColor(.secondary)
            }
            Spacer()
        } else {
            ScrollViewReader { proxy in
                ScrollView {
                    LazyVStack(spacing: 12) {
                        ForEach(messages) { msg in
                            messageBubble(msg)
                                .id(msg.messageId)
                        }
                    }
                    .padding(16)
                }
                .onChange(of: messages.count) { _ in
                    if let last = messages.last {
                        withAnimation {
                            proxy.scrollTo(last.messageId, anchor: .bottom)
                        }
                    }
                }
            }
        }
    }

    private func messageBubble(_ msg: ChatMessage) -> some View {
        let isMe = msg.senderType == userType
        let time = msg.createdOn.formatted(date: .omitted, time: .shortened)

        return HStack(alignment: .bottom, spacing: 8) {
            if isMe { Spacer(minLength: 60) }

            if !isMe {
                Circle()
                    .fill(Color(.systemGray4))
                    .frame(width: 32, height: 32)
                    .overlay(
                        Text(msg.senderName.isEmpty
                             ? (msg.senderType == "worker" ? "S" : "C")
                             : String(msg.senderName.prefix(1)).uppercased())
                            .font(.caption.bold())
                    )
            }

            VStack(alignment: isMe ? .trailing : .leading, spacing: 4) {
                if !isMe && !msg.senderName.isEmpty {
                    Text(msg.senderName)
                        .font(.caption2.bold())
                        .foregroundColor(.secondary)
                }

                Text(msg.text)
                    .foregroundColor(isMe ? .white : .primary)

                Text(time)
                    .font(.caption2)
                    .foregroundColor(isMe ? .white.opacity(0.7) : .secondary)
            }
            .padding(.horizontal, 16)
            .padding(.vertical, 10)
            .background(isMe ? Color.accentColor : Color(.systemGray5))
            .cornerRadius(16, corners: isMe
                ? [.topLeft, .topRight, .bottomLeft]
                : [.topLeft, .topRight, .bottomRight])

            if isMe {
                let initials = {
                    let parts = (appState.userName ?? "").split(separator: " ")
                    if parts.count >= 2 {
                        return "\(parts[0].prefix(1))\(parts[1].prefix(1))".uppercased()
                    } else if let first = parts.first {
                        return String(first.prefix(1)).uppercased()
                    }
                    return "Me"
                }()
                Circle()
                    .fill(Color.accentColor.opacity(0.7))
                    .frame(width: 32, height: 32)
                    .overlay(
                        Text(initials)
                            .font(.caption2)
                            .foregroundColor(.white)
                    )
            }

            if !isMe { Spacer(minLength: 60) }
        }
    }

    // MARK: - Input

    private var inputArea: some View {
        HStack(spacing: 8) {
            TextField("Type a message...", text: $messageText)
                .textFieldStyle(.roundedBorder)
                .onSubmit { sendMessage() }

            Button(action: sendMessage) {
                if isSending {
                    ProgressView()
                        .frame(width: 36, height: 36)
                } else {
                    Image(systemName: "paperplane.fill")
                        .frame(width: 36, height: 36)
                }
            }
            .buttonStyle(.borderedProminent)
            .clipShape(Circle())
            .disabled(isSending || messageText.trimmingCharacters(in: .whitespaces).isEmpty)
        }
        .padding(.horizontal, 12)
        .padding(.vertical, 8)
        .background(.ultraThinMaterial)
    }

    // MARK: - Actions

    private func initializeChat() async {
        // Load messages first
        await loadMessages()

        // Try WebSocket
        let token = await APIService.shared.getToken()
        guard let token = token, !token.isEmpty else { return }

        chatService.onMessage = { msg in
            if !messages.contains(where: { $0.messageId == msg.messageId }) {
                messages.append(msg)
                Task {
                    if msg.senderType != userType {
                        try? await APIService.shared.markChatMessagesRead(taskId: taskId, readerType: userType)
                    }
                }
            }
        }

        chatService.onTyping = { event in
            if event.userType != userType {
                otherUserTyping = event.isTyping
                if !event.userName.isEmpty { otherUserName = event.userName }
            }
        }

        chatService.onEvent = { event in
            switch event.type {
            case .chatEnded:
                chatEnded = true
            case .userJoined:
                if let name = event.data?["userName"] as? String {
                    otherUserName = name
                }
            default: break
            }
        }

        let _ = await chatService.connect(taskId: taskId, userToken: token, userType: userType)
    }

    private func loadMessages() async {
        isLoading = true
        error = nil
        do {
            let result = try await APIService.shared.getChatMessages(taskId: taskId)
            messages = result.messages
            if result.chatClosed { chatEnded = true }
            isLoading = false
        } catch {
            self.error = error.localizedDescription
            isLoading = false
        }
    }

    private func sendMessage() {
        let text = messageText.trimmingCharacters(in: .whitespaces)
        guard !text.isEmpty, !isSending, !chatEnded else { return }

        isSending = true
        chatService.setTyping(false)

        if chatService.isConnected {
            chatService.sendMessage(text)
            messageText = ""
            isSending = false
        } else {
            Task {
                do {
                    let uid = await APIService.shared.getUserId()
                    _ = try await APIService.shared.sendChatMessage(
                        taskId: taskId, message: text, userId: uid, senderType: userType
                    )
                    messageText = ""
                    await loadMessages()
                } catch {
                    self.error = error.localizedDescription
                }
                isSending = false
            }
        }
    }

    private func pollNewMessages() {
        Task {
            let lastId = messages.last?.messageId ?? 0
            if let result = try? await APIService.shared.getChatMessages(taskId: taskId, afterMessageId: lastId) {
                if result.chatClosed && !chatEnded { chatEnded = true }
                for msg in result.messages {
                    if !messages.contains(where: { $0.messageId == msg.messageId }) {
                        messages.append(msg)
                    }
                }
            }
        }
    }

    private func closeChatAction() {
        guard userType == "worker" else { return }
        Task {
            do {
                try await APIService.shared.closeChat(taskId: taskId)
                chatService.closeChatWS()
                chatEnded = true
                dismiss()
            } catch {
                self.error = error.localizedDescription
            }
        }
    }
}

// MARK: - Corner Radius Extension

extension View {
    func cornerRadius(_ radius: CGFloat, corners: UIRectCorner) -> some View {
        clipShape(RoundedCornerShape(radius: radius, corners: corners))
    }
}

struct RoundedCornerShape: Shape {
    var radius: CGFloat
    var corners: UIRectCorner

    func path(in rect: CGRect) -> Path {
        let path = UIBezierPath(roundedRect: rect, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
        return Path(path.cgPath)
    }
}
