//
//  Components.swift
//  MagicCounter
//
//  Created by Atridad Lahiji on 2025-12-06.
//

import SwiftUI
import Combine

/**
 * A circular button with an icon, used for game controls.
 * Supports optional long press to trigger a custom delta prompt.
 */
struct CircleButton: View {
    let icon: String
    let color: Color
    let size: CGFloat
    let action: () -> Void
    var onLongPress: (() -> Void)? = nil

    init(icon: String, color: Color, size: CGFloat = 44, action: @escaping () -> Void, onLongPress: (() -> Void)? = nil) {
        self.icon = icon
        self.color = color
        self.size = size
        self.action = action
        self.onLongPress = onLongPress
    }

    var body: some View {
        Image(systemName: icon)
            .font(size < 40 ? .caption : .title3)
            .frame(width: size, height: size)
            .background(color.opacity(0.2))
            .clipShape(Circle())
            .foregroundStyle(color)
            .contentShape(Circle())
            .onTapGesture {
                action()
            }
            .onLongPressGesture(minimumDuration: 0.5) {
                onLongPress?()
            }
    }
}

/**
 * A view that shows the accumulated delta change near a counter button.
 * Automatically fades out after a delay.
 */
struct DeltaIndicator: View {
    let delta: Int
    let alignment: HorizontalAlignment

    var body: some View {
        if delta != 0 {
            Text(delta > 0 ? "+\(delta)" : "\(delta)")
                .font(.system(size: 16, weight: .bold, design: .rounded))
                .foregroundStyle(delta > 0 ? .green : .red)
                .opacity(0.8)
                .transition(.opacity.combined(with: .scale))
        }
    }
}

/**
 * Observable class to manage delta accumulation and fade-out timing.
 */
class DeltaTracker: ObservableObject {
    @Published var delta: Int = 0
    private var resetTimer: Timer?

    func addDelta(_ amount: Int) {
        delta += amount
        resetTimer?.invalidate()
        resetTimer = Timer.scheduledTimer(withTimeInterval: 2.0, repeats: false) { [weak self] _ in
            withAnimation(.easeOut(duration: 0.3)) {
                self?.delta = 0
            }
        }
    }

    func reset() {
        resetTimer?.invalidate()
        delta = 0
    }
}

/**
 * A control for adjusting a large numerical value (like Life).
 * Shows delta indicators and supports long-press for custom delta input.
 */
struct LifeCounterControl: View {
    let value: Int
    let onDecrease: () -> Void
    let onIncrease: () -> Void
    var onCustomDelta: ((Int) -> Void)? = nil

    @StateObject private var deltaTracker = DeltaTracker()
    @State private var showingCustomDeltaAlert = false
    @State private var customDeltaText = ""
    @State private var isIncreasing = true

    var body: some View {
        HStack(spacing: 16) {
            ZStack {
                CircleButton(
                    icon: "minus",
                    color: .red,
                    action: {
                        onDecrease()
                        withAnimation(.easeOut(duration: 0.15)) {
                            deltaTracker.addDelta(-1)
                        }
                    },
                    onLongPress: {
                        isIncreasing = false
                        customDeltaText = ""
                        showingCustomDeltaAlert = true
                        Haptics.play(.medium)
                    }
                )

                if deltaTracker.delta < 0 {
                    DeltaIndicator(delta: deltaTracker.delta, alignment: .trailing)
                        .offset(y: -35)
                }
            }

            Text("\(value)")
                .font(.system(size: 56, weight: .bold, design: .rounded))
                .minimumScaleFactor(0.5)
                .lineLimit(1)
                .foregroundStyle(.primary)

            ZStack {
                CircleButton(
                    icon: "plus",
                    color: .green,
                    action: {
                        onIncrease()
                        withAnimation(.easeOut(duration: 0.15)) {
                            deltaTracker.addDelta(1)
                        }
                    },
                    onLongPress: {
                        isIncreasing = true
                        customDeltaText = ""
                        showingCustomDeltaAlert = true
                        Haptics.play(.medium)
                    }
                )

                if deltaTracker.delta > 0 {
                    DeltaIndicator(delta: deltaTracker.delta, alignment: .leading)
                        .offset(y: -35)
                }
            }
        }
        .padding(.horizontal, 16)
        .alert("Enter Amount", isPresented: $showingCustomDeltaAlert) {
            TextField("Amount", text: $customDeltaText)
                .keyboardType(.numberPad)
            Button("Cancel", role: .cancel) { }
            Button(isIncreasing ? "Add" : "Subtract") {
                if let amount = Int(customDeltaText), amount > 0 {
                    let delta = isIncreasing ? amount : -amount
                    onCustomDelta?(delta)
                    withAnimation(.easeOut(duration: 0.15)) {
                        deltaTracker.addDelta(delta)
                    }
                }
            }
        } message: {
            Text(isIncreasing ? "Enter the amount to add" : "Enter the amount to subtract")
        }
    }
}

/**
 * A smaller control for adjusting secondary values (like Poison).
 * Shows delta indicators and supports long-press for custom delta input.
 */
struct SmallCounterControl: View {
    let value: Int
    let icon: String
    let color: Color
    let onDecrease: () -> Void
    let onIncrease: () -> Void
    var onCustomDelta: ((Int) -> Void)? = nil

    @StateObject private var deltaTracker = DeltaTracker()
    @State private var showingCustomDeltaAlert = false
    @State private var customDeltaText = ""
    @State private var isIncreasing = true

    var body: some View {
        HStack(spacing: 4) {
            ZStack {
                CircleButton(
                    icon: "minus",
                    color: .gray,
                    size: 24,
                    action: {
                        onDecrease()
                        withAnimation(.easeOut(duration: 0.15)) {
                            deltaTracker.addDelta(-1)
                        }
                    },
                    onLongPress: {
                        isIncreasing = false
                        customDeltaText = ""
                        showingCustomDeltaAlert = true
                        Haptics.play(.medium)
                    }
                )

                if deltaTracker.delta < 0 {
                    DeltaIndicator(delta: deltaTracker.delta, alignment: .trailing)
                        .font(.system(size: 12, weight: .bold))
                        .offset(y: -22)
                }
            }

            VStack(spacing: 0) {
                Image(systemName: icon)
                    .font(.caption2)
                    .foregroundStyle(color)
                Text("\(value)")
                    .font(.title3.bold())
                    .foregroundStyle(color)
            }
            .frame(minWidth: 30)

            ZStack {
                CircleButton(
                    icon: "plus",
                    color: .gray,
                    size: 24,
                    action: {
                        onIncrease()
                        withAnimation(.easeOut(duration: 0.15)) {
                            deltaTracker.addDelta(1)
                        }
                    },
                    onLongPress: {
                        isIncreasing = true
                        customDeltaText = ""
                        showingCustomDeltaAlert = true
                        Haptics.play(.medium)
                    }
                )

                if deltaTracker.delta > 0 {
                    DeltaIndicator(delta: deltaTracker.delta, alignment: .leading)
                        .font(.system(size: 12, weight: .bold))
                        .offset(y: -22)
                }
            }
        }
        .padding(6)
        .background(color.opacity(0.1))
        .cornerRadius(12)
        .alert("Enter Amount", isPresented: $showingCustomDeltaAlert) {
            TextField("Amount", text: $customDeltaText)
                .keyboardType(.numberPad)
            Button("Cancel", role: .cancel) { }
            Button(isIncreasing ? "Add" : "Subtract") {
                if let amount = Int(customDeltaText), amount > 0 {
                    let delta = isIncreasing ? amount : -amount
                    onCustomDelta?(delta)
                    withAnimation(.easeOut(duration: 0.15)) {
                        deltaTracker.addDelta(delta)
                    }
                }
            }
        } message: {
            Text(isIncreasing ? "Enter the amount to add" : "Enter the amount to subtract")
        }
    }
}

/**
 * A reusable slider row for settings.
 */
struct SettingSlider: View {
    let title: String
    let value: Binding<Double>
    let range: ClosedRange<Double>
    let step: Double

    var body: some View {
        VStack(alignment: .leading) {
            HStack {
                Text(title)
                Spacer()
                Text("\(Int(value.wrappedValue))")
                    .bold()
            }
            Slider(value: value, in: range, step: step)
        }
    }
}

/**
 * Helper for haptic feedback.
 */
enum Haptics {
    static func play(_ style: UIImpactFeedbackGenerator.FeedbackStyle) {
        guard UserDefaults.standard.bool(forKey: "hapticFeedbackEnabled") else { return }
        let generator = UIImpactFeedbackGenerator(style: style)
        generator.impactOccurred()
    }

    static func notification(_ type: UINotificationFeedbackGenerator.FeedbackType) {
        guard UserDefaults.standard.bool(forKey: "hapticFeedbackEnabled") else { return }
        let generator = UINotificationFeedbackGenerator()
        generator.notificationOccurred(type)
    }
}
