import SwiftUI
import Photos

// MARK: - PhotoGridView

/// Custom photo library grid matching Figma attachment panel design (1:1).
///
/// Figma layout (node 3994:39103):
/// ```
/// ┌──────────┬──────────┬──────────┐
/// │          │ Photo[0] │ Photo[1] │  ← row 1
/// │  Camera  ├──────────┼──────────┤
/// │  (live)  │ Photo[2] │ Photo[3] │  ← row 2
/// └──────────┴──────────┴──────────┘
/// ┌──────────┬──────────┬──────────┐
/// │ Photo[4] │ Photo[5] │ Photo[6] │  ← row 3 (LazyVGrid)
/// └──────────┴──────────┴──────────┘
/// ```
///
/// Camera tile: col 1, rows 1–2, shows live rear camera feed (AVCaptureSession).
/// Photos: square tiles with selection circle (22pt, white border 1.5pt).
/// 1px spacing between all tiles.
struct PhotoGridView: View {

    @Binding var selectedAssets: [PHAsset]
    let maxSelection: Int
    let onCameraTap: () -> Void
    var onPhotoPreview: ((PHAsset) -> Void)? = nil

    @State private var assets: [PHAsset] = []
    @State private var authorizationStatus: PHAuthorizationStatus = .notDetermined

    private let imageManager = PHCachingImageManager()
    private let columns = 3
    private let spacing: CGFloat = 1

    var body: some View {
        Group {
            switch authorizationStatus {
            case .authorized, .limited:
                photoGrid
            case .denied, .restricted:
                permissionDeniedView
            default:
                requestingView
            }
        }
        .task {
            await requestPhotoAccess()
        }
    }

    // MARK: - Photo Grid

    private var photoGrid: some View {
        GeometryReader { geometry in
            let tileSize = (geometry.size.width - spacing * CGFloat(columns - 1)) / CGFloat(columns)
            let cameraHeight = tileSize * 2 + spacing

            ScrollView {
                VStack(spacing: spacing) {
                    // Header: Camera (2 rows) + 4 photos (2×2 grid)
                    headerSection(tileSize: tileSize, cameraHeight: cameraHeight)

                    // Remaining photos: standard 3-column grid
                    remainingPhotosGrid(tileSize: tileSize, startIndex: 4)
                }
                .padding(.bottom, 100) // Space for tab bar + send button
            }
        }
    }

    /// Header section: Camera tile (col 1, rows 1-2) + 4 photos (cols 2-3, rows 1-2).
    @ViewBuilder
    private func headerSection(tileSize: CGFloat, cameraHeight: CGFloat) -> some View {
        HStack(alignment: .top, spacing: spacing) {
            // Camera tile — spans 2 rows (double height)
            CameraPreviewTile(
                width: tileSize,
                height: cameraHeight,
                onTap: onCameraTap
            )

            // Right side: 2 rows × 2 columns of photos
            VStack(spacing: spacing) {
                // Row 1: photos[0], photos[1]
                HStack(spacing: spacing) {
                    headerPhotoTile(index: 0, size: tileSize)
                    headerPhotoTile(index: 1, size: tileSize)
                }

                // Row 2: photos[2], photos[3]
                HStack(spacing: spacing) {
                    headerPhotoTile(index: 2, size: tileSize)
                    headerPhotoTile(index: 3, size: tileSize)
                }
            }
        }
    }

    /// Single photo tile in the header section.
    @ViewBuilder
    private func headerPhotoTile(index: Int, size: CGFloat) -> some View {
        if index < assets.count {
            let asset = assets[index]
            let isSelected = selectedAssets.contains(where: { $0.localIdentifier == asset.localIdentifier })
            let selectionIndex = selectedAssets.firstIndex(where: { $0.localIdentifier == asset.localIdentifier })

            PhotoTile(
                asset: asset,
                imageManager: imageManager,
                size: size,
                isSelected: isSelected,
                selectionNumber: selectionIndex.map { $0 + 1 },
                onTap: { handlePhotoTap(asset) },
                onCircleTap: { toggleSelection(asset) }
            )
            .frame(width: size, height: size)
        } else {
            Color(white: 0.15)
                .frame(width: size, height: size)
        }
    }

    /// Remaining photos after the header, displayed as a standard 3-column LazyVGrid.
    @ViewBuilder
    private func remainingPhotosGrid(tileSize: CGFloat, startIndex: Int) -> some View {
        let remaining = assets.count > startIndex ? Array(assets[startIndex...]) : []

        LazyVGrid(
            columns: Array(repeating: GridItem(.flexible(), spacing: spacing), count: columns),
            spacing: spacing
        ) {
            ForEach(0..<remaining.count, id: \.self) { index in
                let asset = remaining[index]
                let isSelected = selectedAssets.contains(where: { $0.localIdentifier == asset.localIdentifier })
                let selectionIndex = selectedAssets.firstIndex(where: { $0.localIdentifier == asset.localIdentifier })

                PhotoTile(
                    asset: asset,
                    imageManager: imageManager,
                    size: tileSize,
                    isSelected: isSelected,
                    selectionNumber: selectionIndex.map { $0 + 1 },
                    onTap: { handlePhotoTap(asset) },
                    onCircleTap: { toggleSelection(asset) }
                )
                .frame(height: tileSize)
            }
        }
    }

    // MARK: - Permission Views

    private var requestingView: some View {
        VStack(spacing: 16) {
            ProgressView()
                .tint(.white)
            Text("Requesting photo access...")
                .font(.system(size: 15))
                .foregroundStyle(.white.opacity(0.6))
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
    }

    private var permissionDeniedView: some View {
        VStack(spacing: 16) {
            Image(systemName: "photo.on.rectangle.angled")
                .font(.system(size: 40))
                .foregroundStyle(.white.opacity(0.4))

            Text("Photo Access Required")
                .font(.system(size: 17, weight: .semibold))
                .foregroundStyle(.white)

            Text("Enable photo access in Settings to send images.")
                .font(.system(size: 14))
                .foregroundStyle(.white.opacity(0.6))
                .multilineTextAlignment(.center)
                .padding(.horizontal, 40)

            Button("Open Settings") {
                if let url = URL(string: UIApplication.openSettingsURLString) {
                    UIApplication.shared.open(url)
                }
            }
            .font(.system(size: 15, weight: .medium))
            .foregroundStyle(RosettaColors.primaryBlue)
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
    }

    // MARK: - Logic

    private func requestPhotoAccess() async {
        let status = await PHPhotoLibrary.requestAuthorization(for: .readWrite)
        await MainActor.run {
            authorizationStatus = status
            if status == .authorized || status == .limited {
                loadAssets()
            }
        }
    }

    private func loadAssets() {
        let options = PHFetchOptions()
        options.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
        options.fetchLimit = 500
        let result = PHAsset.fetchAssets(with: .image, options: options)
        var fetched: [PHAsset] = []
        result.enumerateObjects { asset, _, _ in
            fetched.append(asset)
        }
        assets = fetched
    }

    /// Handles tap on the photo body (not the selection circle).
    /// Always opens preview — selection is handled by the circle tap only.
    private func handlePhotoTap(_ asset: PHAsset) {
        onPhotoPreview?(asset)
    }

    private func toggleSelection(_ asset: PHAsset) {
        if let index = selectedAssets.firstIndex(where: { $0.localIdentifier == asset.localIdentifier }) {
            selectedAssets.remove(at: index)
        } else if selectedAssets.count < maxSelection {
            selectedAssets.append(asset)
        }
    }
}

// MARK: - CameraPreviewTile

/// Camera tile with live AVCaptureSession preview.
///
/// Figma: col 1, rows 1–2 in attachment grid. Shows live rear camera feed
/// with a camera icon overlay in the top-right corner.
/// Tapping opens full-screen UIImagePickerController for capture.
private struct CameraPreviewTile: View {
    let width: CGFloat
    let height: CGFloat
    let onTap: () -> Void

    var body: some View {
        ZStack(alignment: .topTrailing) {
            // Live camera preview (or placeholder on simulator)
            CameraPreviewView()
                .frame(width: width, height: height)
                .clipped()

            // Camera icon overlay (Figma: top-right)
            Image(systemName: "camera.fill")
                .font(.system(size: 18))
                .foregroundStyle(.white)
                .shadow(color: .black.opacity(0.5), radius: 2, x: 0, y: 1)
                .padding(8)
        }
        .frame(width: width, height: height)
        .contentShape(Rectangle())
        .onTapGesture(perform: onTap)
    }
}

// MARK: - PhotoTile

/// Single photo tile in the grid with async thumbnail loading and selection circle.
///
/// Figma: square aspect ratio, selection circle (22pt, white border 1.5pt) in
/// top-right corner with 6pt padding. Selected: blue #008BFF filled circle
/// with white number.
///
/// Two tap targets:
/// - Photo body (`onTap`): selects if unselected, opens preview if selected
/// - Selection circle (`onCircleTap`): always toggles selection (deselects if selected)
private struct PhotoTile: View {
    let asset: PHAsset
    let imageManager: PHCachingImageManager
    let size: CGFloat
    let isSelected: Bool
    let selectionNumber: Int?
    let onTap: () -> Void
    let onCircleTap: () -> Void

    @State private var thumbnail: UIImage?

    var body: some View {
        ZStack(alignment: .topTrailing) {
            // Photo thumbnail — body tap
            Group {
                if let thumbnail {
                    Image(uiImage: thumbnail)
                        .resizable()
                        .scaledToFill()
                        .frame(width: size, height: size)
                        .clipped()
                } else {
                    Color(white: 0.15)
                        .frame(width: size, height: size)
                }
            }
            .contentShape(Rectangle())
            .onTapGesture(perform: onTap)

            // Selection circle (Figma: 22pt, top-right, 6pt inset) — circle tap
            selectionCircle
                .padding(6)
                .contentShape(Circle())
                .onTapGesture(perform: onCircleTap)
        }
        .task(id: asset.localIdentifier) {
            loadThumbnail()
        }
    }

    @ViewBuilder
    private var selectionCircle: some View {
        if isSelected {
            ZStack {
                Circle()
                    .fill(Color(hex: 0x008BFF))
                    .frame(width: 22, height: 22)
                if let number = selectionNumber {
                    Text("\(number)")
                        .font(.system(size: 12, weight: .bold))
                        .foregroundStyle(.white)
                }
            }
        } else {
            Circle()
                .strokeBorder(Color.white, lineWidth: 1.5)
                .frame(width: 22, height: 22)
        }
    }

    private func loadThumbnail() {
        let scale = UIScreen.main.scale
        let targetSize = CGSize(width: size * scale, height: size * scale)
        let options = PHImageRequestOptions()
        options.deliveryMode = .opportunistic
        options.isNetworkAccessAllowed = true
        options.resizeMode = .fast

        imageManager.requestImage(
            for: asset,
            targetSize: targetSize,
            contentMode: .aspectFill,
            options: options
        ) { image, _ in
            if let image {
                DispatchQueue.main.async {
                    self.thumbnail = image
                }
            }
        }
    }
}
