import SwiftUI

// MARK: - Loading View

struct LoadingView: View {
    let message: String
    
    var body: some View {
        VStack(spacing: CloserSpacing.lg) {
            CloserHeartLoader()
            Text(message)
                .font(CloserFont.callout)
                .foregroundColor(.closerTextSecondary)
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
    }
}

struct CloserHeartLoader: View {
    @Environment(\.accessibilityReduceMotion) private var reduceMotion
    @State private var fillProgress: CGFloat = 0.08
    @State private var isPulsing = false

    var size: CGFloat = 76

    var body: some View {
        ZStack {
            CloserHeartShape()
                .fill(
                    LinearGradient(
                        colors: [
                            Color(hex: "F7C8E4").opacity(0.22),
                            Color(hex: "D9B8FF").opacity(0.22)
                        ],
                        startPoint: .leading,
                        endPoint: .trailing
                    )
                )

            HStack(spacing: 0) {
                Color(hex: "F7C8E4")
                Color(hex: "D9B8FF")
            }
            .mask(CloserHeartShape())
            .mask(alignment: .bottom) {
                Rectangle()
                    .frame(height: size * (reduceMotion ? 1 : fillProgress))
            }

            CloserHeartHighlightShape(side: .left)
                .fill(Color(hex: "FFF4FA").opacity(reduceMotion ? 0.68 : 0.68 * fillProgress))

            CloserHeartHighlightShape(side: .right)
                .fill(Color(hex: "F3E8FF").opacity(reduceMotion ? 0.52 : 0.52 * fillProgress))
        }
        .frame(width: size, height: size)
        .scaleEffect(reduceMotion ? 1 : (isPulsing ? 1.04 : 0.96))
        .accessibilityHidden(true)
        .onAppear {
            guard !reduceMotion else {
                fillProgress = 1
                isPulsing = false
                return
            }

            withAnimation(.easeInOut(duration: 1.5).repeatForever(autoreverses: false)) {
                fillProgress = 1
            }
            withAnimation(.easeInOut(duration: 0.9).repeatForever(autoreverses: true)) {
                isPulsing = true
            }
        }
        .onChange(of: reduceMotion) { _, newValue in
            if newValue {
                fillProgress = 1
                isPulsing = false
            }
        }
    }
}

private struct CloserHeartShape: Shape {
    func path(in rect: CGRect) -> Path {
        var path = Path()
        path.move(to: point(54, 85, in: rect))
        path.addCurve(
            to: point(22, 48, in: rect),
            control1: point(49, 79, in: rect),
            control2: point(27, 62, in: rect)
        )
        path.addCurve(
            to: point(37, 24, in: rect),
            control1: point(17, 35, in: rect),
            control2: point(24, 24, in: rect)
        )
        path.addCurve(
            to: point(54, 35, in: rect),
            control1: point(45, 24, in: rect),
            control2: point(51, 28, in: rect)
        )
        path.addCurve(
            to: point(71, 24, in: rect),
            control1: point(57, 28, in: rect),
            control2: point(63, 24, in: rect)
        )
        path.addCurve(
            to: point(86, 48, in: rect),
            control1: point(84, 24, in: rect),
            control2: point(91, 35, in: rect)
        )
        path.addCurve(
            to: point(54, 85, in: rect),
            control1: point(81, 62, in: rect),
            control2: point(59, 79, in: rect)
        )
        path.closeSubpath()
        return path
    }
}

private struct CloserHeartHighlightShape: Shape {
    enum Side {
        case left
        case right
    }

    let side: Side

    func path(in rect: CGRect) -> Path {
        var path = Path()
        switch side {
        case .left:
            path.move(to: point(27, 42, in: rect))
            path.addCurve(
                to: point(42, 27, in: rect),
                control1: point(28, 32, in: rect),
                control2: point(34, 27, in: rect)
            )
            path.addCurve(
                to: point(54, 35, in: rect),
                control1: point(48, 27, in: rect),
                control2: point(52, 30, in: rect)
            )
            path.addLine(to: point(54, 41, in: rect))
            path.addCurve(
                to: point(27, 42, in: rect),
                control1: point(47, 36, in: rect),
                control2: point(37, 36, in: rect)
            )
            path.closeSubpath()
        case .right:
            path.move(to: point(54, 35, in: rect))
            path.addCurve(
                to: point(69, 27, in: rect),
                control1: point(57, 30, in: rect),
                control2: point(62, 27, in: rect)
            )
            path.addCurve(
                to: point(85, 42, in: rect),
                control1: point(78, 27, in: rect),
                control2: point(84, 32, in: rect)
            )
            path.addCurve(
                to: point(54, 41, in: rect),
                control1: point(75, 36, in: rect),
                control2: point(65, 36, in: rect)
            )
            path.closeSubpath()
        }
        return path
    }
}

private func point(_ x: CGFloat, _ y: CGFloat, in rect: CGRect) -> CGPoint {
    CGPoint(
        x: rect.minX + rect.width * (x / 108),
        y: rect.minY + rect.height * (y / 108)
    )
}

// MARK: - Error View

struct ErrorView: View {
    let message: String
    let retryAction: (() -> Void)?
    
    var body: some View {
        VStack(spacing: CloserSpacing.lg) {
            Image(systemName: "exclamationmark.triangle.fill")
                .font(.system(size: 48))
                .foregroundColor(.closerWarning)
            Text("Something went wrong")
                .font(CloserFont.title3)
                .foregroundColor(.closerText)
            Text(message)
                .font(CloserFont.callout)
                .foregroundColor(.closerTextSecondary)
                .multilineTextAlignment(.center)
            
            if let retry = retryAction {
                Button(action: retry) {
                    Label("Try Again", systemImage: "arrow.clockwise")
                }
                .buttonStyle(PrimaryButtonStyle())
                .frame(maxWidth: 200)
            }
        }
        .padding(CloserSpacing.xl)
        .frame(maxWidth: .infinity, maxHeight: .infinity)
    }
}

// MARK: - Empty State View

struct EmptyStateView: View {
    let icon: String
    let title: String
    let message: String
    var illustrationName: String? = nil
    var action: (title: String, handler: () -> Void)? = nil
    
    var body: some View {
        VStack(spacing: CloserSpacing.lg) {
            if let illustrationName {
                CloserIllustrationView(imageName: illustrationName, size: 132)
            } else {
                Image(systemName: icon)
                    .font(.system(size: 48))
                    .foregroundColor(.closerPrimary.opacity(0.6))
            }
            
            Text(title)
                .font(CloserFont.title3)
                .foregroundColor(.closerText)
            
            Text(message)
                .font(CloserFont.callout)
                .foregroundColor(.closerTextSecondary)
                .multilineTextAlignment(.center)
            
            if let action = action {
                Button(action.title, action: action.handler)
                    .buttonStyle(PrimaryButtonStyle())
                    .frame(maxWidth: 200)
            }
        }
        .padding(CloserSpacing.xl)
        .frame(maxWidth: .infinity, maxHeight: .infinity)
    }
}

// MARK: - Illustration View

struct CloserIllustrationView: View {
    let imageName: String
    var size: CGFloat = 220
    var cornerRadius: CGFloat = CloserRadius.xlarge
    
    var body: some View {
        Image(imageName)
            .resizable()
            .scaledToFill()
            .frame(width: size, height: size)
            .clipShape(RoundedRectangle(cornerRadius: cornerRadius, style: .continuous))
            .accessibilityHidden(true)
    }
}

// MARK: - Partner Status Row

struct PartnerStatusRow: View {
    let displayName: String
    let answered: Bool
    let lastActive: Date?
    
    var body: some View {
        HStack(spacing: CloserSpacing.md) {
            // Avatar circle
            ZStack {
                Circle()
                    .fill(answered ? .closerPrimary : .closerDivider)
                    .frame(width: 44, height: 44)
                Image(systemName: "person.fill")
                    .foregroundColor(.white)
                    .font(.system(size: 18))
            }
            
            VStack(alignment: .leading, spacing: 2) {
                Text(displayName)
                    .font(CloserFont.headline)
                    .foregroundColor(.closerText)
                
                if answered {
                    Label("Answered", systemImage: "checkmark.circle.fill")
                        .font(CloserFont.caption)
                        .foregroundColor(.closerSuccess)
                } else {
                    Label("Waiting for answer", systemImage: "clock.fill")
                        .font(CloserFont.caption)
                        .foregroundColor(.closerWarning)
                }
            }
            
            Spacer()
        }
        .padding(CloserSpacing.md)
        .background(Color.closerSurface)
        .cornerRadius(CloserRadius.medium)
    }
}

// MARK: - Premium Badge

struct PremiumBadge: View {
    var body: some View {
        HStack(spacing: 4) {
            Image(systemName: "crown.fill")
                .font(.system(size: 10))
            Text("Premium")
                .font(CloserFont.caption)
        }
        .foregroundColor(.closerGold)
        .padding(.horizontal, CloserSpacing.sm)
        .padding(.vertical, 4)
        .background(Color.closerGold.opacity(0.15))
        .cornerRadius(CloserRadius.full)
    }
}

// MARK: - Streak Indicator

struct StreakIndicator: View {
    let count: Int
    let isActive: Bool
    
    var body: some View {
        HStack(spacing: 4) {
            Image(systemName: isActive ? "flame.fill" : "flame")
                .foregroundColor(isActive ? .closerDanger : .closerTextSecondary)
            Text("\(count) day\(count == 1 ? "" : "s")")
                .font(CloserFont.footnote)
                .foregroundColor(.closerTextSecondary)
        }
        .padding(.horizontal, CloserSpacing.sm)
        .padding(.vertical, 4)
        .background(isActive ? Color.closerDanger.opacity(0.1) : Color.closerDivider.opacity(0.3))
        .cornerRadius(CloserRadius.full)
    }
}

// MARK: - Category Glyph

struct CategoryGlyph: View {
    let name: String
    let color: Color
    var isLarge: Bool = false
    
    var body: some View {
        ZStack {
            Circle()
                .fill(color.opacity(0.15))
                .frame(width: isLarge ? 64 : 48, height: isLarge ? 64 : 48)
            
            Image(systemName: iconForCategory(name))
                .font(.system(size: isLarge ? 24 : 18))
                .foregroundColor(color)
        }
    }
    
    private func iconForCategory(_ name: String) -> String {
        switch name.lowercased() {
        case let s where s.contains("communication"): return "bubble.left.and.bubble.right.fill"
        case let s where s.contains("intimacy"): return "heart.fill"
        case let s where s.contains("fun"): return "gamecontroller.fill"
        case let s where s.contains("goal"): return "target"
        case let s where s.contains("adventure"): return "paperplane.fill"
        case let s where s.contains("romance"): return "sparkles"
        case let s where s.contains("deep"): return "brain.head.profile"
        default: return "questionmark.circle.fill"
        }
    }
}

// MARK: - Answer Card

struct AnswerCard: View {
    let text: String
    let date: Date
    let isRevealed: Bool
    let onTap: (() -> Void)?
    
    var body: some View {
        Button(action: { onTap?() }) {
            VStack(alignment: .leading, spacing: CloserSpacing.sm) {
                HStack {
                    Text(date, style: .date)
                        .font(CloserFont.caption)
                        .foregroundColor(.closerTextSecondary)
                    Spacer()
                    if isRevealed {
                        Image(systemName: "eye.fill")
                            .foregroundColor(.closerPrimary)
                    } else {
                        Image(systemName: "eye.slash.fill")
                            .foregroundColor(.closerTextSecondary)
                    }
                }
                
                Text(isRevealed ? text : "Tap to reveal partner's answer")
                    .font(CloserFont.body)
                    .foregroundColor(isRevealed ? .closerText : .closerTextSecondary)
                    .lineLimit(3)
            }
            .padding(CloserSpacing.md)
            .background(Color.closerSurface)
            .cornerRadius(CloserRadius.medium)
        }
        .buttonStyle(.plain)
    }
}

// MARK: - Heart Animation View

struct HeartBurstView: View {
    @State private var animate = false
    
    var body: some View {
        Image(systemName: "heart.fill")
            .font(.system(size: 80))
            .foregroundColor(.closerDanger)
            .scaleEffect(animate ? 1.2 : 0.5)
            .opacity(animate ? 0.8 : 0)
            .animation(.spring(response: 0.6, dampingFraction: 0.5).repeatCount(1, autoreverses: true), value: animate)
            .onAppear { animate = true }
    }
}

// MARK: - Premium Feature Gate

struct PremiumGateView: View {
    let featureName: String
    let onUnlock: () -> Void
    let onDismiss: () -> Void
    
    var body: some View {
        VStack(spacing: CloserSpacing.xl) {
            Image(systemName: "crown.fill")
                .font(.system(size: 64))
                .foregroundColor(.closerGold)
            
            Text("Unlock \(featureName)")
                .font(CloserFont.title2)
                .foregroundColor(.closerText)
            
            Text("This feature requires a premium subscription. Upgrade to access all games, unlimited questions, and more.")
                .font(CloserFont.callout)
                .foregroundColor(.closerTextSecondary)
                .multilineTextAlignment(.center)
            
            Button("See Plans", action: onUnlock)
                .buttonStyle(PrimaryButtonStyle())
            
            Button("Maybe Later", action: onDismiss)
                .buttonStyle(SecondaryButtonStyle())
        }
        .padding(CloserSpacing.xxl)
        .background(Color.closerBackground)
        .cornerRadius(CloserRadius.xlarge)
        .closerShadow(level: .large)
        .padding(CloserSpacing.xl)
    }
}
