//
//  ShareCardComponents.swift
//  SportsTime
//
//  Shared building blocks for the new shareable card system.
//

import SwiftUI
import MapKit
import UIKit

// MARK: - Card Background

struct ShareCardBackground: View {
    let theme: ShareTheme
    var sports: Set<Sport>? = nil

    var body: some View {
        ShareCardSportBackground(sports: sports ?? [], theme: theme)
    }
}

// MARK: - Card Header

struct ShareCardHeader: View {
    let title: String
    let sport: Sport?
    let theme: ShareTheme

    var body: some View {
        VStack(alignment: .leading, spacing: 16) {
            HStack(alignment: .center, spacing: 18) {
                if let sport = sport {
                    ZStack {
                        RoundedRectangle(cornerRadius: 20)
                            .fill(theme.accentColor.opacity(0.22))
                            .frame(width: 88, height: 88)

                        RoundedRectangle(cornerRadius: 20)
                            .stroke(theme.accentColor.opacity(0.65), lineWidth: 1.5)
                            .frame(width: 88, height: 88)

                        Image(systemName: sport.iconName)
                            .font(.system(size: 40, weight: .bold))
                            .foregroundStyle(theme.accentColor)
                    }
                    .shadow(color: .black.opacity(0.22), radius: 10, y: 6)
                }

                VStack(alignment: .leading, spacing: 7) {
                    Text("SPORTSTIME")
                        .font(.system(size: 15, weight: .bold))
                        .tracking(5)
                        .foregroundStyle(theme.secondaryTextColor)

                    Text(title)
                        .font(.system(size: 47, weight: .black, design: .default))
                        .foregroundStyle(theme.textColor)
                        .lineLimit(2)
                        .minimumScaleFactor(0.65)
                        .fixedSize(horizontal: false, vertical: true)
                }

                Spacer(minLength: 0)
            }

            Capsule()
                .fill(
                    LinearGradient(
                        colors: theme.highlightGradient,
                        startPoint: .leading,
                        endPoint: .trailing
                    )
                )
                .frame(height: 4)
        }
        .padding(.horizontal, 26)
        .padding(.vertical, 22)
        .background(
            RoundedRectangle(cornerRadius: 30)
                .fill(theme.surfaceColor)
                .overlay(
                    RoundedRectangle(cornerRadius: 30)
                        .stroke(theme.borderColor, lineWidth: 1)
                )
        )
    }
}

// MARK: - Card Footer

struct ShareCardFooter: View {
    let theme: ShareTheme

    var body: some View {
        HStack(spacing: 14) {
            Text("SPORTSTIME")
                .font(.system(size: 16, weight: .black))
                .tracking(3.5)
                .foregroundStyle(theme.accentColor)

            Capsule()
                .fill(theme.borderColor)
                .frame(width: 26, height: 2)

            Text("build your next game-day route")
                .font(.system(size: 15, weight: .medium))
                .foregroundStyle(theme.secondaryTextColor)

            Spacer(minLength: 0)
        }
        .padding(.horizontal, 18)
        .padding(.vertical, 14)
        .background(
            RoundedRectangle(cornerRadius: 16)
                .fill(theme.surfaceColor)
                .overlay(
                    RoundedRectangle(cornerRadius: 16)
                        .stroke(theme.borderColor, lineWidth: 1)
                )
        )
    }
}

// MARK: - Stats Row

struct ShareStatsRow: View {
    let stats: [(value: String, label: String)]
    let theme: ShareTheme

    var body: some View {
        HStack(spacing: 14) {
            ForEach(Array(stats.enumerated()), id: \.offset) { _, stat in
                VStack(spacing: 7) {
                    Text(stat.value)
                        .font(.system(size: 44, weight: .black, design: .rounded))
                        .foregroundStyle(theme.accentColor)
                        .minimumScaleFactor(0.7)
                        .lineLimit(1)

                    Text(stat.label.uppercased())
                        .font(.system(size: 13, weight: .bold))
                        .tracking(2.2)
                        .foregroundStyle(theme.secondaryTextColor)
                        .lineLimit(1)
                }
                .frame(maxWidth: .infinity)
                .padding(.vertical, 18)
                .background(
                    RoundedRectangle(cornerRadius: 18)
                        .fill(theme.surfaceColor)
                        .overlay(
                            RoundedRectangle(cornerRadius: 18)
                                .stroke(theme.borderColor, lineWidth: 1)
                        )
                )
            }
        }
    }
}

// MARK: - Progress Ring

struct ShareProgressRing: View {
    let current: Int
    let total: Int
    let theme: ShareTheme
    var size: CGFloat = 340
    var lineWidth: CGFloat = 30

    private let segmentCount = 72

    private var progress: Double {
        guard total > 0 else { return 0 }
        return min(max(Double(current) / Double(total), 0), 1)
    }

    private var filledSegments: Int {
        Int(round(progress * Double(segmentCount)))
    }

    var body: some View {
        ZStack {
            ForEach(0..<segmentCount, id: \.self) { index in
                Capsule()
                    .fill(index < filledSegments ? theme.accentColor : theme.surfaceColor.opacity(0.90))
                    .frame(width: lineWidth * 0.62, height: lineWidth * 1.18)
                    .offset(y: -(size / 2 - lineWidth * 0.78))
                    .rotationEffect(.degrees(Double(index) * 360 / Double(segmentCount)))
            }

            ForEach([0.25, 0.50, 0.75], id: \.self) { mark in
                Circle()
                    .fill(theme.textColor.opacity(0.32))
                    .frame(width: 8, height: 8)
                    .offset(y: -(size / 2 - lineWidth * 0.20))
                    .rotationEffect(.degrees(mark * 360))
            }

            Circle()
                .stroke(theme.glowColor.opacity(0.45), lineWidth: 14)
                .blur(radius: 12)
                .frame(width: size - lineWidth * 1.4, height: size - lineWidth * 1.4)

            VStack(spacing: 4) {
                Text("\(current)")
                    .font(.system(size: 108, weight: .black, design: .rounded))
                    .foregroundStyle(theme.textColor)

                Text("of \(total)")
                    .font(.system(size: 27, weight: .light))
                    .foregroundStyle(theme.secondaryTextColor)
            }
        }
        .frame(width: size, height: size)
    }
}

// MARK: - Map Snapshot Generator

@MainActor
final class ShareMapSnapshotGenerator {

    func generateProgressMap(
        visited: [Stadium],
        remaining: [Stadium],
        theme: ShareTheme
    ) async -> UIImage? {
        let allStadiums = visited + remaining
        guard !allStadiums.isEmpty else { return nil }

        let options = MKMapSnapshotter.Options()
        options.region = calculateRegion(for: allStadiums)
        options.size = ShareCardDimensions.mapSnapshotSize
        options.mapType = theme.useDarkMap ? .mutedStandard : .standard

        let snapshotter = MKMapSnapshotter(options: options)

        do {
            let snapshot = try await snapshotter.start()
            return drawStadiumMarkers(
                on: snapshot,
                visited: visited,
                remaining: remaining,
                accentColor: UIColor(theme.accentColor)
            )
        } catch {
            return nil
        }
    }

    func generateRouteMap(
        stops: [TripStop],
        theme: ShareTheme
    ) async -> UIImage? {
        let validStops = stops.filter { $0.coordinate != nil }
        guard validStops.count >= 2 else { return nil }

        let options = MKMapSnapshotter.Options()
        options.region = calculateRegion(for: validStops.compactMap { $0.coordinate })
        options.size = ShareCardDimensions.routeMapSize
        options.mapType = theme.useDarkMap ? .mutedStandard : .standard

        let snapshotter = MKMapSnapshotter(options: options)

        do {
            let snapshot = try await snapshotter.start()
            return drawRoute(on: snapshot, stops: validStops, accentColor: UIColor(theme.accentColor))
        } catch {
            return nil
        }
    }

    private func calculateRegion(for stadiums: [Stadium]) -> MKCoordinateRegion {
        let coordinates = stadiums.map {
            CLLocationCoordinate2D(latitude: $0.latitude, longitude: $0.longitude)
        }
        return calculateRegion(for: coordinates)
    }

    private func calculateRegion(for coordinates: [CLLocationCoordinate2D]) -> MKCoordinateRegion {
        let minLat = coordinates.map(\.latitude).min() ?? 0
        let maxLat = coordinates.map(\.latitude).max() ?? 0
        let minLon = coordinates.map(\.longitude).min() ?? 0
        let maxLon = coordinates.map(\.longitude).max() ?? 0

        return MKCoordinateRegion(
            center: CLLocationCoordinate2D(
                latitude: (minLat + maxLat) / 2,
                longitude: (minLon + maxLon) / 2
            ),
            span: MKCoordinateSpan(
                latitudeDelta: max((maxLat - minLat) * 1.35, 1),
                longitudeDelta: max((maxLon - minLon) * 1.35, 1)
            )
        )
    }

    private func drawStadiumMarkers(
        on snapshot: MKMapSnapshotter.Snapshot,
        visited: [Stadium],
        remaining: [Stadium],
        accentColor: UIColor
    ) -> UIImage {
        UIGraphicsImageRenderer(size: ShareCardDimensions.mapSnapshotSize).image { context in
            snapshot.image.draw(at: .zero)

            for stadium in remaining {
                drawStadiumDot(
                    at: snapshot.point(for: CLLocationCoordinate2D(latitude: stadium.latitude, longitude: stadium.longitude)),
                    color: UIColor.systemGray3,
                    visited: false,
                    context: context.cgContext
                )
            }

            for stadium in visited {
                drawStadiumDot(
                    at: snapshot.point(for: CLLocationCoordinate2D(latitude: stadium.latitude, longitude: stadium.longitude)),
                    color: accentColor,
                    visited: true,
                    context: context.cgContext
                )
            }
        }
    }

    private func drawRoute(
        on snapshot: MKMapSnapshotter.Snapshot,
        stops: [TripStop],
        accentColor: UIColor
    ) -> UIImage {
        UIGraphicsImageRenderer(size: ShareCardDimensions.routeMapSize).image { context in
            snapshot.image.draw(at: .zero)

            let cg = context.cgContext
            let points = stops.compactMap { stop -> CGPoint? in
                guard let coord = stop.coordinate else { return nil }
                return snapshot.point(for: coord)
            }

            if let first = points.first {
                cg.setLineCap(.round)
                cg.setLineJoin(.round)

                cg.setStrokeColor(UIColor.black.withAlphaComponent(0.28).cgColor)
                cg.setLineWidth(11)
                cg.move(to: first)
                for point in points.dropFirst() {
                    cg.addLine(to: point)
                }
                cg.strokePath()

                cg.setStrokeColor(accentColor.cgColor)
                cg.setLineWidth(6)
                cg.move(to: first)
                for point in points.dropFirst() {
                    cg.addLine(to: point)
                }
                cg.strokePath()
            }

            for (index, stop) in stops.enumerated() {
                guard let coord = stop.coordinate else { continue }
                let point = snapshot.point(for: coord)
                let isFirst = index == 0
                let isLast = index == stops.count - 1

                drawCityLabel(
                    at: point,
                    label: isFirst ? "START" : isLast ? "FINISH" : String(stop.city.prefix(3)).uppercased(),
                    endpoint: isFirst || isLast,
                    color: accentColor,
                    context: cg
                )
            }
        }
    }

    private func drawStadiumDot(
        at point: CGPoint,
        color: UIColor,
        visited: Bool,
        context: CGContext
    ) {
        let size: CGFloat = 22

        context.setFillColor(UIColor.black.withAlphaComponent(0.28).cgColor)
        context.fillEllipse(in: CGRect(x: point.x - size / 2 - 3, y: point.y - size / 2 + 2, width: size + 6, height: size + 6))

        context.setFillColor(UIColor.white.cgColor)
        context.fillEllipse(in: CGRect(x: point.x - size / 2 - 2, y: point.y - size / 2 - 2, width: size + 4, height: size + 4))

        context.setFillColor(color.cgColor)
        context.fillEllipse(in: CGRect(x: point.x - size / 2, y: point.y - size / 2, width: size, height: size))

        if visited {
            context.setStrokeColor(UIColor.white.cgColor)
            context.setLineWidth(2.6)
            context.setLineCap(.round)
            context.setLineJoin(.round)

            context.move(to: CGPoint(x: point.x - 4.5, y: point.y + 0.5))
            context.addLine(to: CGPoint(x: point.x - 0.8, y: point.y + 4.6))
            context.addLine(to: CGPoint(x: point.x + 6.2, y: point.y - 3.2))
            context.strokePath()
        }
    }

    private func drawCityLabel(
        at point: CGPoint,
        label: String,
        endpoint: Bool,
        color: UIColor,
        context: CGContext
    ) {
        let dotSize: CGFloat = endpoint ? 22 : 17

        context.setFillColor(UIColor.white.cgColor)
        context.fillEllipse(in: CGRect(x: point.x - dotSize / 2 - 2, y: point.y - dotSize / 2 - 2, width: dotSize + 4, height: dotSize + 4))

        context.setFillColor(color.cgColor)
        context.fillEllipse(in: CGRect(x: point.x - dotSize / 2, y: point.y - dotSize / 2, width: dotSize, height: dotSize))

        let font = UIFont.systemFont(ofSize: endpoint ? 12.5 : 11, weight: .heavy)
        let attrs: [NSAttributedString.Key: Any] = [
            .font: font,
            .foregroundColor: UIColor.white
        ]

        let textSize = (label as NSString).size(withAttributes: attrs)
        let bgRect = CGRect(
            x: point.x - textSize.width / 2 - 11,
            y: point.y - dotSize / 2 - textSize.height - 12,
            width: textSize.width + 22,
            height: textSize.height + 8
        )

        let path = UIBezierPath(roundedRect: bgRect, cornerRadius: 9)
        context.setFillColor(color.withAlphaComponent(0.94).cgColor)
        context.addPath(path.cgPath)
        context.fillPath()

        (label as NSString).draw(
            in: CGRect(
                x: bgRect.origin.x + 11,
                y: bgRect.origin.y + 4,
                width: textSize.width,
                height: textSize.height
            ),
            withAttributes: attrs
        )
    }
}
