import DesignSystem
import EmojiText
import Env
import Models
import Network
import Shimmer
import SwiftUI

public struct StatusRowView: View {
  @Environment(\.redactionReasons) private var reasons
  @Environment(\.isCompact) private var isCompact: Bool

  @EnvironmentObject private var theme: Theme

  @StateObject var viewModel: StatusRowViewModel

  public init(viewModel: StatusRowViewModel) {
    _viewModel = StateObject(wrappedValue: viewModel)
  }

  var contextMenu: some View {
    StatusRowContextMenu(viewModel: viewModel)
  }

  public var body: some View {
    if viewModel.isFiltered, let filter = viewModel.filter {
      switch filter.filter.filterAction {
      case .warn:
        makeFilterView(filter: filter.filter)
          .listRowBackground(viewModel.highlightRowColor)
      case .hide:
        EmptyView()
          .listRowSeparator(.hidden)
      }
    } else {
      let status: AnyStatus = viewModel.status.reblog ?? viewModel.status
      VStack(alignment: .leading) {
        if !isCompact, theme.avatarPosition == .leading {
          StatusRowReblogView(viewModel: viewModel)
          StatusRowReplyView(viewModel: viewModel)
        }
        HStack(alignment: .top, spacing: .statusColumnsSpacing) {
          if !isCompact,
             theme.avatarPosition == .leading
          {
            Button {
              viewModel.routerPath.navigate(to: .accountDetailWithAccount(account: status.account))
            } label: {
              AvatarView(url: status.account.avatar, size: .status)
            }
          }
          VStack(alignment: .leading) {
            if !isCompact, theme.avatarPosition == .top {
              StatusRowReblogView(viewModel: viewModel)
              StatusRowReplyView(viewModel: viewModel)
            }
            VStack(alignment: .leading, spacing: 8) {
              let status: AnyStatus = viewModel.status.reblog ?? viewModel.status
              if !isCompact {
                StatusRowHeaderView(status: status, viewModel: viewModel)
              }
              StatusRowContentView(status: status, viewModel: viewModel)
                .contentShape(Rectangle())
                .onTapGesture {
                  viewModel.navigateToDetail()
                }
            }
            .accessibilityElement(children: viewModel.isFocused ? .contain : .combine)
            .accessibilityAction {
              viewModel.navigateToDetail()
            }
            if viewModel.showActions, theme.statusActionsDisplay != .none {
              StatusRowActionsView(viewModel: viewModel)
                .padding(.top, 8)
                .tint(viewModel.isFocused ? theme.tintColor : .gray)
                .contentShape(Rectangle())
                .onTapGesture {
                  viewModel.navigateToDetail()
                }
            }
          }
        }
      }
      .onAppear {
        viewModel.markSeen()
        if reasons.isEmpty {
          if !isCompact, viewModel.embeddedStatus == nil {
            Task {
              await viewModel.loadEmbeddedStatus()
            }
          }
        }
      }
      .contextMenu {
        contextMenu
      }
      .swipeActions(edge: .trailing) {
        if !isCompact {
          StatusRowSwipeView(viewModel: viewModel, mode: .trailing)
        }
      }
      .swipeActions(edge: .leading) {
        if !isCompact {
          StatusRowSwipeView(viewModel: viewModel, mode: .leading)
        }
      }
      .listRowBackground(viewModel.highlightRowColor)
      .listRowInsets(.init(top: 12,
                           leading: .layoutPadding,
                           bottom: 12,
                           trailing: .layoutPadding))
      .accessibilityElement(children: viewModel.isFocused ? .contain : .combine)
      .accessibilityActions {
        if UIAccessibility.isVoiceOverRunning {
          accesibilityActions
        }
      }
      .background {
        Color.clear
          .contentShape(Rectangle())
          .onTapGesture {
            viewModel.navigateToDetail()
          }
      }
      .overlay {
        if viewModel.isLoadingRemoteContent {
          remoteContentLoadingView
        }
      }
      .alert(isPresented: $viewModel.showDeleteAlert, content: {
        Alert(
          title: Text("status.action.delete.confirm.title"),
          message: Text("status.action.delete.confirm.message"),
          primaryButton: .destructive(
            Text("status.action.delete"))
          {
            Task {
              await viewModel.delete()
            }
          },
          secondaryButton: .cancel()
        )
      })
      .alignmentGuide(.listRowSeparatorLeading) { _ in
        -100
      }
    }
  }

  @ViewBuilder
  private var accesibilityActions: some View {
    // Add the individual mentions as accessibility actions
    ForEach(viewModel.status.mentions, id: \.id) { mention in
      Button("@\(mention.username)") {
        viewModel.routerPath.navigate(to: .accountDetail(id: mention.id))
      }
    }

    Button(viewModel.displaySpoiler ? "status.show-more" : "status.show-less") {
      withAnimation {
        viewModel.displaySpoiler.toggle()
      }
    }

    Button("@\(viewModel.status.account.username)") {
      viewModel.routerPath.navigate(to: .accountDetail(id: viewModel.status.account.id))
    }

    contextMenu
  }

  private func makeFilterView(filter: Filter) -> some View {
    HStack {
      Text("status.filter.filtered-by-\(filter.title)")
      Button {
        withAnimation {
          viewModel.isFiltered = false
        }
      } label: {
        Text("status.filter.show-anyway")
      }
    }
  }

  private var remoteContentLoadingView: some View {
    ZStack(alignment: .center) {
      VStack {
        Spacer()
        HStack {
          Spacer()
          ProgressView()
          Spacer()
        }
        Spacer()
      }
    }
    .background(Color.black.opacity(0.40))
    .transition(.opacity)
  }
}
