StatusComparisonView.swift 13.1 KB
//
//  StatusComparisonView.swift
//  hippo-watch Watch App
//
//  Created by shihao on 2025/7/7.
//

import Foundation
import SwiftUI
import SDWebImageSwiftUI

struct StatusComparisonView: View {
    @Environment(\.scenePhase) private var scenePhase
    @StateObject private var vm = StatusComparisonViewModel()
    @Binding var showPKView: Bool
    @ObservedObject var userinfoManager = WatchUserinfoManager.share
    @ObservedObject var dataManager = WatchDataManager.share
    
    var body: some View {
        GeometryReader { geometry in
            
            VStack(spacing: 6.x) {
                // 顶部时间和标题
                HStack {
                    Text("PK")
                        .font(.system(size: 16, weight: .semibold))
                        .foregroundColor(.white)
                        .frame(width: 34.x, height: 34.x)
                        .background(Color.white.opacity(0.3))
                        .clipShape(Circle())
                        .onTapGesture {
                            showPKView = true
                        }
                    
                    Spacer()
                    
                    VStack(spacing: 2) {
                        Spacer()
                        Text("我们的状态")
                            .font(.system(size: 17))
                            .foregroundColor(.white)
                    }
                    
                }
                .padding(.horizontal, 11.x)
                .padding(.top, 13.x)
                                
                // 用户状态对比
                HStack(spacing: 0) {
                    Spacer()
                    // 左侧用户
                    VStack(spacing: 0) {
                        // 压力状态动画
                        if isMeCustomTheme {
                            WebImage(url: myCustomThemeImageURL)
                                .resizable()
                                .frame(width: 67.x, height: 67.x)
                                .cornerRadius(12.x)
                                .overlay(RoundedRectangle(cornerRadius: 12.x).stroke(Color(hex: "#7F7F7F"), lineWidth: 1))
                        }else {
                            AnimatedGIFView(gifName: myCharacterAnimationName)
                                .frame(width: 80.x, height: 80.x)
                        }
                        
                        // 用户信息
                        HStack(spacing: 4.x) {
                            WebImage(url: userinfoManager.myUserinfo?.avatar?.url)
                                .resizable()
                                .frame(width: 20.x, height: 20.x)
                                .background(.clear)
                                .clipShape(Circle())
                            
                            VStack(alignment: .leading, spacing: 2) {
                                Text(myHRVStatusDescription)
                                    .font(.system(size: 13, weight: .medium))
                                    .foregroundColor(myHRVStatus?.watchStatusTextColor ?? .white)
                                Text(myHRVValueString)
                                    .font(.system(size: 9))
                                    .foregroundColor(.white.opacity(0.7))
                            }
                        }
                        .padding(.top, isMeCustomTheme ? 7.x : -10.x)
                    }
                    
                    Spacer()
                    
                    // 右侧用户
                    VStack(spacing: 0) {
                        // 压力状态动画
                        if isOtherCustomTheme {
                            WebImage(url: otherCustomThemeImageURL)
                                .resizable()
                                .frame(width: 67.x, height: 67.x)
                                .cornerRadius(12.x)
                                .overlay(RoundedRectangle(cornerRadius: 12.x).stroke(Color(hex: "#7F7F7F"), lineWidth: 1))
                        }else {
                            AnimatedGIFView(gifName: otherCharacterAnimationName)
                                .frame(width: 80.x, height: 80.x)
                        }
                        
                        // 用户信息
                        HStack(spacing: 4.x) {
                            VStack(alignment: .trailing, spacing: 2) {
                                Text(otherHRVStatusDescription)
                                    .font(.system(size: 13, weight: .medium))
                                    .foregroundColor(otherHRVStatus?.watchStatusTextColor ?? .white)
                                Text(otherHRVValueString)
                                    .font(.system(size: 9))
                                    .foregroundColor(.white.opacity(0.7))
                            }
                            
                            WebImage(url: userinfoManager.otherUserinfo?.avatar?.url)
                                .resizable()
                                .frame(width: 20.x, height: 20.x)
                                .background(.clear)
                                .clipShape(Circle())
                        }
                        .padding(.top, isOtherCustomTheme ? 7.x : -10.x)
                    }
                    
                    Spacer()
                }
                          
                Spacer()
                
                // 底部想他按钮
                HStack(spacing: 2.x) {
                    Image(userinfoManager.interactionActionType.buttonImage)
                        .resizable()
                        .frame(width: 28.x, height: 28.x)
                        .scaleEffect(x: -1, y: 1)
                    
                    Text(userinfoManager.interactionActionType.title)
                        .font(.system(size: 15, weight: .regular))
                        .foregroundColor(.white)
                }
                .frame(maxWidth: .infinity)
                .frame(height: 36.x)
                .background(
                    RoundedRectangle(cornerRadius: 18.x)
                        .fill(Color(hex: "#758564FF").opacity(0.5))
                )
                .padding(.horizontal, 12.x)
                .padding(.bottom, 10.x)
                .onTapGesture {
                    vm.onInteractionClick()
                    ThinkSDKUtil.track(eventName: "click_doublefeel_watch_page",
                                       properties: ["click_content": "互动键",
                                                    "page_type": "我们的状态",
                                                    "Interactive_type": WatchUserinfoManager.share.interactionActionType.title])
                }
                
                
            }
            .navigationBarHidden(true)
            .frame(width: geometry.size.width, height: geometry.size.height)
            .background(
                HStack(spacing: 0) {
                    LinearGradient(
                        gradient: Gradient(colors: myBgColors),
                        startPoint: .top,
                        endPoint: .bottom
                    )
                    
                    LinearGradient(
                        gradient: Gradient(colors: otherBgColors),
                        startPoint: .top,
                        endPoint: .bottom
                    )
                }
            )
            .overlay {
                if let currentInteractionAction = vm.currentInteractionAction {
                    AnimatedGIFView(gifName: currentInteractionAction.statusComparisonAnimationName)
                        .frame(maxWidth: .infinity, maxHeight: .infinity)
                        .padding(.top, 10.x)
                }
            }
        }
        .ignoresSafeArea(.all)
        .onAppear {
            dataManager.fetchCoupleLatestHRV()
            ThinkSDKUtil.track(eventName: "enter_doublefeel_watch_page",
                               properties: ["page_type": "我们的状态"])
            
        }
        .onReceive(NotificationCenter.default.publisher(for: NotificationType.watchThemeChanged)) { notification in
            vm.refreshTheme()
        }
        .onChange(of: scenePhase) { _, newPhase in
            if newPhase == .active {
                vm.refreshTheme()
            }
        }
        
    }
    
    private var myBgColors: [Color] {
        let status = myHRVStatus ?? .normal
        return status.watchStatusColors
    }
    
    private var otherBgColors: [Color] {
        let status = otherHRVStatus ?? .normal
        return status.watchStatusColors
    }
    
    private var myHRVStatusDescription: String {
        guard let myHRVStatus else {
            return "-"
        }
        
        if isMeCustomTheme == true {
            return vm.myWatchTheme?.hrvStatusDescription(hrvStatus: myHRVStatus) ?? myHRVStatus.rawValue
        }else {
            return myHRVStatus.rawValue
        }
    }
    
    private var otherHRVStatusDescription: String {
        guard let otherHRVStatus else {
            return "-"
        }
        
        if isOtherCustomTheme == true {
            return vm.otherWatchTheme?.hrvStatusDescription(hrvStatus: otherHRVStatus) ?? otherHRVStatus.rawValue
        }else {
            return otherHRVStatus.rawValue
        }
    }
    
    private var myHRVValueString: String {
        if let value = dataManager.myLatestHRVData?.value {
            if value.truncatingRemainder(dividingBy: 1) == 0 {
                return String(format: "%.0f", value) + "ms"// 没有小数部分
            } else {
                return String(format: "%.1f", value) + "ms" // 最多一位小数
            }
        }
        
        return "-ms"
    }
    
    private var otherHRVValueString: String {
        if let value = dataManager.otherLatestHRVData?.value {
            if value.truncatingRemainder(dividingBy: 1) == 0 {
                return String(format: "%.0f", value) + "ms"// 没有小数部分
            } else {
                return String(format: "%.1f", value) + "ms" // 最多一位小数
            }
        }
        
        return "-ms"
    }
    
    private var myHRVStatus: HRVStatus? {
        return dataManager.myLatestHRVData?.status
    }
    
    private var otherHRVStatus: HRVStatus? {
        return dataManager.otherLatestHRVData?.status
    }
    
    private var myCharacterAnimationName: String {
        let character = userinfoManager.myUserinfo?.persona ?? .cat
        print("我的hrvstatus:\(String(describing: myHRVStatus))")
        return character.getCharacterAnimationFileName(myHRVStatus)
    }
    
    private var otherCharacterAnimationName: String {
        let character = userinfoManager.otherUserinfo?.persona ?? .cat
        return character.getCharacterAnimationFileName(otherHRVStatus)
    }
    
    private var isMeCustomTheme: Bool {
        guard let theme = vm.myWatchTheme else {return false}
        return theme.isDefaultTheme != true
    }
    
    private var isOtherCustomTheme: Bool {
        guard let theme = vm.otherWatchTheme else {return false}
        return theme.isDefaultTheme != true
    }
    
    private var myCustomThemeImageURL: URL? {
        let hrvStatus = dataManager.myLatestHRVData?.status ?? .normal
        if let imageUrl = vm.myWatchTheme?.hrvStatusThumnailImageURL(hrvStatus: hrvStatus) {
            return URL(string: imageUrl)
        }
        return nil
    }
    
    private var otherCustomThemeImageURL: URL? {
        let hrvStatus = dataManager.myLatestHRVData?.status ?? .normal
        if let imageUrl = vm.otherWatchTheme?.hrvStatusThumnailImageURL(hrvStatus: hrvStatus) {
            return URL(string: imageUrl)
        }
        return nil
    }
}

fileprivate extension UserCharacter {
    func getCharacterAnimationFileName(_ status: HRVStatus?) -> String {
        switch self {
        case .cat, .default:
            switch status {
            case .fullOfEnergy:
                return "catFullOfEnergy"
            case .normal:
                return "catNormal"
            case .overpressure:
                return "catOverpressure"
            case nil:
                return "catNormal"
            }
        case .dog:
            switch status {
            case .fullOfEnergy:
                return "dogFullOfEnergy"
            case .normal:
                return "dogNormal"
            case .overpressure:
                return "dogOverpressure"
            case nil:
                return "dogNormal"
            }
        case .rabbit:
            switch status {
            case .fullOfEnergy:
                return "rabbitFullOfEnergy"
            case .normal:
                return "rabbitNormal"
            case .overpressure:
                return "rabbitOverpressure"
            case nil:
                return "rabbitNormal"
            }
        case .elephant:
            switch status {
            case .fullOfEnergy:
                return "elephantFullOfEnergy"
            case .normal:
                return "elephantNormal"
            case .overpressure:
                return "elephantOverpressure"
            case nil:
                return "elephantNormal"
            }
        }
    }
}