//
//  FeedbackMappingExt.swift
//  SentianceEventTimeline
//
//  Created by Mohammed Aouf Zouag on 22/10/2025.
//

import SENTSDK
import RNSentianceCore

extension String: @retroactive SentianceNamespaceWrappable {}
extension [String: Any]: @retroactive SentianceNamespaceWrappable {}
extension SENTSDK.SENTOccupantRoleFeedbackResult: @retroactive SentianceNamespaceWrappable {}
extension SENTSDK.VehicleCrashDetectionFeedbackResult: @retroactive SentianceNamespaceWrappable {}

extension SentianceTypeWrapper where T == String {
    func asOccupantRoleFeedback() -> SENTOccupantRoleFeedback? {
        switch value {
        case "DRIVER":
            return .driver
        case "PASSENGER":
            return .passenger
        default:
            return nil
        }
    }
}

extension SentianceTypeWrapper where T == [String: Any] {
    func asVehicleCrashFeedback() -> VehicleCrashDetectionFeedback? {
        let dict = value

        guard let type = dict["type"] as? String else {
            return nil
        }

        switch type {
        case "CRASH":
            return createCrashFeedback(fromRnDict: dict)
        case "NO_CRASH":
            return createNoCrashFeedback(fromRnDict: dict)
        default:
            return nil
        }
    }

    private func createCrashFeedback(fromRnDict feedbackDict: [String: Any]) -> VehicleCrashDetectionFeedback? {
        guard
            let crashTimeEpoch = feedbackDict["crashTimeEpoch"] as? NSNumber,
            let wasCrashDetectedBySdk = feedbackDict["wasCrashDetectedBySentiance"] as? Bool
        else { return nil }

        var crashCoordinates: CLLocationCoordinate2D? = nil
        if feedbackDict["crashLocation"] != nil {
            guard
                let crashLocationDict = feedbackDict["crashLocation"] as? [String:NSNumber],
                let latitude = crashLocationDict["latitude"]?.doubleValue,
                let longitude = crashLocationDict["longitude"]?.doubleValue
            else { return nil }

            crashCoordinates = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
        }

        let crashDate = Date(timeIntervalSince1970: crashTimeEpoch.doubleValue / 1000)
        return .crash(crashDate: crashDate, wasCrashDetectedBySentiance: wasCrashDetectedBySdk, crashLocation: crashCoordinates)
    }

    private func createNoCrashFeedback(fromRnDict feedbackDict: [String: Any]) -> VehicleCrashDetectionFeedback? {
        guard let eventTimeEpoch = feedbackDict["eventTimeEpoch"] as? NSNumber else { return nil }
        return .noCrash(eventDate: Date(timeIntervalSince1970: eventTimeEpoch.doubleValue / 1000))
    }
}

extension SentianceTypeWrapper where T == VehicleCrashDetectionFeedbackResult {
    func toJsString() -> String {
        switch value {
        case .accepted: return "ACCEPTED"
        case .feedbackAlreadyProvided: return "FEEDBACK_ALREADY_PROVIDED"
        case .invalidEventDate: return "INVALID_EVENT_DATE"
        case .invalidLocation: return "INVALID_LOCATION"
        case .noUser: return "NO_USER"
        }
    }
}

extension SentianceTypeWrapper where T == SENTOccupantRoleFeedbackResult {
    func toJsString() -> String {
        switch value {
        case .accepted: return "ACCEPTED"
        case .transportTypeNotSupported: return "TRANSPORT_TYPE_NOT_SUPPORTED"
        case .transportNotFound: return "TRANSPORT_NOT_FOUND"
        case .feedbackAlreadyProvided: return "FEEDBACK_ALREADY_PROVIDED"
        case .transportNotYetComplete: return "TRANSPORT_NOT_YET_COMPLETE"
        case .transportIsProvisional: return "TRANSPORT_IS_PROVISIONAL"
        case .unexpectedError: return "UNEXPECTED_ERROR"
        }
    }
}

extension FeedbackErrorCodes: CustomStringConvertible {
    var description: String {
        switch self {
        case .E_SDK_NOT_INITIALIZED:
            return "SDK is not initialized."
        case .FEEDBACK_SERVICE_NOT_AVAILABLE:
            return "Feedback service is not available"
        case .INVALID_OCCUPANT_ROLE_FEEDBACK:
            return "Invalid occupant role feedback"
        case .INVALID_VEHICLE_CRASH_FEEDBACK:
            return "Invalid vehicle crash feedback"
        }
    }
}
