import ComponentLibrary
import ComposableArchitecture
import SwiftUI

@Reducer
public struct BrandedAlertWalkthrough {
    @ObservableState
    public struct State: Equatable {
        var style: WalkthroughAlertStyle
        var currentPageIndex: Int = 0

        var hasNextPage: Bool {
            currentPageIndex < (style.textCopy.pages.count - 1)
        }

        var hasPreviousPage: Bool {
            currentPageIndex > 0
        }

        var currentPage: WalkthroughAlertStyle.Page? {
            guard currentPageIndex < style.textCopy.pages.count else { return nil }
            return style.textCopy.pages[currentPageIndex]
        }

        let cardWidth: CGFloat = 320.0

        var cardHeight: CGFloat {
            return UIScreen.isCompact ? 520.0 : 580.0
        }

        var landingImageSize: CGFloat {
            return UIScreen.isCompact ? 260.0 : 300.0
        }

        var walkthroughImageSize: CGFloat {
            return UIScreen.isCompact ? 188.0 : 248.0
        }
    }

    public enum Action: BindableAction {
        case delegate(Delegate)
        case binding(BindingAction<State>)
        case nextPage
        case previousPage
        case primaryButtonTapped
        case exitTapped

        public enum Delegate {
            case goToLibraryForVideoSongArt
            case tappedPrimaryButton
            case exitButton
        }
    }

    public init() {}

    public var body: some ReducerOf<Self> {
        BindingReducer()
        Reduce<State, Action> { state, action in
            switch action {
            case .nextPage:
                guard state.hasNextPage else { return .none }
                state.currentPageIndex += 1
                return .none

            case .previousPage:
                guard state.hasPreviousPage else { return .none }
                state.currentPageIndex -= 1
                return .none

            case .exitTapped:
                return .send(.delegate(.exitButton))

            case .primaryButtonTapped:
                switch state.style.tapAction {
                case .exitToLibrary:
                    return .send(.delegate(.goToLibraryForVideoSongArt))
                }

            case .delegate, .binding:
                return .none
            }
        }
    }
}

public struct BrandedAlertWalkthroughView: View {
    @Bindable var store: StoreOf<BrandedAlertWalkthrough>

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

    public var body: some View {
        ZStack {
            VStack(spacing: .zero) {
                alertCopyStack
                Spacer()
                ctaButtons
            }
            dismissButton
                .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topTrailing)
                .padding([.top, .trailing], 20.0)
        }
        .frame(width: store.cardWidth, height: store.cardHeight)
        .background {
            ZStack {
                Color.SemanticV2.backgroundSecondary
                LinearGradient(
                    colors: [Color.SemanticV1.auraPink.opacity(0.5), Color.SemanticV2.backgroundSecondary],
                    startPoint: .top,
                    endPoint: .center
                )
                .ignoresSafeArea()
            }
        }
        .clipShape(.rect(cornerRadius: 24.0))
    }
}

private extension BrandedAlertWalkthroughView {
    @ViewBuilder
    var alertCopyStack: some View {
        VStack(spacing: .zero) {
            // Image carousel
            TabView(selection: $store.currentPageIndex) {
                ForEach(Array(copyData.pages.enumerated()), id: \.offset) { index, page in
                    let imageSize = index == 0 ? store.landingImageSize : store.walkthroughImageSize
                    let paddingAboveText = index == 0 ? 0.0 : 18.0
                    let paddingAboveImage = index == 0 ? 0.0 : 48.0
                    VStack(spacing: .zero) {
                        imageStack(url: page.assetId)
                            .frame(width: imageSize, height: imageSize)
                        if let label = copyData.titleTagLabel, index == 0 {
                            titleTagLabel(label)
                                .padding(.bottom, 14)
                        }
                        VStack(spacing: 9) {
                            Text(page.title)
                                .typographyV1(.headline1.size { _ in 40.0 })
                                .foregroundStyle(Color.SemanticV1.textPrimary)
                                .multilineTextAlignment(.center)
                                .minimumScaleFactor(0.4)
                            if let description = page.description {
                                Text(description)
                                    .typographyV1(.body2thin)
                                    .foregroundStyle(Color.SemanticV1.iconBrand)
                                    .multilineTextAlignment(.center)
                                    .minimumScaleFactor(0.6)
                            }
                        }
                        .padding(.horizontal, 20)
                        .padding(.top, paddingAboveText)
                        if index > 0 {
                            Spacer()
                        }
                    }
                    .padding(.top, paddingAboveImage)
                    .tag(index)
                }
            }
            .tabViewStyle(.page(indexDisplayMode: .never))
            .tint(Color.SemanticV2.foregroundPrimary)
            .animation(.easeInOut(duration: 0.2), value: store.currentPageIndex)
        }
        .padding(.top, 16)
    }

    @ViewBuilder
    func titleTagLabel(_ label: String) -> some View {
        Text(label)
            .typographyV1(.caption.size { _ in 10.0 }.neueMontrealMedium())
            .minimumScaleFactor(0.6)
            .foregroundStyle(Color.SemanticV1.textPrimary)
            .padding(.vertical, 4)
            .padding(.horizontal, 8)
            .background {
                Capsule()
                    .fill(Color.SemanticV1.likePink)
                    .shadow(color: Color.SemanticV1.likePink, radius: 4.0)
            }
            .frame(maxWidth: .infinity, alignment: .center)
            .environment(\.colorScheme, .light)
    }

    @ViewBuilder
    func imageStack(url: String) -> some View {
        ZStack {
            Color.clear
            if let url = URL(string: url) {
                GifWebView(url: url)
                    .aspectRatio(contentMode: .fill)
            }
        }
        .clipShape(RoundedRectangle(cornerRadius: 10))
    }

    @ViewBuilder
    var dismissButton: some View {
        Button {
            store.send(.exitTapped)
        } label: {
            Image.Icon.close
                .resizable()
                .aspectRatio(contentMode: .fit)
                .frame(width: 30.0, height: 30.0)
                .foregroundStyle(Color.SemanticV2.foregroundPrimary)
                .background(
                    Circle()
                        .fill(Color.SemanticV1.backgroundQuaternary)
                        .frame(width: 44.0, height: 44.0)
                )
        }
    }

    @ViewBuilder
    var ctaButtons: some View {
        VStack(spacing: 4) {
            // Primary button (always present)
            if let primaryButton = store.currentPage?.primaryButton {
                Button {
                    switch primaryButton {
                    case .next, .learnHow:
                        store.send(.nextPage)
                    case .previous:
                        store.send(.previousPage)
                    case .tryNow:
                        store.send(.primaryButtonTapped)
                    }
                } label: {
                    ZStack {
                        Capsule()
                            .fill(Color.SemanticV2.foregroundPrimary)
                        Text(primaryButton.displayText)
                            .typographyV1(.button1)
                            .foregroundStyle(Color.SemanticV2.backgroundPrimary)
                    }
                }
                .contentShape(.rect)
                .frame(height: 50.0)
            }
            // Secondary button if configured
            if let secondaryButton = store.currentPage?.secondaryButton {
                Button {
                    switch secondaryButton {
                    case .next, .learnHow:
                        store.send(.nextPage)
                    case .previous:
                        store.send(.previousPage)
                    case .tryNow:
                        store.send(.primaryButtonTapped)
                    }
                } label: {
                    Text(secondaryButton.displayText)
                        .typographyV1(.button1)
                        .foregroundStyle(Color.SemanticV1.textPrimary)
                }
                .contentShape(.rect)
                .frame(height: 50.0)
            }
        }
        .padding([.horizontal, .bottom], 20.0)
        .padding(.top, 8)
    }

    var copyData: WalkthroughAlertStyle.TextCopy {
        store.style.textCopy
    }
}
