import ComponentLibrary
import ComposableArchitecture
import Localization
import StoreKit
import SwiftUI
import Utilities

@Reducer
public struct RatingTracker {
    @ObservableState
    public struct State: Equatable {
        @Shared(.appStorage(.likeCount)) var likeCount: Int = 0
        @Shared(.appStorage(.shareCount)) var shareCount: Int = 0
        @Shared(.appStorage(.addedToPlaylist)) var addedToPlaylist: Int = 0
        @Shared(.appStorage(.songCreateCount)) var songCreateCount: Int = 0
        @Shared(.appStorage(.hasRated)) var hasRated: Bool = false
        @Shared(.appStorage(.lastRatingRequestSeen)) var lastRatingRequestSeen: TimeInterval = 0

        var shouldShowRatingRequest: Bool {
            // Only show to those that haven't already rated
            // One month between prompts
            guard !hasRated,
                  Date().timeIntervalSince1970 - lastRatingRequestSeen > 60 * 60 * 24 * 30 else { return false }

            if likeCount >= 3 ||
                addedToPlaylist >= 5 ||
                songCreateCount >= 10 ||
                shareCount >= 2
            {
                return true
            }
            return false
        }

        public init() {}
    }

    public enum Action {
        case delegate(Delegate)
        case like
        case create(Int)
        case addToPlaylist
        case share
        case checkIfReviewPromptShouldBeShown
        case rateSuno(RequestReviewAction)
        case dismiss

        public enum Delegate {
            case rateRequestTriggered
        }
    }

    public init() {}

    public var body: some ReducerOf<Self> {
        Reduce { state, action in
            switch action {
            case .like:
                state.$likeCount.withLock { $0 += 1 }
                return .send(.checkIfReviewPromptShouldBeShown)

            case .create(let count):
                state.$songCreateCount.withLock { $0 += count }
                return .send(.checkIfReviewPromptShouldBeShown)

            case .addToPlaylist:
                state.$addedToPlaylist.withLock { $0 += 1 }
                return .send(.checkIfReviewPromptShouldBeShown)

            case .share:
                state.$shareCount.withLock { $0 += 1 }
                return .send(.checkIfReviewPromptShouldBeShown)

            case .checkIfReviewPromptShouldBeShown:
                if state.shouldShowRatingRequest {
                    return .run { send in
                        try await Task.sleep(for: .seconds(1))
                        await send(.delegate(.rateRequestTriggered))
                    }
                }
                return .none

            case .rateSuno(let action):
                state.$hasRated.withLock { $0 = true }
                return .run { send in
                    await action()
                    await send(.dismiss)
                }

            case .dismiss:
                state.$lastRatingRequestSeen.withLock { $0 = Date().timeIntervalSince1970 }
                return .send(.delegate(.rateRequestTriggered))

            case .delegate:
                return .none
            }
        }

        Analytics()
    }
}

public struct RatingTrackerScreen: View {
    @Environment(\.requestReview) var requestReview

    private let store: StoreOf<RatingTracker>

    public init(store: StoreOf<RatingTracker>) {
        self.store = store
    }

    public var body: some View {
        review
    }

    @ViewBuilder
    private var review: some View {
        VStack(spacing: 16) {
            Spacer()

            Text(L10n.FeatureRatingTracker.ratingTitle)
                .typographyV1(.headline1)
                .foregroundColor(Color.SemanticV1.textOnDark)
                .multilineTextAlignment(.center)
                .padding(.horizontal, 16)

            Text(L10n.FeatureRatingTracker.ratingMessage)
                .typographyV1(.caption.neueMontrealMedium())
                .foregroundColor(Color.SemanticV1.textOnDark)
                .multilineTextAlignment(.center)
                .padding(.horizontal, 32)

            Spacer()

            HStack(alignment: .center) {
                Button {
                    store.send(.dismiss)
                } label: {
                    Text(L10n.FeatureRatingTracker.ratingNo)
                        .typographyV1(.body3)
                        .foregroundColor(Color.SemanticV1.textSecondary)
                        .padding(4.0)
                }
                .frame(maxWidth: .infinity)

                Divider()

                Button {
                    store.send(.rateSuno(requestReview))
                } label: {
                    Text(L10n.FeatureRatingTracker.ratingYes)
                        .typographyV1(.body3)
                        .foregroundColor(Color.SemanticV1.textPrimary)
                        .padding(4.0)
                }
                .frame(maxWidth: .infinity)
            }
            .frame(height: 56)
            .background(Color.SemanticV1.backgroundQuaternary)
        }
        .frame(width: 320, height: 364)
        .background {
            Image.Assets.rateBackground
                .resizable()
                .aspectRatio(contentMode: .fill)
        }
        .clipShape(RoundedRectangle(cornerRadius: 24.0))
    }
}
