import DesignSystem
import EmojiText
import Env
import Models
import NukeUI
import Shimmer
import SwiftUI

struct AccountDetailHeaderView: View {
  enum Constants {
    static let headerHeight: CGFloat = 200
  }

  @EnvironmentObject private var theme: Theme
  @EnvironmentObject private var quickLook: QuickLook
  @EnvironmentObject private var routerPath: RouterPath
  @EnvironmentObject private var currentAccount: CurrentAccount
  @Environment(\.redactionReasons) private var reasons

  @ObservedObject var viewModel: AccountDetailViewModel
  let account: Account
  let scrollViewProxy: ScrollViewProxy?

  var body: some View {
    VStack(alignment: .leading) {
      Rectangle()
        .frame(height: Constants.headerHeight)
        .overlay {
          headerImageView
        }
      accountInfoView
    }
  }

  private var headerImageView: some View {
    ZStack(alignment: .bottomTrailing) {
      if reasons.contains(.placeholder) {
        Rectangle()
          .foregroundColor(theme.secondaryBackgroundColor)
          .frame(height: Constants.headerHeight)
      } else {
        LazyImage(url: account.header) { state in
          if let image = state.image {
            image
              .resizable()
              .aspectRatio(contentMode: .fill)
              .overlay(account.haveHeader ? .black.opacity(0.50) : .clear)
              .frame(height: Constants.headerHeight)
              .clipped()
          } else if state.isLoading {
            theme.secondaryBackgroundColor
              .frame(height: Constants.headerHeight)
              .shimmering()
          } else {
            theme.secondaryBackgroundColor
              .frame(height: Constants.headerHeight)
          }
        }
        .frame(height: Constants.headerHeight)
      }

      if viewModel.relationship?.followedBy == true {
        Text("account.relation.follows-you")
          .font(.scaledFootnote)
          .fontWeight(.semibold)
          .padding(4)
          .background(.ultraThinMaterial)
          .cornerRadius(4)
          .padding(8)
      }
    }
    .background(theme.secondaryBackgroundColor)
    .frame(height: Constants.headerHeight)
    .contentShape(Rectangle())
    .onTapGesture {
      guard account.haveHeader else {
        return
      }
      Task {
        await quickLook.prepareFor(urls: [account.header], selectedURL: account.header)
      }
    }
  }

  private var accountAvatarView: some View {
    HStack {
      AvatarView(url: account.avatar, size: .account)
        .onTapGesture {
          guard account.haveAvatar else {
            return
          }
          Task {
            await quickLook.prepareFor(urls: [account.avatar], selectedURL: account.avatar)
          }
        }
      Spacer()
      Group {
        Button {
          withAnimation {
            scrollViewProxy?.scrollTo("status", anchor: .top)
          }
        } label: {
          makeCustomInfoLabel(title: "account.posts", count: account.statusesCount)
        }
        .buttonStyle(.borderless)

        Button {
          routerPath.navigate(to: .following(id: account.id))
        } label: {
          makeCustomInfoLabel(title: "account.following", count: account.followingCount)
        }
        .buttonStyle(.borderless)

        Button {
          routerPath.navigate(to: .followers(id: account.id))
        } label: {
          makeCustomInfoLabel(
            title: "account.followers",
            count: account.followersCount,
            needsBadge: currentAccount.account?.id == account.id && !currentAccount.followRequests.isEmpty
          )
        }
        .buttonStyle(.borderless)

      }.offset(y: 20)
    }
  }

  private var accountInfoView: some View {
    Group {
      accountAvatarView
      HStack(alignment: .firstTextBaseline) {
        VStack(alignment: .leading, spacing: 0) {
          EmojiTextApp(.init(stringValue: account.safeDisplayName), emojis: account.emojis)
            .font(.scaledHeadline)
          Text("@\(account.acct)")
            .font(.scaledCallout)
            .foregroundColor(.gray)
          joinedAtView
        }
        Spacer()
        if let relationship = viewModel.relationship, !viewModel.isCurrentUser {
          HStack {
            FollowButton(viewModel: .init(accountId: account.id,
                                          relationship: relationship,
                                          shouldDisplayNotify: true,
                                          relationshipUpdated: { relationship in
                                            viewModel.relationship = relationship
                                          }))
          }
        }
      }
      
      if let note = viewModel.relationship?.note, !note.isEmpty,
          !viewModel.isCurrentUser {
        makeNoteView(note)
      }

      EmojiTextApp(account.note, emojis: account.emojis)
        .font(.scaledBody)
        .padding(.top, 8)
        .environment(\.openURL, OpenURLAction { url in
          routerPath.handle(url: url)
        })
      
      fieldsView
    }
    .padding(.horizontal, .layoutPadding)
    .offset(y: -40)
  }

  private func makeCustomInfoLabel(title: LocalizedStringKey, count: Int, needsBadge: Bool = false) -> some View {
    VStack {
      Text("\(count)")
        .font(.scaledHeadline)
        .foregroundColor(theme.tintColor)
        .overlay(alignment: .trailing) {
          if needsBadge {
            Circle()
              .fill(Color.red)
              .frame(width: 9, height: 9)
              .offset(x: 12)
          }
        }
      Text(title)
        .font(.scaledFootnote)
        .foregroundColor(.gray)
    }
  }

  @ViewBuilder
  private var joinedAtView: some View {
    if let joinedAt = viewModel.account?.createdAt.asDate {
      HStack(spacing: 4) {
        Image(systemName: "calendar")
        Text("account.joined")
        Text(joinedAt, style: .date)
      }
      .foregroundColor(.gray)
      .font(.footnote)
      .padding(.top, 6)
    }
  }
  
  @ViewBuilder
  private func makeNoteView(_ note: String) -> some View {
    VStack(alignment: .leading, spacing: 4) {
      Text("account.relation.note.label")
        .foregroundColor(.gray)
      Text(note)
        .frame(maxWidth: .infinity, alignment: .leading)
        .padding(8)
        .background(theme.secondaryBackgroundColor)
        .cornerRadius(4)
        .overlay(
          RoundedRectangle(cornerRadius: 4)
            .stroke(.gray.opacity(0.35), lineWidth: 1)
        )
    }
  }
  
  @ViewBuilder
  private var fieldsView: some View {
    if !viewModel.fields.isEmpty {
      VStack(alignment: .leading) {
        ForEach(viewModel.fields) { field in
          HStack {
            VStack(alignment: .leading, spacing: 2) {
              Text(field.name)
                .font(.scaledHeadline)
              HStack {
                if field.verifiedAt != nil {
                  Image(systemName: "checkmark.seal")
                    .foregroundColor(Color.green.opacity(0.80))
                }
                EmojiTextApp(field.value, emojis: viewModel.account?.emojis ?? [])
                  .foregroundColor(theme.tintColor)
                  .environment(\.openURL, OpenURLAction { url in
                    routerPath.handle(url: url)
                  })
              }
              .font(.scaledBody)
              if viewModel.fields.last != field {
                Divider()
                  .padding(.vertical, 4)
              }
            }
            Spacer()
          }
        }
      }
      .padding(8)
      .background(theme.secondaryBackgroundColor)
      .cornerRadius(4)
      .overlay(
        RoundedRectangle(cornerRadius: 4)
          .stroke(.gray.opacity(0.35), lineWidth: 1)
      )
    }
  }
}

struct AccountDetailHeaderView_Previews: PreviewProvider {
  static var previews: some View {
    AccountDetailHeaderView(viewModel: .init(account: .placeholder()),
                            account: .placeholder(),
                            scrollViewProxy: nil)
  }
}
