import PhotosUI
import SwiftUI

// MARK: - Inbox / History

struct InboxTabView: View {
    @EnvironmentObject private var services: AppServices
    private var repo: ChatRepository { services.repository }
    private var chat: ChatState { repo.state }

    var body: some View {
        ScrollView {
            LazyVStack(alignment: .leading, spacing: 10) {
                Text(L10n.tr("tab_inbox"))
                    .font(.title2.weight(.bold))
                    .padding(.horizontal, 16)
                if chat.inboxResults.isEmpty {
                    Text(L10n.tr("inbox_empty"))
                        .foregroundStyle(YpChatTheme.textMuted)
                        .padding(.horizontal, 16)
                }
                ForEach(chat.inboxResults, id: \.userName) { item in
                    Button {
                        repo.openConversation(userName: item.userName)
                    } label: {
                        HStack {
                            Text(item.userName).fontWeight(.semibold)
                            Spacer()
                            Text(L10n.inboxNew(item.unreadCount))
                                .font(.subheadline)
                                .foregroundStyle(YpChatTheme.textMuted)
                        }
                        .padding(16)
                        .frame(maxWidth: .infinity, alignment: .leading)
                        .background(YpChatTheme.surface, in: RoundedRectangle(cornerRadius: 12))
                    }
                    .buttonStyle(.plain)
                    .padding(.horizontal, 16)
                }
            }
            .padding(.vertical, 16)
        }
    }
}

struct HistoryTabView: View {
    @EnvironmentObject private var services: AppServices
    private var repo: ChatRepository { services.repository }
    private var chat: ChatState { repo.state }

    var body: some View {
        ScrollView {
            LazyVStack(alignment: .leading, spacing: 10) {
                Text(L10n.tr("tab_history"))
                    .font(.title2.weight(.bold))
                    .padding(.horizontal, 16)
                if chat.historyResults.isEmpty {
                    Text(L10n.tr("history_empty"))
                        .foregroundStyle(YpChatTheme.textMuted)
                        .padding(.horizontal, 16)
                }
                ForEach(chat.historyResults, id: \.userName) { item in
                    Button {
                        repo.openConversation(userName: item.userName)
                    } label: {
                        VStack(alignment: .leading, spacing: 4) {
                            Text(item.userName).fontWeight(.semibold)
                            Text(item.lastMessage?.message ?? L10n.tr("no_message"))
                                .font(.subheadline)
                                .foregroundStyle(YpChatTheme.textMuted)
                        }
                        .padding(16)
                        .frame(maxWidth: .infinity, alignment: .leading)
                        .background(YpChatTheme.surface, in: RoundedRectangle(cornerRadius: 12))
                    }
                    .buttonStyle(.plain)
                    .padding(.horizontal, 16)
                }
            }
            .padding(.vertical, 16)
        }
    }
}

// MARK: - Console

struct ConsoleTabView: View {
    @EnvironmentObject private var services: AppServices
    private var repo: ChatRepository { services.repository }
    private var chat: ChatState { repo.state }

    @State private var input = ""

    private var placeholder: String {
        if chat.awaitingLoginUsername { return L10n.tr("feedback_admin_user") }
        if chat.awaitingLoginPassword { return L10n.tr("feedback_admin_password") }
        return L10n.tr("console_placeholder")
    }

    var body: some View {
        ScrollView {
            VStack(alignment: .leading, spacing: 12) {
                Text(L10n.tr("console_title"))
                    .font(.title2.weight(.bold))

                TextField(placeholder, text: $input)
                    .textFieldStyle(.roundedBorder)

                Button(L10n.tr("console_send")) {
                    repo.sendMessage(text: input)
                    input = ""
                }
                .buttonStyle(.borderedProminent)
                .tint(YpChatTheme.primary600)
                .disabled(input.isEmpty)

                if chat.commandLines.isEmpty, chat.commandTable == nil {
                    Text(L10n.tr("console_empty"))
                        .foregroundStyle(YpChatTheme.textMuted)
                }

                ForEach(Array(chat.commandLines.enumerated()), id: \.offset) { _, line in
                    consoleLineCard(line: localizeRuntimeMessage(line), kind: chat.commandKind)
                }

                if let table = chat.commandTable {
                    commandTableCard(table)
                }
            }
            .padding(16)
        }
    }

    private func consoleLineCard(line: String, kind: String?) -> some View {
        let k = kind ?? ""
        let bg: Color = {
            if k.hasPrefix("login") { return YpChatTheme.surfaceSoftBlue }
            if k == "info" { return YpChatTheme.surfaceSoftGreen }
            if k == "error" { return YpChatTheme.surfaceSoftRed }
            return YpChatTheme.surfaceSubtle
        }()
        let border: Color = {
            if k.hasPrefix("login") { return Color(red: 0.79, green: 0.86, blue: 0.93) }
            if k == "info" { return Color(red: 0.81, green: 0.89, blue: 0.83) }
            if k == "error" { return Color(red: 0.94, green: 0.79, blue: 0.79) }
            return YpChatTheme.border
        }()
        let fg = k == "error" ? YpChatTheme.danger : YpChatTheme.textStrong
        return Text(line)
            .font(.body)
            .foregroundStyle(fg)
            .padding(14)
            .frame(maxWidth: .infinity, alignment: .leading)
            .background(bg, in: RoundedRectangle(cornerRadius: 12))
            .overlay(RoundedRectangle(cornerRadius: 12).stroke(border, lineWidth: 1))
    }

    private func commandTableCard(_ table: CommandTableState) -> some View {
        VStack(alignment: .leading, spacing: 10) {
            Text(table.title).fontWeight(.bold).foregroundStyle(YpChatTheme.textStrong)
            if !table.columns.isEmpty {
                HStack {
                    ForEach(table.columns, id: \.self) { col in
                        Text(col).fontWeight(.bold).foregroundStyle(YpChatTheme.primary700)
                        Spacer(minLength: 8)
                    }
                }
                .padding(.horizontal, 10)
                .padding(.vertical, 8)
                .background(YpChatTheme.primary100, in: RoundedRectangle(cornerRadius: 12))
            }
            ForEach(Array(table.rows.enumerated()), id: \.offset) { _, row in
                HStack {
                    ForEach(Array(row.enumerated()), id: \.offset) { _, cell in
                        Text(cell).foregroundStyle(YpChatTheme.textMuted)
                        Spacer(minLength: 8)
                    }
                }
                .padding(.horizontal, 10)
                .padding(.vertical, 8)
                .background(YpChatTheme.surfaceSubtle, in: RoundedRectangle(cornerRadius: 12))
            }
        }
        .padding(16)
        .frame(maxWidth: .infinity, alignment: .leading)
        .background(YpChatTheme.surface, in: RoundedRectangle(cornerRadius: 12))
        .overlay(RoundedRectangle(cornerRadius: 12).stroke(YpChatTheme.border, lineWidth: 1))
    }
}

// MARK: - More

struct MoreTabView: View {
    @Binding var section: MoreSection

    var body: some View {
        Group {
            switch section {
            case .overview:
                moreOverview
            case .feedback:
                FeedbackDetailView { section = .overview }
            case .partners:
                PartnersDetailView { section = .overview }
            case .faq:
                staticContent(title: L10n.tr("faq_title"), body: L10n.tr("faq_body")) { section = .overview }
            case .rules:
                staticContent(title: L10n.tr("rules_title"), body: L10n.tr("rules_body")) { section = .overview }
            case .safety:
                staticContent(title: L10n.tr("safety_title"), body: L10n.tr("safety_body")) { section = .overview }
            case .imprint:
                staticContent(title: L10n.tr("imprint_title"), body: L10n.tr("imprint_body")) { section = .overview }
            }
        }
    }

    private var moreOverview: some View {
        ScrollView {
            VStack(alignment: .leading, spacing: 12) {
                Text(L10n.tr("more_title"))
                    .font(.title2.weight(.bold))
                moreLink(L10n.tr("more_feedback"), L10n.tr("feedback_comment")) { section = .feedback }
                moreLink(L10n.tr("more_partners"), L10n.tr("partners_intro")) { section = .partners }
                moreLink(L10n.tr("more_faq"), L10n.tr("faq_intro")) { section = .faq }
                moreLink(L10n.tr("more_rules"), L10n.tr("rules_intro")) { section = .rules }
                moreLink(L10n.tr("more_safety"), L10n.tr("safety_intro")) { section = .safety }
                moreLink(L10n.tr("more_imprint"), L10n.tr("imprint_intro")) { section = .imprint }
            }
            .padding(16)
        }
    }

    private func moreLink(_ title: String, _ subtitle: String, action: @escaping () -> Void) -> some View {
        Button(action: action) {
            VStack(alignment: .leading, spacing: 6) {
                Text(title).fontWeight(.semibold).foregroundStyle(YpChatTheme.textStrong)
                Text(subtitle).font(.subheadline).foregroundStyle(YpChatTheme.textMuted)
            }
            .padding(16)
            .frame(maxWidth: .infinity, alignment: .leading)
            .background(YpChatTheme.surface, in: RoundedRectangle(cornerRadius: 12))
        }
        .buttonStyle(.plain)
    }

    private func staticContent(title: String, body: String, onBack: @escaping () -> Void) -> some View {
        ScrollView {
            VStack(alignment: .leading, spacing: 12) {
                HStack {
                    Button(L10n.tr("more_back"), action: onBack)
                        .foregroundStyle(YpChatTheme.primary700)
                    Text(title)
                        .font(.title2.weight(.bold))
                }
                Text(body).foregroundStyle(YpChatTheme.textStrong)
            }
            .padding(16)
        }
    }
}

struct FeedbackDetailView: View {
    @EnvironmentObject private var services: AppServices
    var onBack: () -> Void

    private var repo: ChatRepository { services.repository }
    private var chat: ChatState { repo.state }

    @State private var comment = ""
    @State private var adminUser = ""
    @State private var adminPassword = ""

    var body: some View {
        ScrollView {
            VStack(alignment: .leading, spacing: 12) {
                HStack {
                    Button(L10n.tr("more_back"), action: onBack)
                        .foregroundStyle(YpChatTheme.primary700)
                    Text(L10n.tr("feedback_title"))
                        .font(.title2.weight(.bold))
                }

                TextField(L10n.tr("feedback_comment"), text: $comment, axis: .vertical)
                    .lineLimit(4 ... 8)
                    .textFieldStyle(.roundedBorder)

                Button(L10n.tr("feedback_send")) {
                    Task {
                        await repo.submitFeedback(comment: comment)
                        comment = ""
                    }
                }
                .buttonStyle(.borderedProminent)
                .tint(YpChatTheme.primary600)
                .disabled(comment.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty)

                if let fm = chat.feedbackMessage {
                    Text(localizeRuntimeMessage(fm))
                        .font(.footnote)
                        .foregroundStyle(YpChatTheme.textMuted)
                }

                VStack(alignment: .leading, spacing: 8) {
                    if chat.feedbackAdminAuthenticated {
                        Text("\(L10n.tr("feedback_admin_user")): \(chat.feedbackAdminUserName ?? "")")
                            .fontWeight(.semibold)
                        Button(L10n.tr("feedback_admin_logout")) {
                            Task { await repo.logoutFeedbackAdmin() }
                        }
                        .buttonStyle(.bordered)
                        .tint(YpChatTheme.primary500)
                    } else {
                        TextField(L10n.tr("feedback_admin_user"), text: $adminUser)
                            .textFieldStyle(.roundedBorder)
                        SecureField(L10n.tr("feedback_admin_password"), text: $adminPassword)
                            .textFieldStyle(.roundedBorder)
                        Button(L10n.tr("feedback_admin_login")) {
                            Task {
                                await repo.loginFeedbackAdmin(username: adminUser, password: adminPassword)
                            }
                        }
                        .buttonStyle(.bordered)
                        .tint(YpChatTheme.primary500)
                    }
                    if let err = chat.feedbackAdminError {
                        Text(localizeRuntimeMessage(err))
                            .foregroundStyle(YpChatTheme.danger)
                            .font(.footnote)
                    }
                }
                .padding(16)
                .frame(maxWidth: .infinity, alignment: .leading)
                .background(YpChatTheme.surfaceSubtle, in: RoundedRectangle(cornerRadius: 12))

                if chat.feedbackItems.isEmpty {
                    Text(L10n.tr("feedback_empty"))
                        .foregroundStyle(YpChatTheme.textMuted)
                }
                ForEach(Array(chat.feedbackItems.enumerated()), id: \.offset) { _, item in
                    feedbackRow(item)
                }
            }
            .padding(16)
        }
    }

    private func feedbackRow(_ item: FeedbackItemDto) -> some View {
        VStack(alignment: .leading, spacing: 6) {
            HStack {
                Text(item.name.flatMap { $0.isEmpty ? nil : $0 } ?? L10n.tr("anonymous"))
                    .fontWeight(.semibold)
                Spacer()
                if chat.feedbackAdminAuthenticated {
                    Button(L10n.tr("feedback_delete"), role: .destructive) {
                        Task { await repo.deleteFeedback(id: item.id) }
                    }
                    .font(.caption)
                }
            }
            Text(item.comment).foregroundStyle(YpChatTheme.textStrong)
            let meta = [item.country, item.gender, item.age.map { String($0) }]
                .compactMap { $0 }
                .filter { !$0.isEmpty }
            if !meta.isEmpty {
                Text(meta.joined(separator: L10n.tr("feedback_meta_separator")))
                    .font(.caption)
                    .foregroundStyle(YpChatTheme.textMuted)
            }
            if let ts = formatFeedbackTimestamp(item.createdAt) {
                Text(L10n.feedbackCreatedAt(ts))
                    .font(.caption2)
                    .foregroundStyle(YpChatTheme.textMuted)
            }
        }
        .padding(16)
        .frame(maxWidth: .infinity, alignment: .leading)
        .background(YpChatTheme.surface, in: RoundedRectangle(cornerRadius: 12))
    }
}

struct PartnersDetailView: View {
    @EnvironmentObject private var services: AppServices
    var onBack: () -> Void
    @Environment(\.openURL) private var openURL

    private var chat: ChatState { services.repository.state }

    var body: some View {
        ScrollView {
            VStack(alignment: .leading, spacing: 12) {
                HStack {
                    Button(L10n.tr("more_back"), action: onBack)
                        .foregroundStyle(YpChatTheme.primary700)
                    Text(L10n.tr("partners_title"))
                        .font(.title2.weight(.bold))
                }
                Text(L10n.tr("partners_intro"))
                    .foregroundStyle(YpChatTheme.textMuted)
                if let err = chat.partnersError {
                    Text(localizeRuntimeMessage(err))
                        .foregroundStyle(YpChatTheme.danger)
                }
                ForEach(Array(chat.partnerLinks.enumerated()), id: \.offset) { _, link in
                    Button {
                        if let u = URL(string: link.url) { openURL(u) }
                    } label: {
                        VStack(alignment: .leading, spacing: 4) {
                            Text(link.pageName).fontWeight(.semibold)
                            Text(link.url).foregroundStyle(YpChatTheme.primary700)
                            Text(L10n.tr("external_link"))
                                .font(.caption)
                                .foregroundStyle(YpChatTheme.textMuted)
                        }
                        .padding(16)
                        .frame(maxWidth: .infinity, alignment: .leading)
                        .background(YpChatTheme.surface, in: RoundedRectangle(cornerRadius: 12))
                    }
                    .buttonStyle(.plain)
                }
            }
            .padding(16)
        }
    }
}

// MARK: - Chat

struct YpChatConversationView: View {
    @EnvironmentObject private var services: AppServices
    private var repo: ChatRepository { services.repository }
    private var chat: ChatState { repo.state }

    @State private var draft = ""
    @State private var showSmileys = false
    @State private var photoItem: PhotosPickerItem?

    private static let maxImageBytes = 5 * 1024 * 1024

    var body: some View {
        VStack(spacing: 0) {
            HStack {
                Button(L10n.tr("back")) { repo.closeConversation() }
                Text(chat.currentConversation ?? "")
                    .fontWeight(.bold)
                    .frame(maxWidth: .infinity)
                Button(L10n.tr("block")) {
                    if let u = chat.currentConversation { repo.blockUser(userName: u) }
                }
                Button(L10n.tr("unblock")) {
                    if let u = chat.currentConversation { repo.unblockUser(userName: u) }
                }
            }
            .padding(12)
            Divider()
            ScrollView {
                LazyVStack(alignment: .leading, spacing: 8) {
                    ForEach(Array(chat.messages.enumerated()), id: \.offset) { _, message in
                        messageBubble(message)
                    }
                }
                .padding(12)
            }
            if chat.isUploadingImage || chat.imageUploadMessage != nil {
                uploadBanner
            }
            HStack(alignment: .bottom) {
                TextField(L10n.tr("message_placeholder"), text: $draft, axis: .vertical)
                    .lineLimit(1 ... 4)
                    .textFieldStyle(.roundedBorder)
                    .disabled(chat.isUploadingImage)
                Button {
                    showSmileys.toggle()
                } label: {
                    Image(systemName: "face.smiling")
                }
                .disabled(chat.isUploadingImage)
                PhotosPicker(selection: $photoItem, matching: .images) {
                    Image(systemName: "photo")
                }
                .disabled(chat.isUploadingImage)
                Button(L10n.tr("button_send")) {
                    repo.sendMessage(text: draft)
                    draft = ""
                }
                .buttonStyle(.borderedProminent)
                .tint(YpChatTheme.primary600)
                .disabled(draft.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty || chat.isUploadingImage)
            }
            .padding(12)
            if showSmileys {
                ScrollView(.horizontal, showsIndicators: false) {
                    HStack(spacing: 8) {
                        ForEach(ypChatSmileys) { sm in
                            Button {
                                draft += sm.token
                                showSmileys = false
                            } label: {
                                Text(smileyEmoji(hexCode: sm.hexCode))
                                    .padding(.horizontal, 12)
                                    .padding(.vertical, 8)
                                    .background(YpChatTheme.primary100, in: Capsule())
                                    .foregroundStyle(YpChatTheme.primary700)
                                    .fontWeight(.bold)
                            }
                        }
                    }
                    .padding(.horizontal, 12)
                }
            }
            if let err = chat.errorMessage {
                Text(localizeRuntimeMessage(err))
                    .font(.footnote)
                    .foregroundStyle(YpChatTheme.danger)
                    .padding(.horizontal, 12)
            }
        }
        .onChange(of: photoItem) { _, new in
            Task { await handlePhoto(new) }
        }
    }

    private var uploadBanner: some View {
        let msg: String = {
            if chat.isUploadingImage { return L10n.tr("image_upload_in_progress") }
            return localizeRuntimeMessage(chat.imageUploadMessage ?? "")
        }()
        let ok = chat.imageUploadMessage == "Image uploaded"
        let bg: Color = chat.isUploadingImage ? YpChatTheme.surfaceSoftBlue : (ok ? YpChatTheme.surfaceSoftGreen : YpChatTheme.surfaceSoftRed)
        let fg: Color = chat.isUploadingImage || ok ? YpChatTheme.primary700 : YpChatTheme.danger
        return Text(msg)
            .font(.subheadline)
            .foregroundStyle(fg)
            .padding(.horizontal, 14)
            .padding(.vertical, 10)
            .frame(maxWidth: .infinity, alignment: .leading)
            .background(bg)
            .padding(.horizontal, 12)
    }

    @ViewBuilder
    private func messageBubble(_ message: ChatMessageDto) -> some View {
        let selfMsg = message.from == (chat.currentUser?.userName ?? "")
        HStack {
            if selfMsg { Spacer(minLength: 40) }
            VStack(alignment: selfMsg ? .trailing : .leading) {
                if message.isImage, let urlStr = message.imageUrl, let url = URL(string: urlStr) {
                    AsyncImage(url: url) { phase in
                        switch phase {
                        case .success(let img):
                            img.resizable().scaledToFit().frame(maxHeight: 220)
                        case .failure:
                            Text(L10n.tr("image_message")).foregroundStyle(YpChatTheme.textMuted)
                        case .empty:
                            ProgressView()
                        @unknown default:
                            EmptyView()
                        }
                    }
                } else {
                    Text(message.message)
                }
            }
            .padding(12)
            .background(selfMsg ? YpChatTheme.bubbleSelf : YpChatTheme.surfaceSubtle, in: RoundedRectangle(cornerRadius: 18))
            if !selfMsg { Spacer(minLength: 40) }
        }
    }

    private func handlePhoto(_ item: PhotosPickerItem?) async {
        guard let item, let partner = chat.currentConversation else { return }
        repo.setImageUploadState(inProgress: true, message: nil)
        guard let data = try? await item.loadTransferable(type: Data.self) else {
            repo.setImageUploadState(inProgress: false, message: "Image could not be opened")
            photoItem = nil
            return
        }
        guard data.count <= Self.maxImageBytes else {
            repo.setImageUploadState(inProgress: false, message: "Image exceeds 5 MB")
            photoItem = nil
            return
        }
        do {
            let response = try await repo.uploadImage(data: data, fileName: "ypchat-image.jpg", mimeType: "image/jpeg")
            if response.success, let code = response.code, let url = response.url, !code.isEmpty {
                repo.sendImage(toUserName: partner, imageCode: code, imageUrl: url)
                repo.setImageUploadState(inProgress: false, message: "Image uploaded")
            } else {
                repo.setImageUploadState(inProgress: false, message: response.error ?? "Image upload failed")
            }
        } catch {
            repo.setImageUploadState(inProgress: false, message: error.localizedDescription)
        }
        photoItem = nil
    }
}
