import SwiftUI
import Foundation

struct ContactsTab: View {
    @State private var contacts: [Contact] = []
    @State private var isLoading = false
    @State private var loadError: String?
    @State private var pagingError: String?
    @State private var activeAlert: ContactsAlert?
    @State private var hasMore = true
    @State private var offset = 0

    private let contactsService = ContactsService()
    private let pageSize = 25

    var body: some View {
        List {
            if isLoading && contacts.isEmpty {
                loadingState
            }
            
            if let loadError, contacts.isEmpty {
                errorState(loadError)
            } else if contacts.isEmpty {
                emptyState
            } else {
                ForEach(Array(contacts.enumerated()), id: \.element.id) { index, contact in
                    Button {
                        showContactPlaceholder(for: contact)
                    } label: {
                        ContactRow(contact: contact)
                            .contentShape(Rectangle())
                    }
                    .buttonStyle(.plain)
//                    .disabled(contact.isDeleted)
                    .contextMenu {
                        Button {
                            handleContactAction(.edit, for: contact)
                        } label: {
                            Label(
                                NSLocalizedString("Изменить контакт", comment: "Contacts context action edit"),
                                systemImage: "square.and.pencil"
                            )
                        }
//                        .disabled(contact.isDeleted)

                        Button {
                            handleContactAction(.block, for: contact)
                        } label: {
                            Label(
                                NSLocalizedString("Заблокировать контакт", comment: "Contacts context action block"),
                                systemImage: "hand.raised.fill"
                            )
                        }
//                        .disabled(contact.isDeleted)

                        Button(role: .destructive) {
                            handleContactAction(.delete, for: contact)
                        } label: {
                            Label(
                                NSLocalizedString("Удалить контакт", comment: "Contacts context action delete"),
                                systemImage: "trash"
                            )
                        }
//                        .disabled(contact.isDeleted)
                    }
                    .listRowInsets(EdgeInsets(top: 0, leading: 12, bottom: 0, trailing: 12))
                    .onAppear {
                        if index >= contacts.count - 5 {
                            Task {
                                await loadContacts(reset: false)
                            }
                        }
                    }
                }

                if isLoading && !contacts.isEmpty {
                    loadingState
                } else if let pagingError, !contacts.isEmpty {
                    pagingErrorState(pagingError)
                }
            }
        }
        .background(Color(UIColor.systemBackground))
        .listStyle(.plain)
        .task {
            await loadContacts(reset: false)
        }
        .refreshable {
            await refreshContacts()
        }
        .alert(item: $activeAlert) { alert in
            switch alert {
            case .error(_, let message):
                return Alert(
                    title: Text(NSLocalizedString("Ошибка", comment: "Contacts load error title")),
                    message: Text(message),
                    dismissButton: .default(Text(NSLocalizedString("OK", comment: "Common OK")))
                )
            case .info(_, let title, let message):
                return Alert(
                    title: Text(title),
                    message: Text(message),
                    dismissButton: .default(Text(NSLocalizedString("OK", comment: "Common OK")))
                )
            }
        }
    }

    private var loadingState: some View {
        HStack {
            Spacer()
            ProgressView()
                .progressViewStyle(CircularProgressViewStyle())
            Spacer()
        }
        .padding(.vertical, 18)
        .listRowInsets(EdgeInsets(top: 18, leading: 12, bottom: 18, trailing: 12))
        .listRowSeparator(.hidden)
    }

    private func errorState(_ message: String) -> some View {
        HStack(alignment: .center, spacing: 8) {
            Image(systemName: "exclamationmark.triangle.fill")
                .foregroundColor(.orange)
            Text(message)
                .font(.subheadline)
                .foregroundColor(.orange)
            Spacer()
            Button(action: { Task { await refreshContacts() } }) {
                Text(NSLocalizedString("Обновить", comment: "Contacts retry button"))
                    .font(.subheadline)
            }
        }
        .padding(.vertical, 10)
        .listRowInsets(EdgeInsets(top: 10, leading: 12, bottom: 10, trailing: 12))
        .listRowSeparator(.hidden)
    }

    private func pagingErrorState(_ message: String) -> some View {
        HStack(alignment: .center, spacing: 8) {
            Image(systemName: "exclamationmark.triangle.fill")
                .foregroundColor(.orange)
            Text(message)
                .font(.subheadline)
                .foregroundColor(.orange)
            Spacer()
            Button(action: { Task { await loadContacts(reset: false) } }) {
                Text(NSLocalizedString("Обновить", comment: "Contacts retry button"))
                    .font(.subheadline)
            }
        }
        .padding(.vertical, 10)
        .listRowInsets(EdgeInsets(top: 10, leading: 12, bottom: 10, trailing: 12))
        .listRowSeparator(.hidden)
    }

    private var emptyState: some View {
        VStack(spacing: 12) {
            Image(systemName: "person.crop.circle.badge.questionmark")
                .font(.system(size: 52))
                .foregroundColor(.secondary)
            Text(NSLocalizedString("Контактов пока нет", comment: "Contacts empty state title"))
                .font(.headline)
                .multilineTextAlignment(.center)
            Text(NSLocalizedString("Добавьте контакты, чтобы быстрее выходить на связь.", comment: "Contacts empty state subtitle"))
                .font(.subheadline)
                .foregroundColor(.secondary)
                .multilineTextAlignment(.center)
        }
        .frame(maxWidth: .infinity)
        .padding(.vertical, 28)
        .listRowInsets(EdgeInsets(top: 20, leading: 12, bottom: 20, trailing: 12))
        .listRowSeparator(.hidden)
    }

    @MainActor
    private func refreshContacts() async {
        hasMore = true
        offset = 0
        pagingError = nil
        loadError = nil
        contacts.removeAll()
        await loadContacts(reset: true)
    }

    @MainActor
    private func loadContacts(reset: Bool) async {
        if isLoading { return }
        if !reset && !hasMore { return }

        isLoading = true
        if offset == 0 {
            loadError = nil
        }
        pagingError = nil

        do {
            let payload = try await contactsService.fetchContacts(limit: pageSize, offset: offset)
            let newContacts = payload.items.map(Contact.init)
            if reset {
                contacts = newContacts
            } else {
                contacts.append(contentsOf: newContacts)
            }
            offset += newContacts.count
            hasMore = payload.hasMore
        } catch {
            let message = error.localizedDescription
            if contacts.isEmpty {
                loadError = message
            } else {
                pagingError = message
            }
            if AppConfig.DEBUG { print("[ContactsTab] load contacts failed: \(error)") }
        }

        isLoading = false
    }

    private func showContactPlaceholder(for contact: Contact) {
        activeAlert = .info(
            title: NSLocalizedString("Скоро", comment: "Contacts placeholder title"),
            message: String(
                format: NSLocalizedString("Просмотр \"%1$@\" появится позже.", comment: "Contacts placeholder message"),
                contact.displayName
            )
        )
    }

    private func handleContactAction(_ action: ContactAction, for contact: Contact) {
        activeAlert = .info(
            title: NSLocalizedString("Скоро", comment: "Contacts placeholder title"),
            message: action.placeholderMessage(for: contact)
        )
    }
}

private struct ContactRow: View {
    let contact: Contact

    var body: some View {
        HStack(alignment: .top, spacing: 10) {
            Circle()
                .fill(contact.isDeleted ? Color(.systemGray5) : Color.accentColor.opacity(0.15))
                .frame(width: 40, height: 40)
                .overlay(
                    Group {
                        if contact.isDeleted {
                            Image(systemName: "person.slash")
                                .font(.headline)
                                .foregroundColor(Color(.systemGray2))
                        } else {
                            Text(contact.initials)
                                .font(.headline)
                                .foregroundColor(.accentColor)
                        }
                    }
                )

            VStack(alignment: .leading, spacing: 3) {
                HStack(alignment: .firstTextBaseline) {
                    if #available(iOS 16.0, *) {
                        Text(contact.displayName)
                            .font(.subheadline.weight(.semibold))
                            .foregroundColor(.primary)
                            .strikethrough(contact.isDeleted, color: .secondary)
                    } else {
                        Text(contact.displayName)
                            .font(.subheadline.weight(.semibold))
                            .foregroundColor(.primary)
                            .strikethrough(contact.isDeleted)
                    }
                    Spacer()
                    Text(contact.formattedCreatedAt)
                        .font(.caption2)
                        .foregroundColor(.secondary)
                }

                if let handle = contact.handle {
                    Text(handle)
                        .font(.caption2)
                        .foregroundColor(.secondary)
                }

                if contact.friendCode {
                    friendCodeBadge
                }
            }
            .frame(maxWidth: .infinity, alignment: .leading)
        }
        .padding(.vertical, 6)
    }

    private var friendCodeBadge: some View {
        Text(NSLocalizedString("Код дружбы", comment: "Friend code badge"))
            .font(.caption2.weight(.medium))
            .foregroundColor(Color.accentColor)
            .padding(.horizontal, 6)
            .padding(.vertical, 3)
            .background(Color.accentColor.opacity(0.12))
            .clipShape(Capsule())
    }
}

private struct Contact: Identifiable, Equatable {
    let id: UUID
    let login: String?
    let fullName: String?
    let customName: String?
    let friendCode: Bool
    let createdAt: Date

    let displayName: String
    let handle: String?

    var isDeleted: Bool {
        login?.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty ?? true
    }

    var initials: String {
        if isDeleted { return "" }

        let nameSource: String?
        if let customName, !customName.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
            nameSource = customName
        } else if let fullName, !fullName.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
            nameSource = fullName
        } else {
            nameSource = nil
        }

        if let name = nameSource {
            let components = name.split(separator: " ")
            let nameInitials = components.prefix(2).compactMap { $0.first }
            if !nameInitials.isEmpty {
                return nameInitials.map { String($0) }.joined().uppercased()
            }
        }
        
        return String(login!.prefix(1)).uppercased()
    }

    var formattedCreatedAt: String {
        Self.relativeFormatter.localizedString(for: createdAt, relativeTo: Date())
    }

    init(payload: ContactPayload) {
        self.id = payload.userId
        self.login = payload.login
        self.fullName = payload.fullName
        self.customName = payload.customName
        self.friendCode = payload.friendCode
        self.createdAt = payload.createdAt

        let isUserDeleted = payload.login?.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty ?? true

        if isUserDeleted {
            self.displayName = NSLocalizedString("Неизвестный пользователь", comment: "Deleted user display name")
            self.handle = nil
        } else {
            if let customName = payload.customName, !customName.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
                self.displayName = customName
            } else if let fullName = payload.fullName, !fullName.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
                self.displayName = fullName
            } else {
                self.displayName = payload.login!
            }

            if let login = payload.login, !login.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
                self.handle = "@\(login)"
            } else {
                self.handle = nil
            }
        }
    }

    private static let relativeFormatter: RelativeDateTimeFormatter = {
        let formatter = RelativeDateTimeFormatter()
        formatter.unitsStyle = .short
        return formatter
    }()
}

private enum ContactsAlert: Identifiable {
    case error(id: UUID = UUID(), message: String)
    case info(id: UUID = UUID(), title: String, message: String)

    var id: String {
        switch self {
        case .error(let id, _), .info(let id, _, _):
            return id.uuidString
        }
    }
}

private enum ContactAction {
    case edit
    case block
    case delete

    func placeholderMessage(for contact: Contact) -> String {
        switch self {
        case .edit:
            return String(
                format: NSLocalizedString("Изменение контакта \"%1$@\" появится позже.", comment: "Contacts edit placeholder message"),
                contact.displayName
            )
        case .block:
            return String(
                format: NSLocalizedString("Блокировка контакта \"%1$@\" появится позже.", comment: "Contacts block placeholder message"),
                contact.displayName
            )
        case .delete:
            return String(
                format: NSLocalizedString("Удаление контакта \"%1$@\" появится позже.", comment: "Contacts delete placeholder message"),
                contact.displayName
            )
        }
    }
}
