import SwiftUI
import Bedrock
import SwiftData

struct BusinessCardView: View {
    let card: BusinessCard
    var isCompact: Bool = false

    private var hasOverlappingContent: Bool {
        card.headerLayout.hasOverlappingContent
    }

    var body: some View {
        VStack(spacing: 0) {
            CardBannerView(card: card)
            
            CardContentView(card: card, isCompact: isCompact)
                .offset(y: hasOverlappingContent ? -Design.CardSize.avatarOverlap : 0)
                .padding(.bottom, hasOverlappingContent ? -Design.CardSize.avatarOverlap : 0)
        }
        .background(Color.AppBackground.elevated)
        .clipShape(.rect(cornerRadius: Design.CornerRadius.xLarge))
        .shadow(
            color: Color.Text.secondary.opacity(Design.Opacity.hint),
            radius: Design.Shadow.radiusLarge,
            x: Design.Shadow.offsetNone,
            y: Design.Shadow.offsetMedium
        )
        .accessibilityElement(children: .ignore)
        .accessibilityLabel(String.localized("Business card"))
        .accessibilityValue("\(card.fullName), \(card.role), \(card.company)")
    }
}

// MARK: - Banner View

private struct CardBannerView: View {
    let card: BusinessCard
    
    var body: some View {
        Group {
            switch card.headerLayout.bannerContent {
            case .profile:
                ProfileBannerContent(card: card)
            case .logo:
                LogoBannerContent(card: card)
            case .cover:
                CoverBannerContent(card: card)
            }
        }
        .frame(height: Design.CardSize.bannerHeight)
        .clipped()
    }
}

// MARK: - Profile Banner Content

private struct ProfileBannerContent: View {
    let card: BusinessCard
    
    var body: some View {
        GeometryReader { geometry in
            ZStack {
                if let photoData = card.photoData, let uiImage = UIImage(data: photoData) {
                    Image(uiImage: uiImage)
                        .resizable()
                        .scaledToFill()
                        .frame(width: geometry.size.width, height: geometry.size.height)
                        .clipped()
                } else {
                    LinearGradient(
                        colors: [card.theme.primaryColor, card.theme.secondaryColor],
                        startPoint: .topLeading,
                        endPoint: .bottomTrailing
                    )
                    
                    VStack(spacing: Design.Spacing.xSmall) {
                        Image(systemName: "person.fill")
                            .typography(.title2Bold)
                        Text("Profile")
                            .typography(.title3)
                            .bold()
                    }
                    .foregroundStyle(card.theme.textColor.opacity(Design.Opacity.medium))
                }
            }
        }
    }
}

// MARK: - Logo Banner Content

private struct LogoBannerContent: View {
    let card: BusinessCard
    
    var body: some View {
        GeometryReader { geometry in
            ZStack {
                LinearGradient(
                    colors: [card.theme.primaryColor, card.theme.secondaryColor],
                    startPoint: .topLeading,
                    endPoint: .bottomTrailing
                )
                
                if let logoData = card.logoData, let uiImage = UIImage(data: logoData) {
                    Image(uiImage: uiImage)
                        .resizable()
                        .scaledToFill()
                        .frame(width: geometry.size.width, height: geometry.size.height)
                        .clipped()
                } else {
                    VStack(spacing: Design.Spacing.xSmall) {
                        Image(systemName: "building.2.fill")
                            .typography(.title2Bold)
                        Text("Logo")
                            .typography(.title3)
                            .bold()
                    }
                    .foregroundStyle(card.theme.textColor.opacity(Design.Opacity.medium))
                }
            }
        }
    }
}

// MARK: - Cover Banner Content

private struct CoverBannerContent: View {
    let card: BusinessCard
    
    var body: some View {
        GeometryReader { geometry in
            if let coverPhotoData = card.coverPhotoData, let uiImage = UIImage(data: coverPhotoData) {
                Image(uiImage: uiImage)
                    .resizable()
                    .scaledToFill()
                    .frame(width: geometry.size.width, height: geometry.size.height)
                    .clipped()
            } else {
                ZStack {
                    LinearGradient(
                        colors: [card.theme.primaryColor, card.theme.secondaryColor],
                        startPoint: .topLeading,
                        endPoint: .bottomTrailing
                    )
                    
                    VStack(spacing: Design.Spacing.xSmall) {
                        Image(systemName: "photo.fill")
                            .typography(.title2Bold)
                        Text("Cover")
                            .typography(.title3)
                            .bold()
                    }
                    .foregroundStyle(card.theme.textColor.opacity(Design.Opacity.medium))
                }
            }
        }
    }
}

// MARK: - Content View

private struct CardContentView: View {
    let card: BusinessCard
    let isCompact: Bool
    
    private var textColor: Color { Color.Text.primary }
    
    private var userInfoTopPadding: CGFloat {
        card.headerLayout.contentOverlay == .none ? Design.Spacing.large : 0
    }
    
    var body: some View {
        VStack(alignment: .leading, spacing: Design.Spacing.medium) {
            contentOverlay
            
            VStack(alignment: .leading, spacing: Design.Spacing.xxSmall) {
                HStack(spacing: Design.Spacing.xSmall) {
                    Text(card.fullName)
                        .typography(.title2)
                        .bold()
                        .foregroundStyle(textColor)
                    
                    if !card.pronouns.isEmpty {
                        Text("(\(card.pronouns))")
                            .typography(.subheading)
                            .foregroundStyle(Color.Text.secondary)
                    }
                }
                
                Text(card.role)
                    .typography(.heading)
                    .foregroundStyle(textColor)
                
                Text(card.company)
                    .typography(.subheading)
                    .foregroundStyle(Color.Text.secondary)
                
                if !card.headline.isEmpty {
                    Text(card.headline)
                        .typography(.caption)
                        .foregroundStyle(Color.Text.secondary)
                        .padding(.top, Design.Spacing.xxSmall)
                }
            }
            .padding(.top, userInfoTopPadding)
            
            if !isCompact {
                Divider()
                    .padding(.vertical, Design.Spacing.xSmall)
                
                ContactFieldsListView(card: card)
            }
        }
        .padding(.horizontal, Design.Spacing.large)
        .padding(.bottom, Design.Spacing.large)
    }
    
    @ViewBuilder
    private var contentOverlay: some View {
        switch card.headerLayout.contentOverlay {
        case .none:
            EmptyView()
        case .avatar:
            HStack {
                ProfileAvatarView(card: card)
                Spacer()
            }
        case .logoRectangle:
            HStack {
                LogoRectangleView(card: card)
                Spacer()
            }
        case .avatarAndLogo:
            HStack(alignment: .bottom) {
                ProfileAvatarView(card: card)
                Spacer()
                LogoRectangleView(card: card)
            }
        }
    }
}

// MARK: - Profile Avatar

private struct ProfileAvatarView: View {
    let card: BusinessCard
    
    var body: some View {
        Group {
            if let photoData = card.photoData, let uiImage = UIImage(data: photoData) {
                Image(uiImage: uiImage)
                    .resizable()
                    .scaledToFill()
            } else {
                Image(systemName: card.avatarSystemName)
                    .typography(.title3)
                    .foregroundStyle(card.theme.textColor)
                    .frame(maxWidth: .infinity, maxHeight: .infinity)
                    .background(card.theme.accentColor)
            }
        }
        .frame(width: Design.CardSize.avatarLarge, height: Design.CardSize.avatarLarge)
        .clipShape(.circle)
        .overlay(Circle().stroke(Color.AppBackground.elevated, lineWidth: Design.LineWidth.thick))
        .shadow(color: Color.Text.secondary.opacity(Design.Opacity.hint), radius: Design.Shadow.radiusSmall, x: Design.Shadow.offsetNone, y: Design.Shadow.offsetSmall)
    }
}

// MARK: - Logo Badge View

private struct LogoBadgeView: View {
    let card: BusinessCard
    
    var body: some View {
        Group {
            if let logoData = card.logoData, let uiImage = UIImage(data: logoData) {
                Image(uiImage: uiImage)
                    .resizable()
                    .scaledToFill()
                    .clipped()
            } else {
                VStack(spacing: Design.Spacing.xxSmall) {
                    Image(systemName: "building.2")
                        .typography(.body)
                    Text("Logo")
                        .typography(.caption2)
                }
                .foregroundStyle(card.theme.textColor)
                .frame(maxWidth: .infinity, maxHeight: .infinity)
            }
        }
        .frame(width: Design.CardSize.avatarLarge, height: Design.CardSize.avatarLarge)
        .background(card.theme.accentColor)
        .clipShape(.rect(cornerRadius: Design.CornerRadius.medium))
        .overlay(RoundedRectangle(cornerRadius: Design.CornerRadius.medium).stroke(Color.AppBackground.elevated, lineWidth: Design.LineWidth.thick))
        .shadow(color: Color.Text.secondary.opacity(Design.Opacity.hint), radius: Design.Shadow.radiusSmall, x: Design.Shadow.offsetNone, y: Design.Shadow.offsetSmall)
    }
}

// MARK: - Logo Rectangle View

private struct LogoRectangleView: View {
    let card: BusinessCard
    
    private let aspectRatio: CGFloat = Design.CardSize.logoContainerAspectRatio
    
    var body: some View {
        Group {
            if let logoData = card.logoData, let uiImage = UIImage(data: logoData) {
                Image(uiImage: uiImage)
                    .resizable()
                    .scaledToFill()
                    .clipped()
            } else {
                VStack(spacing: Design.Spacing.xxSmall) {
                    Image(systemName: "building.2")
                        .typography(.body)
                    Text("Logo")
                        .typography(.caption2)
                }
                .foregroundStyle(card.theme.textColor)
                .frame(maxWidth: .infinity, maxHeight: .infinity)
            }
        }
        .frame(width: Design.CardSize.avatarLarge * aspectRatio, height: Design.CardSize.avatarLarge)
        .background(card.theme.accentColor)
        .clipShape(.rect(cornerRadius: Design.CornerRadius.medium))
        .overlay(RoundedRectangle(cornerRadius: Design.CornerRadius.medium).stroke(Color.AppBackground.elevated, lineWidth: Design.LineWidth.thick))
        .shadow(color: Color.Text.secondary.opacity(Design.Opacity.hint), radius: Design.Shadow.radiusSmall, x: Design.Shadow.offsetNone, y: Design.Shadow.offsetSmall)
    }
}

// MARK: - Contact Fields List

private struct ContactFieldsListView: View {
    @Environment(\.openURL) private var openURL
    @AppStorage("businessCard.contactFieldsViewMode") private var viewModeRawValue = ContactFieldsViewMode.list.rawValue
    let card: BusinessCard
    
    private var viewMode: ContactFieldsViewMode {
        get { ContactFieldsViewMode(rawValue: viewModeRawValue) ?? .list }
        nonmutating set { viewModeRawValue = newValue.rawValue }
    }
    
    private var columns: [GridItem] {
        [
            GridItem(.flexible(), spacing: Design.Spacing.small),
            GridItem(.flexible(), spacing: Design.Spacing.small)
        ]
    }
    
    private var primaryContactFields: [ContactField] {
        card.orderedContactFields.filter { ["phone", "email", "address"].contains($0.typeId) }
    }
    
    private var secondaryContactFields: [ContactField] {
        card.orderedContactFields.filter { !["phone", "email", "address"].contains($0.typeId) }
    }
    
    var body: some View {
        VStack(alignment: .leading, spacing: Design.Spacing.xxxLarge) {
            if !primaryContactFields.isEmpty {
                primaryContactSection(fields: primaryContactFields)
            }
            if !secondaryContactFields.isEmpty {
                secondaryFieldsSection(title: primaryContactFields.isEmpty ? nil : "Profiles & Links", fields: secondaryContactFields)
            }
        }
    }
    
    private func primaryContactSection(fields: [ContactField]) -> some View {
        VStack(alignment: .leading, spacing: Design.Spacing.medium) {
            Text("Contact")
                .typography(.caption)
                .foregroundStyle(Color.Text.secondary)
                .padding(.top, Design.Spacing.xxSmall)
            
            VStack(alignment: .leading, spacing: Design.Spacing.xSmall) {
                ForEach(fields.indices, id: \.self) { index in
                    let field = fields[index]
                    PrimaryContactFieldRowView(field: field, themeColor: card.theme.primaryColor) {
                        openField(field)
                    }
                    
                    if index < fields.count - 1 {
                        Divider()
                            .opacity(0.45)
                    }
                }
            }
        }
    }
    
    @ViewBuilder
    private func secondaryFieldsSection(title: String?, fields: [ContactField]) -> some View {
        VStack(alignment: .leading, spacing: Design.Spacing.medium) {
            if let title {
                Text(title)
                    .typography(.caption)
                    .foregroundStyle(Color.Text.secondary)
                    .padding(.top, Design.Spacing.xxSmall)
            }
            
            // Always present profiles/links as grid. Keep the view mode enum/storage for future toggling.
            LazyVGrid(columns: columns, spacing: Design.Spacing.small) {
                ForEach(fields) { field in
                    ContactFieldRowView(field: field, themeColor: card.theme.primaryColor, style: .grid) {
                        openField(field)
                    }
                }
            }
        }
    }
    
    private func openField(_ field: ContactField) {
        if let url = field.buildURL() {
            openURL(url)
        }
    }
}

private struct PrimaryContactFieldRowView: View {
    let field: ContactField
    let themeColor: Color
    let action: () -> Void
    
    private var labelText: String {
        let trimmed = field.title.trimmingCharacters(in: .whitespacesAndNewlines)
        return trimmed.isEmpty ? field.displayName : trimmed
    }
    
    var body: some View {
        Button(action: action) {
            HStack(alignment: .top, spacing: Design.Spacing.medium) {
                field.iconImage()
                    .typography(.subheading)
                    .foregroundStyle(themeColor)
                    .frame(width: 28)
                
                VStack(alignment: .leading, spacing: Design.Spacing.xxxSmall) {
                    Text(field.displayValue)
                        .typography(.subheading)
                        .foregroundStyle(Color.Text.primary)
                        .multilineTextAlignment(.leading)
                        .lineLimit(2)
                    
                    Text(labelText)
                        .typography(.caption)
                        .foregroundStyle(Color.Text.secondary)
                        .lineLimit(1)
                }
                .frame(maxWidth: .infinity, alignment: .leading)
            }
            .padding(.vertical, Design.Spacing.xxSmall)
        }
        .buttonStyle(.plain)
    }
}

private enum ContactFieldsViewMode: String, CaseIterable, Identifiable {
    case list
    case grid
    
    var id: String { rawValue }
    
    var title: String {
        switch self {
        case .list: return "List"
        case .grid: return "Grid"
        }
    }
}

private struct ContactFieldRowView: View {
    enum Style {
        case list
        case grid
    }
    
    let field: ContactField
    let themeColor: Color
    let style: Style
    let action: () -> Void
    
    private var valueText: String {
        field.displayValue
    }
    
    private var labelText: String {
        let trimmedTitle = field.title.trimmingCharacters(in: .whitespacesAndNewlines)
        guard !trimmedTitle.isEmpty else { return field.displayName }
        return shouldUseProviderLabel(for: trimmedTitle) ? field.displayName : trimmedTitle
    }
    
    private func shouldUseProviderLabel(for title: String) -> Bool {
        let normalized = title
            .trimmingCharacters(in: .whitespacesAndNewlines)
            .lowercased()
        
        let noisyPrefixes = [
            "connect with",
            "follow me",
            "add me",
            "subscribe",
            "view our work",
            "ask me",
            "pay via",
            "schedule"
        ]
        
        if noisyPrefixes.contains(where: normalized.hasPrefix) {
            return true
        }
        
        // If this is a long, canned suggestion, prefer provider name.
        if let suggestions = field.fieldType?.titleSuggestions {
            let matchedSuggestion = suggestions
                .map { $0.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() }
                .contains(normalized)
            
            if matchedSuggestion {
                let words = normalized.split(whereSeparator: \.isWhitespace)
                if words.count >= 3 {
                    return true
                }
            }
        }
        
        return false
    }
    
    private var valueLineLimit: Int {
        style == .grid ? 2 : 1
    }
    
    private var rowMinHeight: CGFloat? {
        style == .grid ? 84 : nil
    }
    
    var body: some View {
        Button(action: action) {
            HStack(alignment: .center, spacing: Design.Spacing.medium) {
                ZStack {
                    Circle()
                        .fill(themeColor.opacity(0.22))
                        .frame(width: 34, height: 34)
                    field.iconImage()
                        .typography(.caption)
                        .foregroundStyle(themeColor)
                }
                
                VStack(alignment: .leading, spacing: Design.Spacing.xxSmall) {
                    Text(valueText)
                        .typography(.subheading)
                        .foregroundStyle(Color.Text.primary)
                        .multilineTextAlignment(.leading)
                        .lineLimit(valueLineLimit)
                        .minimumScaleFactor(0.72)
                        .allowsTightening(true)
                    
                    Text(labelText)
                        .typography(.captionEmphasis)
                        .italic()
                        .foregroundStyle(Color.Text.secondary)
                        .lineLimit(style == .grid ? 2 : 1)
                }
                .frame(maxWidth: .infinity, alignment: .leading)
            }
            .padding(.horizontal, Design.Spacing.medium)
            .padding(.vertical, Design.Spacing.medium)
            .frame(maxWidth: .infinity, minHeight: rowMinHeight, alignment: .center)
            .background(Color.AppBackground.base.opacity(0.82))
            .overlay(
                RoundedRectangle(cornerRadius: Design.CornerRadius.medium)
                    .stroke(Color.white.opacity(0.08), lineWidth: 1)
            )
            .clipShape(.rect(cornerRadius: Design.CornerRadius.medium))
            .contentShape(.rect)
        }
        .buttonStyle(.plain)
        .accessibilityLabel("\(field.displayName): \(field.value)")
        .accessibilityHint(field.title.isEmpty ? String(localized: "Opens \(field.displayName)") : field.title)
    }
}

// MARK: - Previews

#Preview("Profile Banner") {
    @Previewable @State var card = BusinessCard(
        role: "Lead iOS Developer",
        company: "Toyota",
        themeName: "Coral",
        headerLayoutRawValue: "profileBanner",
        firstName: "Matt",
        lastName: "Bruce"
    )
    
    BusinessCardView(card: card)
        .padding()
        .background(Color.AppBackground.base)
}

#Preview("Cover + Avatar + Logo") {
    @Previewable @State var card = BusinessCard(
        role: "Lead iOS Developer",
        company: "Toyota",
        themeName: "Violet",
        headerLayoutRawValue: "coverWithAvatarAndLogo",
        firstName: "Matt",
        lastName: "Bruce"
    )
    
    BusinessCardView(card: card)
        .padding()
        .background(Color.AppBackground.base)
}
