//
//  RulesListView.swift
//  CasinoKit
//
//  A reusable list-based rules/help view for casino games.
//

import SwiftUI

// MARK: - Rule Topic Model

/// A model representing a single rule/help topic.
public struct RuleTopic: Identifiable {
    public let id = UUID()
    
    /// The title of the topic.
    public let title: String
    
    /// The SF Symbol icon name.
    public let icon: String
    
    /// The bullet-point content items.
    public let content: [String]
    
    /// Creates a rule topic.
    /// - Parameters:
    ///   - title: The topic title.
    ///   - icon: SF Symbol name for the icon.
    ///   - content: Array of bullet-point strings.
    public init(title: String, icon: String, content: [String]) {
        self.title = title
        self.icon = icon
        self.content = content
    }
}

// MARK: - Rules Provider Protocol

/// Protocol for providing game rules content.
/// Implement this to define rules for a specific game.
public protocol RulesProvider {
    /// The title for the rules sheet (e.g., "How to Play").
    var title: String { get }
    
    /// The list of rule topics for this game.
    var topics: [RuleTopic] { get }
}

// MARK: - Rule Topic Templates

/// Templates for common rule topics that games can customize.
/// Games provide their own localized content for these templates.
public enum RuleTopicTemplate {
    
    /// Creates an Objective topic.
    /// - Parameter content: The localized content bullets.
    public static func objective(content: [String]) -> RuleTopic {
        RuleTopic(
            title: String(localized: "Objective", bundle: .module),
            icon: "target",
            content: content
        )
    }
    
    /// Creates a Card Values topic.
    /// - Parameter content: The localized content bullets.
    public static func cardValues(content: [String]) -> RuleTopic {
        RuleTopic(
            title: String(localized: "Card Values", bundle: .module),
            icon: "suit.spade.fill",
            content: content
        )
    }
    
    /// Creates a Payouts topic.
    /// - Parameter content: The localized content bullets.
    public static func payouts(content: [String]) -> RuleTopic {
        RuleTopic(
            title: String(localized: "Payouts", bundle: .module),
            icon: "dollarsign.circle.fill",
            content: content
        )
    }
    
    /// Creates a Side Bets topic.
    /// - Parameter content: The localized content bullets.
    public static func sideBets(content: [String]) -> RuleTopic {
        RuleTopic(
            title: String(localized: "Side Bets", bundle: .module),
            icon: "plus.circle.fill",
            content: content
        )
    }
    
    /// Creates a Game Sessions topic.
    /// - Parameter content: The localized content bullets.
    public static func gameSessions(content: [String]) -> RuleTopic {
        RuleTopic(
            title: String(localized: "Game Sessions", bundle: .module),
            icon: "clock.badge.checkmark.fill",
            content: content
        )
    }
    
    /// Creates a Strategy Tips topic.
    /// - Parameter content: The localized content bullets.
    public static func strategyTips(content: [String]) -> RuleTopic {
        RuleTopic(
            title: String(localized: "Strategy Tips", bundle: .module),
            icon: "lightbulb.fill",
            content: content
        )
    }
    
    /// Creates a custom topic with the specified parameters.
    /// - Parameters:
    ///   - title: The localized title.
    ///   - icon: SF Symbol name.
    ///   - content: The localized content bullets.
    public static func custom(title: String, icon: String, content: [String]) -> RuleTopic {
        RuleTopic(title: title, icon: icon, content: content)
    }
}

// MARK: - Rule Topic Builder

/// A builder for composing rule topics with a fluent API.
@resultBuilder
public struct RuleTopicsBuilder {
    public static func buildBlock(_ components: RuleTopic...) -> [RuleTopic] {
        components
    }
    
    public static func buildBlock(_ components: [RuleTopic]...) -> [RuleTopic] {
        components.flatMap { $0 }
    }
    
    public static func buildArray(_ components: [[RuleTopic]]) -> [RuleTopic] {
        components.flatMap { $0 }
    }
    
    public static func buildExpression(_ expression: RuleTopic) -> [RuleTopic] {
        [expression]
    }
    
    public static func buildExpression(_ expression: [RuleTopic]) -> [RuleTopic] {
        expression
    }
}

/// A list-based rules/help view with navigation to detail pages.
///
/// Usage:
/// ```swift
/// RulesListView(
///     title: "How to Play",
///     topics: [
///         RuleTopic(title: "Objective", icon: "target", content: [...]),
///         RuleTopic(title: "Card Values", icon: "suit.spade.fill", content: [...])
///     ]
/// )
/// ```
public struct RulesListView: View {
    /// The navigation title for the sheet.
    public let title: String
    
    /// The list of topics to display.
    public let topics: [RuleTopic]
    
    /// Environment dismiss action.
    @Environment(\.dismiss) private var dismiss
    
    /// Creates a rules list view.
    /// - Parameters:
    ///   - title: The navigation title.
    ///   - topics: Array of rule topics to display.
    public init(title: String, topics: [RuleTopic]) {
        self.title = title
        self.topics = topics
    }
    
    public var body: some View {
        NavigationStack {
            ZStack {
                Color.Sheet.background
                    .ignoresSafeArea()
                
                ScrollView {
                    LazyVStack(spacing: CasinoDesign.Spacing.small) {
                        ForEach(topics) { topic in
                            NavigationLink(value: topic) {
                                RuleTopicRow(topic: topic)
                            }
                            .buttonStyle(.plain)
                        }
                    }
                    .padding(.horizontal, CasinoDesign.Spacing.medium)
                    .padding(.vertical, CasinoDesign.Spacing.medium)
                }
            }
            .navigationTitle(title)
            .navigationBarTitleDisplayMode(.inline)
            .toolbarBackground(Color.Sheet.background, for: .navigationBar)
            .toolbarBackground(.visible, for: .navigationBar)
            .toolbarColorScheme(.dark, for: .navigationBar)
            .toolbar {
                ToolbarItem(placement: .topBarTrailing) {
                    Button(String(localized: "Done", bundle: .module)) {
                        dismiss()
                    }
                    .bold()
                    .foregroundStyle(Color.Sheet.accent)
                }
            }
            .navigationDestination(for: RuleTopic.self) { topic in
                RuleDetailView(topic: topic)
            }
        }
    }
}

// MARK: - Rule Topic Row

/// A row displaying a rule topic with icon and title.
struct RuleTopicRow: View {
    let topic: RuleTopic
    
    var body: some View {
        HStack(spacing: CasinoDesign.Spacing.medium) {
            // Icon
            Image(systemName: topic.icon)
                .font(.system(size: CasinoDesign.BaseFontSize.large))
                .foregroundStyle(Color.Sheet.accent)
                .frame(width: 32, height: 32)
            
            // Title
            Text(topic.title)
                .font(.system(size: CasinoDesign.BaseFontSize.body, weight: .medium))
                .foregroundStyle(.white)
            
            Spacer()
            
            // Chevron
            Image(systemName: "chevron.right")
                .font(.system(size: CasinoDesign.BaseFontSize.callout, weight: .semibold))
                .foregroundStyle(.white.opacity(CasinoDesign.Opacity.medium))
        }
        .padding(.horizontal, CasinoDesign.Spacing.medium)
        .padding(.vertical, CasinoDesign.Spacing.small + CasinoDesign.Spacing.xSmall)
        .background(
            RoundedRectangle(cornerRadius: CasinoDesign.CornerRadius.medium)
                .fill(Color.Sheet.sectionFill)
        )
        .accessibilityElement(children: .combine)
        .accessibilityAddTraits(.isButton)
    }
}

// MARK: - Rule Detail View

/// A detail view showing the content of a single rule topic.
struct RuleDetailView: View {
    let topic: RuleTopic
    
    @ScaledMetric(relativeTo: .body) private var bodySize: CGFloat = CasinoDesign.BaseFontSize.body
    @ScaledMetric(relativeTo: .subheadline) private var subheadSize: CGFloat = CasinoDesign.BaseFontSize.callout
    
    var body: some View {
        ZStack {
            Color.Sheet.background
                .ignoresSafeArea()
            
            ScrollView {
                VStack(alignment: .leading, spacing: CasinoDesign.Spacing.small) {
                    ForEach(topic.content.indices, id: \.self) { index in
                        contentRow(for: topic.content[index])
                    }
                    
                    Spacer(minLength: CasinoDesign.Spacing.xxLarge)
                }
                .padding(.horizontal, CasinoDesign.Spacing.large)
                .padding(.top, CasinoDesign.Spacing.medium)
            }
        }
        .navigationBarTitleDisplayMode(.inline)
        .toolbarBackground(Color.Sheet.background, for: .navigationBar)
        .toolbarBackground(.visible, for: .navigationBar)
        .toolbarColorScheme(.dark, for: .navigationBar)
        .toolbar {
            ToolbarItem(placement: .principal) {
                HStack(spacing: CasinoDesign.Spacing.small) {
                    Image(systemName: topic.icon)
                        .font(.system(size: 22, weight: .semibold))
                        .foregroundStyle(Color.Sheet.accent)
                    
                    Text(topic.title)
                        .font(.system(size: 22, weight: .semibold))
                        .foregroundStyle(.white)
                }
            }
        }
    }
    
    /// Determines how to render each content line based on its format.
    @ViewBuilder
    private func contentRow(for text: String) -> some View {
        if text.isEmpty {
            // Empty line = spacer
            Spacer()
                .frame(height: CasinoDesign.Spacing.small)
        } else if text.hasSuffix(":") {
            // Section header (ends with colon)
            Text(text)
                .font(.system(size: subheadSize, weight: .semibold))
                .foregroundStyle(Color.Sheet.accent)
                .padding(.top, CasinoDesign.Spacing.small)
        } else {
            // Regular bullet point
            HStack(alignment: .firstTextBaseline, spacing: CasinoDesign.Spacing.small) {
                Text("•")
                    .foregroundStyle(Color.Sheet.accent.opacity(CasinoDesign.Opacity.medium))
                
                Text(text)
                    .font(.system(size: bodySize))
                    .foregroundStyle(.white.opacity(CasinoDesign.Opacity.heavy))
            }
        }
    }
}

// MARK: - Hashable Conformance for Navigation

extension RuleTopic: Hashable {
    public static func == (lhs: RuleTopic, rhs: RuleTopic) -> Bool {
        lhs.id == rhs.id
    }
    
    public func hash(into hasher: inout Hasher) {
        hasher.combine(id)
    }
}

// MARK: - Previews

#Preview("Rules List") {
    RulesListView(
        title: "How to Play",
        topics: [
            RuleTopic(
                title: "Objective",
                icon: "target",
                content: [
                    "Beat the dealer by getting closer to 21.",
                    "Don't go over 21 or you bust.",
                    "Dealer must hit on 16 or less."
                ]
            ),
            RuleTopic(
                title: "Card Values",
                icon: "suit.spade.fill",
                content: [
                    "2-10: Face value",
                    "Jack, Queen, King: 10",
                    "Ace: 1 or 11"
                ]
            ),
            RuleTopic(
                title: "Blackjack",
                icon: "star.fill",
                content: [
                    "Ace + 10-value card = Blackjack",
                    "Pays 3:2",
                    "Beats regular 21"
                ]
            )
        ]
    )
}
