import SwiftUI

/// Reusable "Where did you find Dayflow?" survey component.
struct ReferralSurveyView: View {
  let prompt: String
  let submitLabel: String
  let showsThankYou: Bool
  let showSubmitButton: Bool
  let onSubmit: (_ option: ReferralOption, _ detail: String?) -> Void

  @State private var internalSelectedReferral: ReferralOption? = nil
  @State private var internalCustomReferral: String = ""
  @State private var randomizedOptions = ReferralOption.randomizedConcreteOptions()
  @State private var hasSubmitted = false

  @Binding private var selectedReferral: ReferralOption?
  @Binding private var customReferral: String

  init(
    prompt: String,
    submitLabel: String = "Submit",
    showsThankYou: Bool = false,
    showSubmitButton: Bool = true,
    selectedReferral: Binding<ReferralOption?>? = nil,
    customReferral: Binding<String>? = nil,
    onSubmit: @escaping (_ option: ReferralOption, _ detail: String?) -> Void = { _, _ in }
  ) {
    self.prompt = prompt
    self.submitLabel = submitLabel
    self.showsThankYou = showsThankYou
    self.showSubmitButton = showSubmitButton
    self.onSubmit = onSubmit

    if let selectedReferral = selectedReferral, let customReferral = customReferral {
      _selectedReferral = selectedReferral
      _customReferral = customReferral
    } else {
      _selectedReferral = _internalSelectedReferral.projectedValue
      _customReferral = _internalCustomReferral.projectedValue
    }
  }

  var body: some View {
    VStack(alignment: .leading, spacing: 8) {
      Text(prompt)
        .font(.custom("Figtree", size: 15).weight(.semibold))
        .foregroundColor(.black.opacity(0.85))
        .fixedSize(horizontal: false, vertical: true)

      VStack(spacing: 10) {
        ForEach(Array(referralRows.enumerated()), id: \.offset) { _, row in
          HStack(spacing: 12) {
            ForEach(row, id: \.id) { option in
              referralOptionView(option)
            }

            if row.count == 1 {
              Spacer(minLength: 0)
            }
          }
        }
      }

      detailField

      if showsThankYou && hasSubmitted {
        Label("Thanks for letting me know!", systemImage: "checkmark.circle.fill")
          .font(.custom("Figtree", size: 14))
          .foregroundColor(Color(red: 0.25, green: 0.17, blue: 0))
          .padding(.top, 4)
      }

      if showSubmitButton {
        HStack {
          Spacer()
          DayflowSurfaceButton(
            action: handleSubmit,
            content: {
              Text(submitLabel)
                .font(.custom("Figtree", size: 16))
                .fontWeight(.semibold)
            },
            background: submitBackground,
            foreground: Color.white.opacity(canSubmit ? 1 : 0.85),
            borderColor: .clear,
            cornerRadius: 8,
            horizontalPadding: 40,
            verticalPadding: 14,
            minWidth: 200,
            showOverlayStroke: true
          )
          .disabled(!canSubmit)
          .opacity(canSubmit ? 1 : 0.85)
          .keyboardShortcut(.defaultAction)
        }
        .padding(.top, 8)
      }
    }
    .onChange(of: customReferral) {
      hasSubmitted = false
    }
  }

  private var referralRows: [[ReferralOption]] {
    (randomizedOptions + [.other]).chunked(into: 2)
  }

  var canSubmit: Bool {
    guard let option = selectedReferral else { return false }
    if option.requiresDetail {
      return !customReferral.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
    }
    return true
  }

  private var submitBackground: Color {
    canSubmit
      ? Color(red: 0.25, green: 0.17, blue: 0)
      : Color(red: 0.88, green: 0.84, blue: 0.78)
  }

  @ViewBuilder
  private func referralOptionView(_ option: ReferralOption) -> some View {
    let isSelected = selectedReferral == option

    VStack(alignment: .leading, spacing: 0) {
      Button(action: { select(option) }) {
        HStack(spacing: 8) {
          Image(systemName: isSelected ? "largecircle.fill.circle" : "circle")
            .foregroundColor(Color(red: 0.25, green: 0.17, blue: 0))

          Text(option.displayName)
            .font(.custom("Figtree", size: 14))
            .foregroundColor(.black.opacity(0.78))

          Spacer(minLength: 0)
        }
        .frame(maxWidth: .infinity, alignment: .leading)
        .padding(.vertical, 10)
        .padding(.horizontal, 12)
        .background(
          RoundedRectangle(cornerRadius: 8, style: .continuous)
            .fill(isSelected ? Color(red: 1.0, green: 0.95, blue: 0.9) : Color.white)
        )
        .overlay(
          RoundedRectangle(cornerRadius: 8, style: .continuous)
            .stroke(
              Color(red: 0.25, green: 0.17, blue: 0).opacity(isSelected ? 0.22 : 0.1), lineWidth: 1)
        )
      }
      .buttonStyle(PlainButtonStyle())
      .pointingHandCursor()
    }
    .frame(maxWidth: .infinity, alignment: .leading)
  }

  private func select(_ option: ReferralOption) {
    selectedReferral = option
    hasSubmitted = false

    if !option.requiresDetail {
      customReferral = ""
    }
  }

  private var detailField: some View {
    TextField(currentDetailPlaceholder, text: $customReferral)
      .textFieldStyle(RoundedBorderTextFieldStyle())
      .font(.custom("Figtree", size: 13))
      .opacity(selectedReferral?.requiresDetail == true ? 1 : 0)
      .disabled(selectedReferral?.requiresDetail != true)
      .allowsHitTesting(selectedReferral?.requiresDetail == true)
      .frame(height: 44)
      .frame(maxWidth: .infinity)
      .padding(.horizontal, 12)
      .padding(.top, 6)
  }

  private var currentDetailPlaceholder: String {
    selectedReferral?.detailPlaceholder ?? "Tell me more"
  }

  private func handleSubmit() {
    guard canSubmit, let option = selectedReferral else { return }
    let trimmedDetail = customReferral.trimmingCharacters(in: .whitespacesAndNewlines)
    let detailToSend = option.requiresDetail ? trimmedDetail : nil

    onSubmit(option, detailToSend?.isEmpty == false ? detailToSend : nil)
    hasSubmitted = true
  }
}

enum ReferralOption: CaseIterable, Identifiable, Hashable {
  case hackerNews
  case x
  case friend
  case youtube
  case newsletterBlog
  case chatGPTClaudeAI
  case other

  var id: String { analyticsValue }

  static func randomizedConcreteOptions() -> [ReferralOption] {
    allCases.filter { $0 != .other }.shuffled()
  }

  var displayName: String {
    switch self {
    case .hackerNews: return "Hacker News"
    case .x: return "X / Twitter"
    case .friend: return "Friend or colleague"
    case .youtube: return "YouTube"
    case .newsletterBlog: return "Newsletter or blog (which one?)"
    case .chatGPTClaudeAI: return "ChatGPT / Claude / AI"
    case .other: return "Other (please specify)"
    }
  }

  var analyticsValue: String {
    switch self {
    case .hackerNews: return "hacker_news"
    case .x: return "x"
    case .friend: return "friend"
    case .youtube: return "youtube"
    case .newsletterBlog: return "newsletter_blog"
    case .chatGPTClaudeAI: return "chatgpt_claude_ai"
    case .other: return "other"
    }
  }

  var requiresDetail: Bool {
    switch self {
    case .youtube, .newsletterBlog, .other:
      return true
    default:
      return false
    }
  }

  var detailPlaceholder: String {
    switch self {
    case .newsletterBlog:
      return "Which newsletter or blog?"
    case .youtube:
      return "Which channel?"
    case .other:
      return "Where did you hear about Dayflow?"
    default:
      return ""
    }
  }
}

extension Array {
  fileprivate func chunked(into size: Int) -> [[Element]] {
    stride(from: 0, to: count, by: size).map { startIndex in
      Array(self[startIndex..<Swift.min(startIndex + size, count)])
    }
  }
}
