import SwiftUI
import UIKit

// MARK: - Organic Design System
// Warm, natural aesthetic with soft shapes, subtle textures, and flowing layouts

// MARK: - Honeycomb Setting Reader
/// Reads honeycomb enabled state from AppThemeSource (reactive in main app, static in widgets).
enum HoneycombSetting {
    static var isEnabled: Bool {
        #if WIDGET_EXTENSION
        AppThemeSource.honeycombEnabled
        #else
        AppThemeSource.shared.honeycombEnabled
        #endif
    }
}

// MARK: - Organic Shapes

/// Soft organic blob shape for backgrounds
struct OrganicBlobShape: Shape {
    var variation: Int = 0

    func path(in rect: CGRect) -> Path {
        var path = Path()
        let w = rect.width
        let h = rect.height

        switch variation % 3 {
        case 0:
            // Soft cloud-like blob
            path.move(to: CGPoint(x: w * 0.1, y: h * 0.5))
            path.addCurve(
                to: CGPoint(x: w * 0.5, y: h * 0.05),
                control1: CGPoint(x: w * 0.0, y: h * 0.1),
                control2: CGPoint(x: w * 0.25, y: h * 0.0)
            )
            path.addCurve(
                to: CGPoint(x: w * 0.95, y: h * 0.45),
                control1: CGPoint(x: w * 0.75, y: h * 0.1),
                control2: CGPoint(x: w * 1.0, y: h * 0.25)
            )
            path.addCurve(
                to: CGPoint(x: w * 0.55, y: h * 0.95),
                control1: CGPoint(x: w * 0.9, y: h * 0.7),
                control2: CGPoint(x: w * 0.8, y: h * 0.95)
            )
            path.addCurve(
                to: CGPoint(x: w * 0.1, y: h * 0.5),
                control1: CGPoint(x: w * 0.25, y: h * 0.95),
                control2: CGPoint(x: w * 0.05, y: h * 0.75)
            )
        case 1:
            // Pebble shape
            path.move(to: CGPoint(x: w * 0.15, y: h * 0.4))
            path.addCurve(
                to: CGPoint(x: w * 0.6, y: h * 0.08),
                control1: CGPoint(x: w * 0.1, y: h * 0.15),
                control2: CGPoint(x: w * 0.35, y: h * 0.05)
            )
            path.addCurve(
                to: CGPoint(x: w * 0.9, y: h * 0.55),
                control1: CGPoint(x: w * 0.85, y: h * 0.12),
                control2: CGPoint(x: w * 0.95, y: h * 0.35)
            )
            path.addCurve(
                to: CGPoint(x: w * 0.45, y: h * 0.92),
                control1: CGPoint(x: w * 0.85, y: h * 0.8),
                control2: CGPoint(x: w * 0.65, y: h * 0.95)
            )
            path.addCurve(
                to: CGPoint(x: w * 0.15, y: h * 0.4),
                control1: CGPoint(x: w * 0.2, y: h * 0.88),
                control2: CGPoint(x: w * 0.08, y: h * 0.65)
            )
        default:
            // Leaf-like shape
            path.move(to: CGPoint(x: w * 0.05, y: h * 0.5))
            path.addCurve(
                to: CGPoint(x: w * 0.5, y: h * 0.02),
                control1: CGPoint(x: w * 0.05, y: h * 0.2),
                control2: CGPoint(x: w * 0.25, y: h * 0.02)
            )
            path.addCurve(
                to: CGPoint(x: w * 0.95, y: h * 0.5),
                control1: CGPoint(x: w * 0.75, y: h * 0.02),
                control2: CGPoint(x: w * 0.95, y: h * 0.2)
            )
            path.addCurve(
                to: CGPoint(x: w * 0.5, y: h * 0.98),
                control1: CGPoint(x: w * 0.95, y: h * 0.8),
                control2: CGPoint(x: w * 0.75, y: h * 0.98)
            )
            path.addCurve(
                to: CGPoint(x: w * 0.05, y: h * 0.5),
                control1: CGPoint(x: w * 0.25, y: h * 0.98),
                control2: CGPoint(x: w * 0.05, y: h * 0.8)
            )
        }

        return path
    }
}

/// Super soft rounded rectangle for organic cards
struct OrganicRoundedRectangle: Shape {
    var cornerRadius: CGFloat = 28

    func path(in rect: CGRect) -> Path {
        Path(roundedRect: rect, cornerRadius: cornerRadius, style: .continuous)
    }
}

// MARK: - Grain Texture Cache

/// Generates and caches a grain texture image so it is only computed once,
/// regardless of how many GrainTexture views are on screen.
private final class GrainTextureCache {
    static let shared = GrainTextureCache()

    /// Cached grain image at a fixed tile size. Tiled across the view.
    private(set) var cachedImage: UIImage?
    private let tileSize = CGSize(width: 128, height: 128)
    private let lock = NSLock()

    private init() {
        generateIfNeeded()
    }

    func generateIfNeeded() {
        lock.lock()
        defer { lock.unlock() }
        guard cachedImage == nil else { return }

        let renderer = UIGraphicsImageRenderer(size: tileSize)
        cachedImage = renderer.image { ctx in
            let cgCtx = ctx.cgContext
            let w = tileSize.width
            let h = tileSize.height
            let dotCount = Int(w * h / 200)

            for _ in 0..<dotCount {
                let x = CGFloat.random(in: 0...w)
                let y = CGFloat.random(in: 0...h)
                let grainOpacity = CGFloat.random(in: 0.3...1.0)

                cgCtx.setFillColor(UIColor.black.withAlphaComponent(grainOpacity).cgColor)
                cgCtx.fillEllipse(in: CGRect(x: x, y: y, width: 1, height: 1))
            }
        }
    }
}

// MARK: - Honeycomb Texture Cache

/// Generates and caches a honeycomb hexagonal grid tile image.
/// Matches the website pattern: 60×103.92px tile, #C4856A stroke, 0.8px width.
private final class HoneycombTextureCache {
    static let shared = HoneycombTextureCache()

    private(set) var cachedImage: UIImage?
    private let tileSize = CGSize(width: 60, height: 103.92)
    private let lock = NSLock()

    private init() {
        generateIfNeeded()
    }

    func generateIfNeeded() {
        lock.lock()
        defer { lock.unlock() }
        guard cachedImage == nil else { return }

        let w = tileSize.width
        let h = tileSize.height
        let strokeColor = UIColor(red: 196/255, green: 133/255, blue: 106/255, alpha: 1.0) // #C4856A
        let strokeWidth: CGFloat = 0.8

        let renderer = UIGraphicsImageRenderer(size: tileSize)
        cachedImage = renderer.image { ctx in
            let cgCtx = ctx.cgContext
            cgCtx.setStrokeColor(strokeColor.cgColor)
            cgCtx.setLineWidth(strokeWidth)
            cgCtx.setFillColor(UIColor.clear.cgColor)

            // First hexagon (top)
            let hex1 = CGMutablePath()
            hex1.move(to: CGPoint(x: 30, y: 0))
            hex1.addLine(to: CGPoint(x: 60, y: 17.32))
            hex1.addLine(to: CGPoint(x: 60, y: 51.96))
            hex1.addLine(to: CGPoint(x: 30, y: 69.28))
            hex1.addLine(to: CGPoint(x: 0, y: 51.96))
            hex1.addLine(to: CGPoint(x: 0, y: 17.32))
            hex1.closeSubpath()
            cgCtx.addPath(hex1)
            cgCtx.strokePath()

            // Second hexagon (bottom-right, offset for tessellation)
            let hex2 = CGMutablePath()
            hex2.move(to: CGPoint(x: 60, y: 51.96))
            hex2.addLine(to: CGPoint(x: 90, y: 69.28))
            hex2.addLine(to: CGPoint(x: 90, y: h))
            hex2.addLine(to: CGPoint(x: 60, y: h + 17.32))
            hex2.addLine(to: CGPoint(x: 30, y: h))
            hex2.addLine(to: CGPoint(x: 30, y: 69.28))
            hex2.closeSubpath()
            cgCtx.addPath(hex2)
            cgCtx.strokePath()
        }
    }
}

// MARK: - Honeycomb Texture Overlay

struct HoneycombTexture: View {
    var opacity: Double = 0.10

    var body: some View {
        if let uiImage = HoneycombTextureCache.shared.cachedImage {
            Image(uiImage: uiImage)
                .resizable(resizingMode: .tile)
                .opacity(opacity)
                .allowsHitTesting(false)
        }
    }
}

// MARK: - Grain Texture Overlay

struct GrainTexture: View {
    var opacity: Double = 0.03
    var animated: Bool = false

    var body: some View {
        if let uiImage = GrainTextureCache.shared.cachedImage {
            Image(uiImage: uiImage)
                .resizable(resizingMode: .tile)
                .opacity(opacity)
                .allowsHitTesting(false)
        }
    }
}

// MARK: - Organic Card Background

struct OrganicCardBackground: View {
    var accentColor: Color = Color.appPrimary
    var showBlob: Bool = true
    var blobVariation: Int = 0

    var body: some View {
        ZStack {
            // Main card fill
            RoundedRectangle(cornerRadius: 28, style: .continuous)
                .fill(Color.appBackgroundSecondary)

            // Subtle accent blob in corner
            if showBlob {
                GeometryReader { geo in
                    OrganicBlobShape(variation: blobVariation)
                        .fill(
                            LinearGradient(
                                colors: [
                                    accentColor.opacity(0.08),
                                    accentColor.opacity(0.02)
                                ],
                                startPoint: .topLeading,
                                endPoint: .bottomTrailing
                            )
                        )
                        .frame(width: geo.size.width * 0.6, height: geo.size.height * 0.7)
                        .offset(x: geo.size.width * 0.5, y: -geo.size.height * 0.1)
                        .blur(radius: 20)
                }
                .clipped()
            }

            // Grain texture
            GrainTexture(opacity: 0.015)
                .clipShape(RoundedRectangle(cornerRadius: 28, style: .continuous))

            // Honeycomb pattern overlay
            if HoneycombSetting.isEnabled {
                HoneycombTexture(opacity: 0.10)
                    .clipShape(RoundedRectangle(cornerRadius: 28, style: .continuous))
            }
        }
    }
}

// MARK: - Natural Shadow Modifier

struct NaturalShadow: ViewModifier {
    var intensity: ShadowIntensity = .medium

    enum ShadowIntensity {
        case subtle, medium, pronounced

        var values: (color: Color, radius: CGFloat, y: CGFloat) {
            switch self {
            case .subtle:
                return (Color.black.opacity(0.04), 8, 4)
            case .medium:
                return (Color.black.opacity(0.08), 16, 8)
            case .pronounced:
                return (Color.black.opacity(0.12), 24, 12)
            }
        }
    }

    func body(content: Content) -> some View {
        content
            .shadow(
                color: intensity.values.color,
                radius: intensity.values.radius,
                x: 0,
                y: intensity.values.y
            )
            // Secondary ambient shadow for depth
            .shadow(
                color: intensity.values.color.opacity(0.5),
                radius: intensity.values.radius * 2,
                x: 0,
                y: intensity.values.y * 0.5
            )
    }
}

// MARK: - Organic Icon Container

struct OrganicIconContainer: View {
    let systemName: String
    var size: CGFloat = 48
    var iconScale: CGFloat = 0.5
    var backgroundColor: Color = Color.appPrimary
    var iconColor: Color = Color.appTextOnPrimary

    var body: some View {
        ZStack {
            // Soft organic background
            Circle()
                .fill(
                    RadialGradient(
                        colors: [
                            backgroundColor,
                            backgroundColor.opacity(0.85)
                        ],
                        center: .topLeading,
                        startRadius: 0,
                        endRadius: size
                    )
                )
                .frame(width: size, height: size)

            // Inner glow
            Circle()
                .fill(
                    RadialGradient(
                        colors: [
                            Color.white.opacity(0.2),
                            Color.clear
                        ],
                        center: .topLeading,
                        startRadius: 0,
                        endRadius: size * 0.5
                    )
                )
                .frame(width: size, height: size)

            // Icon
            Image(systemName: systemName)
                .font(.system(size: size * iconScale, weight: .semibold))
                .foregroundColor(iconColor)
        }
        .modifier(NaturalShadow(intensity: .subtle))
    }
}

// MARK: - Organic Stat Pill

struct OrganicStatPill: View {
    let icon: String
    let value: String
    let label: String
    var color: Color = Color.appPrimary
    var isSystemIcon: Bool = true

    var body: some View {
        HStack(spacing: 8) {
            // Icon with soft background
            ZStack {
                Circle()
                    .fill(color.opacity(0.12))
                    .frame(width: 32, height: 32)

                if isSystemIcon {
                    Image(systemName: icon)
                        .font(.system(size: 13, weight: .semibold))
                        .foregroundColor(color)
                } else {
                    Image(icon)
                        .renderingMode(.template)
                        .resizable()
                        .scaledToFit()
                        .frame(width: 16, height: 16)
                        .foregroundColor(color)
                }
            }

            VStack(alignment: .leading, spacing: 1) {
                Text(value)
                    .font(.system(size: 15, weight: .bold, design: .rounded))
                    .foregroundColor(Color.appTextPrimary)

                Text(label)
                    .font(.system(size: 11, weight: .medium))
                    .foregroundColor(Color.appTextSecondary)
            }
        }
        .padding(.horizontal, 14)
        .padding(.vertical, 10)
        .background(
            Capsule()
                .fill(Color.appBackgroundSecondary)
                .overlay(
                    Capsule()
                        .stroke(color.opacity(0.15), lineWidth: 1)
                )
        )
    }
}

// MARK: - Organic Divider

struct OrganicDivider: View {
    var color: Color = Color.appTextSecondary.opacity(0.15)
    var height: CGFloat = 1
    var horizontalPadding: CGFloat = 0

    var body: some View {
        Rectangle()
            .fill(
                LinearGradient(
                    colors: [
                        color.opacity(0),
                        color,
                        color,
                        color.opacity(0)
                    ],
                    startPoint: .leading,
                    endPoint: .trailing
                )
            )
            .frame(height: height)
            .padding(.horizontal, horizontalPadding)
    }
}

// MARK: - Warm Gradient Background

struct WarmGradientBackground: View {
    @Environment(\.colorScheme) var colorScheme

    var body: some View {
        ZStack {
            Color.appBackgroundPrimary

            // Subtle warm gradient overlay
            LinearGradient(
                colors: colorScheme == .dark
                    ? [Color.appPrimary.opacity(0.05), Color.clear]
                    : [Color.appPrimary.opacity(0.03), Color.clear],
                startPoint: .topLeading,
                endPoint: .bottomTrailing
            )

            // Grain for natural feel
            GrainTexture(opacity: 0.02)

            // Honeycomb pattern overlay
            if HoneycombSetting.isEnabled {
                HoneycombTexture(opacity: 0.10)
            }
        }
        .ignoresSafeArea()
    }
}

// MARK: - View Extensions

extension View {
    func organicCard(
        accentColor: Color = Color.appPrimary,
        showBlob: Bool = true,
        shadowIntensity: NaturalShadow.ShadowIntensity = .medium
    ) -> some View {
        self
            .background(OrganicCardBackground(accentColor: accentColor, showBlob: showBlob))
            .clipShape(RoundedRectangle(cornerRadius: 28, style: .continuous))
            .modifier(NaturalShadow(intensity: shadowIntensity))
    }

    func naturalShadow(_ intensity: NaturalShadow.ShadowIntensity = .medium) -> some View {
        modifier(NaturalShadow(intensity: intensity))
    }
}

// MARK: - Organic Spacing

struct OrganicSpacing {
    static let compact: CGFloat = 8
    static let cozy: CGFloat = 20
    static let comfortable: CGFloat = 24
    static let spacious: CGFloat = 32
    static let airy: CGFloat = 40
}

// MARK: - Animated Leaf Decoration

struct FloatingLeaf: View {
    @State private var rotation: Double = 0
    @State private var offset: CGFloat = 0
    @State private var isAnimating = false
    @Environment(\.accessibilityReduceMotion) private var reduceMotion
    var delay: Double = 0
    var size: CGFloat = 20
    var color: Color = Color.appPrimary

    var body: some View {
        Image(systemName: "leaf.fill")
            .font(.system(size: size))
            .foregroundColor(color.opacity(0.15))
            .rotationEffect(.degrees(rotation))
            .offset(y: offset)
            .onAppear {
                isAnimating = true
                guard !reduceMotion else { return }
                withAnimation(
                    Animation
                        .easeInOut(duration: 4)
                        .repeatForever(autoreverses: true)
                        .delay(delay)
                ) {
                    rotation = 15
                    offset = 8
                }
            }
            .onDisappear {
                isAnimating = false
                rotation = 0
                offset = 0
            }
    }
}

// MARK: - Preview

#Preview("Organic Components") {
    ScrollView {
        VStack(spacing: 24) {
            // Organic Icon Container
            HStack(spacing: 16) {
                OrganicIconContainer(systemName: "house.fill", size: 56)
                OrganicIconContainer(systemName: "wrench.fill", size: 48, backgroundColor: .orange)
                OrganicIconContainer(systemName: "leaf.fill", size: 40, backgroundColor: .green)
            }

            // Organic Stat Pills
            HStack(spacing: 12) {
                OrganicStatPill(icon: "outline", value: "3", label: "Properties", isSystemIcon: false)
                OrganicStatPill(icon: "checklist", value: "12", label: "Tasks", color: .orange)
            }

            // Organic Card
            VStack(alignment: .leading, spacing: 16) {
                Text("Organic Card Example")
                    .font(.title3.weight(.bold))
                Text("This card uses soft shapes, subtle gradients, and natural shadows.")
                    .font(.subheadline)
                    .foregroundColor(.secondary)
            }
            .padding(OrganicSpacing.cozy)
            .organicCard()

            // Organic Divider
            OrganicDivider()
                .padding(.horizontal, 40)
        }
        .padding()
    }
    .background(WarmGradientBackground())
}
