import SwiftUI

/// UIPageViewController wrapper that handles paging entirely in UIKit.
/// Exposes both the settled page index AND a continuous drag progress for smooth dot tracking.
struct OnboardingPager<Page: View>: UIViewControllerRepresentable {
    @Binding var currentIndex: Int
    /// Continuous progress: 0.0 = page 0, 1.0 = page 1, etc. Tracks the finger in real time.
    @Binding var continuousProgress: CGFloat
    let count: Int
    let buildPage: (Int) -> Page

    func makeCoordinator() -> Coordinator { Coordinator(self) }

    func makeUIViewController(context: Context) -> UIPageViewController {
        let vc = UIPageViewController(
            transitionStyle: .scroll,
            navigationOrientation: .horizontal
        )
        vc.view.backgroundColor = .clear
        vc.dataSource = context.coordinator
        vc.delegate = context.coordinator
        vc.setViewControllers(
            [context.coordinator.controllers[currentIndex]],
            direction: .forward,
            animated: false
        )
        // Hook into the inner scroll view for real-time offset tracking
        for sub in vc.view.subviews {
            if let scrollView = sub as? UIScrollView {
                scrollView.backgroundColor = .clear
                scrollView.delegate = context.coordinator
                context.coordinator.pageWidth = scrollView.frame.width
            }
        }
        return vc
    }

    func updateUIViewController(_ vc: UIPageViewController, context: Context) {
        context.coordinator.parent = self
    }

    // MARK: - Coordinator

    final class Coordinator: NSObject,
        UIPageViewControllerDataSource,
        UIPageViewControllerDelegate,
        UIScrollViewDelegate
    {
        var parent: OnboardingPager
        let controllers: [UIHostingController<Page>]
        var pageWidth: CGFloat = 0
        private var pendingIndex: Int = 0

        init(_ parent: OnboardingPager) {
            self.parent = parent
            self.pendingIndex = parent.currentIndex
            self.controllers = (0..<parent.count).map { i in
                let hc = UIHostingController(rootView: parent.buildPage(i))
                hc.view.backgroundColor = .clear
                return hc
            }
        }

        deinit {}

        // MARK: DataSource

        func pageViewController(
            _ pvc: UIPageViewController,
            viewControllerBefore vc: UIViewController
        ) -> UIViewController? {
            guard let idx = controllers.firstIndex(where: { $0 === vc }), idx > 0 else { return nil }
            return controllers[idx - 1]
        }

        func pageViewController(
            _ pvc: UIPageViewController,
            viewControllerAfter vc: UIViewController
        ) -> UIViewController? {
            guard let idx = controllers.firstIndex(where: { $0 === vc }),
                  idx < parent.count - 1 else { return nil }
            return controllers[idx + 1]
        }

        // MARK: Delegate

        func pageViewController(
            _ pvc: UIPageViewController,
            willTransitionTo pendingVCs: [UIViewController]
        ) {
            if let vc = pendingVCs.first,
               let idx = controllers.firstIndex(where: { $0 === vc }) {
                pendingIndex = idx
            }
        }

        func pageViewController(
            _ pvc: UIPageViewController,
            didFinishAnimating finished: Bool,
            previousViewControllers: [UIViewController],
            transitionCompleted completed: Bool
        ) {
            guard completed,
                  let current = pvc.viewControllers?.first,
                  let idx = controllers.firstIndex(where: { $0 === current }) else { return }
            parent.currentIndex = idx
        }

        // MARK: ScrollView — real-time progress

        func scrollViewDidScroll(_ scrollView: UIScrollView) {
            let w = scrollView.frame.width
            guard w > 0 else { return }
            // UIPageViewController's scroll view rests at x = width.
            // Dragging left (next page) increases x; dragging right decreases.
            let offsetFromCenter = scrollView.contentOffset.x - w
            let fraction = offsetFromCenter / w
            let progress = CGFloat(parent.currentIndex) + fraction
            parent.continuousProgress = max(0, min(CGFloat(parent.count - 1), progress))
        }
    }
}
