import SwiftUI

struct ContentView: View {
    @EnvironmentObject private var model: AppModel

    var body: some View {
        ZStack {
            Group {
                if model.currentUser == nil {
                    AuthView()
                } else {
                    MainTabView()
                }
            }

            if model.isLoading {
                LoadingView()
            }
        }
        .task {
            await model.bootstrap()
        }
        .overlay(alignment: .top) {
            if let banner = model.matchBanner {
                MatchBanner(text: banner)
                    .padding(.top, 16)
                    .transition(.move(edge: .top).combined(with: .opacity))
                    .task {
                        try? await Task.sleep(for: .seconds(2.5))
                        model.dismissMatchBanner()
                    }
            }
        }
        .alert(
            "HeartMatch",
            isPresented: Binding(
                get: { model.alertMessage != nil },
                set: { _ in model.dismissAlert() }
            ),
            actions: {
                Button("OK", role: .cancel) {
                    model.dismissAlert()
                }
            },
            message: {
                Text(model.alertMessage ?? "")
            }
        )
    }
}

private struct AuthView: View {
    @EnvironmentObject private var model: AppModel

    @State private var isLoginMode = false
    @State private var name = ""
    @State private var email = ""
    @State private var password = ""
    @State private var age = "25"
    @State private var city = "Toronto"
    @State private var occupation = ""
    @State private var bio = ""
    @State private var gender = "Woman"
    @State private var interestedIn = "Men"
    @State private var prompt = "A great first date is coffee, conversation, and a walk somewhere pretty."
    @State private var interestsText = "Coffee, Travel, Music"

    var body: some View {
        NavigationStack {
            ScrollView {
                VStack(alignment: .leading, spacing: 22) {
                    header
                    modePicker
                    formCard
                    actionButton
                    quickLoginCard
                }
                .padding(20)
            }
            .background(AuthBackground())
            .navigationBarHidden(true)
        }
    }

    private var header: some View {
        VStack(alignment: .leading, spacing: 8) {
            Text("HeartMatch")
                .font(.system(size: 38, weight: .bold, design: .rounded))
                .foregroundStyle(.white)

            Text("A polished Tinder-style MVP for iPhone, built to work with your own backend.")
                .font(.subheadline)
                .foregroundStyle(.white.opacity(0.86))
        }
        .padding(.top, 24)
    }

    private var modePicker: some View {
        Picker("Mode", selection: $isLoginMode) {
            Text("Create Account").tag(false)
            Text("Login").tag(true)
        }
        .pickerStyle(.segmented)
    }

    private var formCard: some View {
        VStack(alignment: .leading, spacing: 14) {
            if !isLoginMode {
                TextField("Your name", text: $name)
                    .textContentType(.name)
                TextField("Age", text: $age)
                    .keyboardType(.numberPad)
                TextField("City", text: $city)
                TextField("Occupation", text: $occupation)
                TextField("Bio", text: $bio, axis: .vertical)
                    .lineLimit(3...5)

                Picker("Gender", selection: $gender) {
                    Text("Woman").tag("Woman")
                    Text("Man").tag("Man")
                    Text("Non-binary").tag("Non-binary")
                }

                Picker("Interested In", selection: $interestedIn) {
                    Text("Women").tag("Women")
                    Text("Men").tag("Men")
                    Text("Everyone").tag("Everyone")
                }

                TextField("Prompt", text: $prompt, axis: .vertical)
                    .lineLimit(2...4)
                TextField("Interests (comma separated)", text: $interestsText)
            }

            TextField("Email", text: $email)
                .textInputAutocapitalization(.never)
                .autocorrectionDisabled()
                .keyboardType(.emailAddress)
            SecureField("Password", text: $password)
        }
        .textFieldStyle(.roundedBorder)
        .padding(18)
        .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 28, style: .continuous))
    }

    private var actionButton: some View {
        Button(action: submit) {
            Text(isLoginMode ? "Login" : "Create Profile")
                .font(.headline)
                .foregroundStyle(.white)
                .frame(maxWidth: .infinity)
                .padding(.vertical, 16)
                .background(
                    LinearGradient(
                        colors: [Color.orange, Color.pink],
                        startPoint: .leading,
                        endPoint: .trailing
                    ),
                    in: Capsule()
                )
        }
        .buttonStyle(.plain)
    }

    private var quickLoginCard: some View {
        VStack(alignment: .leading, spacing: 8) {
            Text("Demo accounts")
                .font(.headline)
            Text("Use `mia@example.com`, `ava@example.com`, or `noah@example.com` with password `TamilLove123!`.")
                .font(.footnote)
                .foregroundStyle(.secondary)
        }
        .padding(16)
        .frame(maxWidth: .infinity, alignment: .leading)
        .background(.white.opacity(0.92), in: RoundedRectangle(cornerRadius: 20, style: .continuous))
    }

    private func submit() {
        Task {
            if isLoginMode {
                await model.login(email: email, password: password)
                return
            }

            await model.signUp(
                name: name,
                email: email,
                password: password,
                age: Int(age) ?? 25,
                city: city,
                bio: bio,
                occupation: occupation,
                gender: gender,
                interestedIn: interestedIn,
                prompt: prompt,
                interests: interestsText
                    .split(separator: ",")
                    .map { $0.trimmingCharacters(in: .whitespacesAndNewlines) }
                    .filter { !$0.isEmpty }
            )
        }
    }
}

private struct MainTabView: View {
    @EnvironmentObject private var model: AppModel

    var body: some View {
        TabView(selection: $model.selectedTab) {
            NavigationStack {
                DiscoverView()
            }
            .tabItem {
                Label("Discover", systemImage: "flame.fill")
            }
            .tag(AppModel.Tab.discover)

            NavigationStack {
                MatchesView()
            }
            .tabItem {
                Label("Matches", systemImage: "heart.fill")
            }
            .tag(AppModel.Tab.matches)

            NavigationStack {
                ChatsView()
            }
            .tabItem {
                Label("Chats", systemImage: "bubble.left.and.bubble.right.fill")
            }
            .tag(AppModel.Tab.chats)

            NavigationStack {
                ProfileView()
            }
            .tabItem {
                Label("Profile", systemImage: "person.crop.circle.fill")
            }
            .tag(AppModel.Tab.profile)
        }
        .tint(.pink)
    }
}

private struct DiscoverView: View {
    @EnvironmentObject private var model: AppModel

    var body: some View {
        ScrollView {
            VStack(spacing: 24) {
                HStack {
                    VStack(alignment: .leading, spacing: 6) {
                        Text("Discover")
                            .font(.largeTitle.bold())
                        Text("Swipe right if the vibe is good.")
                            .foregroundStyle(.secondary)
                    }

                    Spacer()

                    Button("Refresh") {
                        Task { await model.refreshAll() }
                    }
                }

                if model.discoverProfiles.isEmpty {
                    EmptyStateCard(
                        title: "You’re all caught up",
                        subtitle: "No new profiles are left in the deck. Refresh after you add more users to the server."
                    )
                } else {
                    cardStack
                    actionRow
                }
            }
            .padding(20)
        }
        .background(Color(.systemGroupedBackground))
        .navigationTitle("")
        .navigationBarTitleDisplayMode(.inline)
    }

    private var cardStack: some View {
        let deck = Array(model.discoverProfiles.prefix(3))

        return ZStack {
            ForEach(Array(deck.enumerated()), id: \.element.id) { index, user in
                DiscoverCardView(
                    user: user,
                    isTopCard: index == 0,
                    onDecision: { direction in
                        Task {
                            await model.handleSwipe(for: user, direction: direction)
                        }
                    }
                )
                .offset(y: CGFloat(index) * 10)
                .scaleEffect(1 - CGFloat(index) * 0.035)
                .zIndex(Double(deck.count - index))
            }
        }
        .frame(height: 560)
    }

    private var actionRow: some View {
        HStack(spacing: 20) {
            SwipeButton(icon: "xmark", tint: .gray) {
                guard let user = model.discoverProfiles.first else { return }
                Task { await model.handleSwipe(for: user, direction: .pass) }
            }

            SwipeButton(icon: "star.fill", tint: .blue) {
                guard let user = model.discoverProfiles.first else { return }
                Task { await model.handleSwipe(for: user, direction: .like) }
            }

            SwipeButton(icon: "heart.fill", tint: .pink) {
                guard let user = model.discoverProfiles.first else { return }
                Task { await model.handleSwipe(for: user, direction: .like) }
            }
        }
    }
}

private struct MatchesView: View {
    @EnvironmentObject private var model: AppModel

    var body: some View {
        List(model.matches) { match in
            VStack(alignment: .leading, spacing: 8) {
                Text(match.user.name)
                    .font(.headline)
                Text("\(match.user.age) • \(match.user.city)")
                    .foregroundStyle(.secondary)
                if let lastMessage = match.lastMessage {
                    Text(lastMessage)
                        .font(.subheadline)
                        .foregroundStyle(.secondary)
                } else {
                    Text("New match. Start the conversation.")
                        .font(.subheadline)
                        .foregroundStyle(.pink)
                }
            }
            .padding(.vertical, 6)
        }
        .overlay {
            if model.matches.isEmpty {
                EmptyStateCard(
                    title: "No matches yet",
                    subtitle: "Mutual likes will appear here. Use the Discover tab to start swiping."
                )
                .padding(20)
            }
        }
        .listStyle(.plain)
        .navigationTitle("Matches")
    }
}

private struct ChatsView: View {
    @EnvironmentObject private var model: AppModel

    var body: some View {
        List(model.chats) { chat in
            NavigationLink {
                ChatDetailView(matchId: chat.matchId, otherUser: chat.otherUser)
            } label: {
                VStack(alignment: .leading, spacing: 6) {
                    Text(chat.otherUser.name)
                        .font(.headline)
                    Text(chat.lastMessage?.text ?? "Say hi and break the ice.")
                        .foregroundStyle(.secondary)
                        .lineLimit(2)
                }
                .padding(.vertical, 4)
            }
        }
        .overlay {
            if model.chats.isEmpty {
                EmptyStateCard(
                    title: "Your inbox is quiet",
                    subtitle: "When a match sends a message, the conversation appears here."
                )
                .padding(20)
            }
        }
        .listStyle(.plain)
        .navigationTitle("Chats")
    }
}

private struct ChatDetailView: View {
    @EnvironmentObject private var model: AppModel

    let matchId: Int
    let otherUser: User

    @State private var draft = ""

    var body: some View {
        VStack(spacing: 0) {
            ScrollViewReader { proxy in
                ScrollView {
                    LazyVStack(spacing: 12) {
                        ForEach(model.messagesByMatch[matchId] ?? []) { message in
                            MessageBubble(
                                text: message.text,
                                isMine: message.senderId == model.currentUser?.id
                            )
                            .id(message.id)
                        }
                    }
                    .padding(16)
                }
                .background(Color(.systemGroupedBackground))
                .onChange(of: model.messagesByMatch[matchId]?.last?.id) {
                    guard let lastID = model.messagesByMatch[matchId]?.last?.id else { return }
                    withAnimation {
                        proxy.scrollTo(lastID, anchor: .bottom)
                    }
                }
            }

            HStack(spacing: 12) {
                TextField("Message \(otherUser.name)", text: $draft, axis: .vertical)
                    .textFieldStyle(.roundedBorder)

                Button("Send") {
                    let text = draft
                    draft = ""
                    Task { await model.sendMessage(matchId: matchId, text: text) }
                }
                .buttonStyle(.borderedProminent)
                .tint(.pink)
            }
            .padding(16)
            .background(.thinMaterial)
        }
        .navigationTitle(otherUser.name)
        .navigationBarTitleDisplayMode(.inline)
        .task {
            await model.loadMessages(matchId: matchId)
        }
    }
}

private struct ProfileView: View {
    @EnvironmentObject private var model: AppModel

    @State private var name = ""
    @State private var age = ""
    @State private var city = ""
    @State private var occupation = ""
    @State private var bio = ""
    @State private var gender = ""
    @State private var interestedIn = ""
    @State private var prompt = ""
    @State private var interestsText = ""
    @State private var photosText = ""

    var body: some View {
        Form {
            Section("Basics") {
                TextField("Name", text: $name)
                TextField("Age", text: $age)
                    .keyboardType(.numberPad)
                TextField("City", text: $city)
                TextField("Occupation", text: $occupation)
            }

            Section("About") {
                TextField("Bio", text: $bio, axis: .vertical)
                    .lineLimit(3...6)
                TextField("Prompt", text: $prompt, axis: .vertical)
                    .lineLimit(2...5)
                TextField("Interests", text: $interestsText, prompt: Text("Coffee, Travel, Music"))
            }

            Section("Preferences") {
                TextField("Gender", text: $gender)
                TextField("Interested In", text: $interestedIn)
            }

            Section("Photos") {
                TextField("Photo URLs", text: $photosText, prompt: Text("https://... , https://..."))
                Text("For this MVP, photo storage is URL-based. You can swap this for S3 or your own uploader next.")
                    .font(.footnote)
                    .foregroundStyle(.secondary)
            }

            Section {
                Button("Save Changes") {
                    save()
                }
                .buttonStyle(.borderedProminent)
                .tint(.pink)

                Button("Logout", role: .destructive) {
                    model.logout()
                }
            }
        }
        .navigationTitle("Profile")
        .task {
            populateFields()
        }
        .onChange(of: model.currentUser?.id) {
            populateFields()
        }
    }

    private func populateFields() {
        guard let user = model.currentUser else { return }
        name = user.name
        age = String(user.age)
        city = user.city
        occupation = user.occupation
        bio = user.bio
        gender = user.gender
        interestedIn = user.interestedIn
        prompt = user.prompt
        interestsText = user.interests.joined(separator: ", ")
        photosText = user.photos.joined(separator: ", ")
    }

    private func save() {
        guard let currentUser = model.currentUser else { return }

        let updatedUser = User(
            id: currentUser.id,
            name: name,
            email: currentUser.email,
            age: Int(age) ?? currentUser.age,
            bio: bio,
            city: city,
            occupation: occupation,
            gender: gender,
            interestedIn: interestedIn,
            prompt: prompt,
            interests: interestsText
                .split(separator: ",")
                .map { $0.trimmingCharacters(in: .whitespacesAndNewlines) }
                .filter { !$0.isEmpty },
            photos: photosText
                .split(separator: ",")
                .map { $0.trimmingCharacters(in: .whitespacesAndNewlines) }
                .filter { !$0.isEmpty },
            distanceKm: currentUser.distanceKm
        )

        Task {
            await model.updateProfile(updatedUser)
        }
    }
}

private struct DiscoverCardView: View {
    let user: User
    let isTopCard: Bool
    let onDecision: (SwipeDirection) -> Void

    @State private var offset = CGSize.zero

    var body: some View {
        ZStack(alignment: .bottomLeading) {
            cardImage

            LinearGradient(
                colors: [.clear, .black.opacity(0.86)],
                startPoint: .top,
                endPoint: .bottom
            )

            VStack(alignment: .leading, spacing: 12) {
                HStack(alignment: .firstTextBaseline, spacing: 8) {
                    Text(user.name)
                        .font(.system(size: 34, weight: .bold, design: .rounded))
                    Text("\(user.age)")
                        .font(.title2.weight(.semibold))
                }
                .foregroundStyle(.white)

                Text("\(user.occupation) • \(user.city) • \(user.distanceKm) km away")
                    .font(.subheadline.weight(.medium))
                    .foregroundStyle(.white.opacity(0.88))

                Text(user.bio)
                    .font(.body)
                    .foregroundStyle(.white.opacity(0.92))

                Text(user.prompt)
                    .font(.footnote)
                    .foregroundStyle(.white.opacity(0.78))

                InterestWrapView(interests: user.interests)
            }
            .padding(22)
        }
        .frame(maxWidth: .infinity)
        .frame(height: 540)
        .background(Color(.secondarySystemBackground))
        .clipShape(RoundedRectangle(cornerRadius: 30, style: .continuous))
        .shadow(color: .black.opacity(0.18), radius: 22, x: 0, y: 18)
        .rotationEffect(.degrees(Double(offset.width / 18)))
        .offset(offset)
        .allowsHitTesting(isTopCard)
        .gesture(dragGesture)
        .animation(.spring(response: 0.28, dampingFraction: 0.82), value: offset)
    }

    @ViewBuilder
    private var cardImage: some View {
        if let photo = user.photos.first, let url = URL(string: photo) {
            AsyncImage(url: url) { phase in
                switch phase {
                case .success(let image):
                    image
                        .resizable()
                        .scaledToFill()
                default:
                    placeholderImage
                }
            }
        } else {
            placeholderImage
        }
    }

    private var placeholderImage: some View {
        LinearGradient(
            colors: [Color.orange, Color.pink, Color.red],
            startPoint: .topLeading,
            endPoint: .bottomTrailing
        )
        .overlay {
            Image(systemName: "sparkles")
                .font(.system(size: 96))
                .foregroundStyle(.white.opacity(0.24))
        }
    }

    private var dragGesture: some Gesture {
        DragGesture()
            .onChanged { value in
                offset = value.translation
            }
            .onEnded { value in
                if value.translation.width > 130 {
                    onDecision(.like)
                    offset = .zero
                } else if value.translation.width < -130 {
                    onDecision(.pass)
                    offset = .zero
                } else {
                    offset = .zero
                }
            }
    }
}

private struct InterestWrapView: View {
    let interests: [String]

    var body: some View {
        ViewThatFits {
            HStack {
                interestCapsules
            }

            VStack(alignment: .leading) {
                interestCapsules
            }
        }
    }

    @ViewBuilder
    private var interestCapsules: some View {
        ForEach(interests, id: \.self) { interest in
            Text(interest)
                .font(.caption.weight(.semibold))
                .padding(.horizontal, 10)
                .padding(.vertical, 6)
                .background(.white.opacity(0.16), in: Capsule())
                .foregroundStyle(.white)
        }
    }
}

private struct SwipeButton: View {
    let icon: String
    let tint: Color
    let action: () -> Void

    var body: some View {
        Button(action: action) {
            Image(systemName: icon)
                .font(.title2.weight(.bold))
                .foregroundStyle(tint)
                .frame(width: 68, height: 68)
                .background(.white, in: Circle())
                .shadow(color: .black.opacity(0.12), radius: 12, x: 0, y: 8)
        }
        .buttonStyle(.plain)
    }
}

private struct EmptyStateCard: View {
    let title: String
    let subtitle: String

    var body: some View {
        VStack(spacing: 12) {
            Image(systemName: "sparkles.rectangle.stack.fill")
                .font(.system(size: 42))
                .foregroundStyle(.pink)
            Text(title)
                .font(.title3.bold())
            Text(subtitle)
                .font(.subheadline)
                .foregroundStyle(.secondary)
                .multilineTextAlignment(.center)
        }
        .padding(24)
        .frame(maxWidth: .infinity)
        .background(.white, in: RoundedRectangle(cornerRadius: 28, style: .continuous))
    }
}

private struct MessageBubble: View {
    let text: String
    let isMine: Bool

    var body: some View {
        HStack {
            if isMine {
                Spacer(minLength: 40)
            }

            Text(text)
                .padding(.horizontal, 14)
                .padding(.vertical, 12)
                .background(
                    isMine ? Color.pink : Color.white,
                    in: RoundedRectangle(cornerRadius: 18, style: .continuous)
                )
                .foregroundStyle(isMine ? .white : .primary)

            if !isMine {
                Spacer(minLength: 40)
            }
        }
    }
}

private struct MatchBanner: View {
    let text: String

    var body: some View {
        Text(text)
            .font(.headline)
            .foregroundStyle(.white)
            .padding(.horizontal, 18)
            .padding(.vertical, 14)
            .background(
                LinearGradient(
                    colors: [Color.pink, Color.orange],
                    startPoint: .leading,
                    endPoint: .trailing
                ),
                in: Capsule()
            )
            .shadow(color: .black.opacity(0.16), radius: 12, x: 0, y: 8)
    }
}

private struct LoadingView: View {
    var body: some View {
        ZStack {
            Color.black.opacity(0.16)
                .ignoresSafeArea()

            ProgressView("Loading")
                .padding(20)
                .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 20, style: .continuous))
        }
    }
}

private struct AuthBackground: View {
    var body: some View {
        LinearGradient(
            colors: [
                Color(red: 0.96, green: 0.41, blue: 0.30),
                Color(red: 0.93, green: 0.18, blue: 0.43),
                Color(red: 0.36, green: 0.15, blue: 0.34),
            ],
            startPoint: .topLeading,
            endPoint: .bottomTrailing
        )
        .ignoresSafeArea()
        .overlay {
            Circle()
                .fill(.white.opacity(0.12))
                .frame(width: 240, height: 240)
                .offset(x: 160, y: -260)
        }
    }
}
