import Foundation

// MARK: - RCTVideoError

enum RCTVideoError: Error, Hashable {
    case fromJSPart(String)
    case noLicenseServerURL
    case licenseRequestFailed(Int)
    case noDataFromLicenseRequest
    case noSPC
    case noCertificateData
    case noCertificateURL
    case noDRMData
    case invalidContentId
    case invalidAppCert
    case keyRequestCreationFailed
    case persistableKeyRequestFailed
    case embeddedKeyExtractionFailed
    case offlineDRMNotSupported
    case unsupportedDRMType
    case simulatorDRMNotSupported

    var errorCode: Int {
        switch self {
        case .fromJSPart:
            return 1000
        case .noLicenseServerURL:
            return 1001
        case .licenseRequestFailed:
            return 1002
        case .noDataFromLicenseRequest:
            return 1003
        case .noSPC:
            return 1004
        case .noCertificateData:
            return 1005
        case .noCertificateURL:
            return 1006
        case .noDRMData:
            return 1007
        case .invalidContentId:
            return 1008
        case .invalidAppCert:
            return 1009
        case .keyRequestCreationFailed:
            return 1010
        case .persistableKeyRequestFailed:
            return 1011
        case .embeddedKeyExtractionFailed:
            return 1012
        case .offlineDRMNotSupported:
            return 1013
        case .unsupportedDRMType:
            return 1014
        case .simulatorDRMNotSupported:
            return 1015
        }
    }
}

// MARK: LocalizedError

extension RCTVideoError: LocalizedError {
    var errorDescription: String? {
        switch self {
        case let .fromJSPart(error):
            return NSLocalizedString("Error from JavaScript: \(error)", comment: "")
        case .noLicenseServerURL:
            return NSLocalizedString("No license server URL provided", comment: "")
        case let .licenseRequestFailed(statusCode):
            return NSLocalizedString("License request failed with status code: \(statusCode)", comment: "")
        case .noDataFromLicenseRequest:
            return NSLocalizedString("No data received from license server", comment: "")
        case .noSPC:
            return NSLocalizedString("Failed to create Server Playback Context (SPC)", comment: "")
        case .noCertificateData:
            return NSLocalizedString("No certificate data obtained", comment: "")
        case .noCertificateURL:
            return NSLocalizedString("No certificate URL provided", comment: "")
        case .noDRMData:
            return NSLocalizedString("No DRM data available", comment: "")
        case .invalidContentId:
            return NSLocalizedString("Invalid content ID", comment: "")
        case .invalidAppCert:
            return NSLocalizedString("Invalid application certificate", comment: "")
        case .keyRequestCreationFailed:
            return NSLocalizedString("Failed to create content key request", comment: "")
        case .persistableKeyRequestFailed:
            return NSLocalizedString("Failed to create persistable content key request", comment: "")
        case .embeddedKeyExtractionFailed:
            return NSLocalizedString("Failed to extract embedded key", comment: "")
        case .offlineDRMNotSupported:
            return NSLocalizedString("Offline DRM is not supported, see https://github.com/TheWidlarzGroup/react-native-video/issues/3539", comment: "")
        case .unsupportedDRMType:
            return NSLocalizedString("Unsupported DRM type", comment: "")
        case .simulatorDRMNotSupported:
            return NSLocalizedString("DRM on simulators is not supported", comment: "")
        }
    }

    var failureReason: String? {
        switch self {
        case .fromJSPart:
            return NSLocalizedString("An error occurred in the JavaScript part of the application.", comment: "")
        case .noLicenseServerURL:
            return NSLocalizedString("The license server URL is missing in the DRM configuration.", comment: "")
        case .licenseRequestFailed:
            return NSLocalizedString("The license server responded with an error status code.", comment: "")
        case .noDataFromLicenseRequest:
            return NSLocalizedString("The license server did not return any data.", comment: "")
        case .noSPC:
            return NSLocalizedString("Failed to generate the Server Playback Context (SPC) for the content.", comment: "")
        case .noCertificateData:
            return NSLocalizedString("Unable to retrieve certificate data from the specified URL.", comment: "")
        case .noCertificateURL:
            return NSLocalizedString("The certificate URL is missing in the DRM configuration.", comment: "")
        case .noDRMData:
            return NSLocalizedString("The required DRM data is not available or is invalid.", comment: "")
        case .invalidContentId:
            return NSLocalizedString("The content ID provided is not valid or recognized.", comment: "")
        case .invalidAppCert:
            return NSLocalizedString("The application certificate is invalid or not recognized.", comment: "")
        case .keyRequestCreationFailed:
            return NSLocalizedString("Unable to create a content key request for DRM.", comment: "")
        case .persistableKeyRequestFailed:
            return NSLocalizedString("Failed to create a persistable content key request for offline playback.", comment: "")
        case .embeddedKeyExtractionFailed:
            return NSLocalizedString("Unable to extract the embedded key from the custom scheme URL.", comment: "")
        case .offlineDRMNotSupported:
            return NSLocalizedString("You tried to use Offline DRM but it is not supported yet", comment: "")
        case .unsupportedDRMType:
            return NSLocalizedString("You tried to use unsupported DRM type", comment: "")
        case .simulatorDRMNotSupported:
            return NSLocalizedString("You tried to DRM on a simulator", comment: "")
        }
    }

    var recoverySuggestion: String? {
        switch self {
        case .fromJSPart:
            return NSLocalizedString("Check the JavaScript logs for more details and fix any issues in the JS code.", comment: "")
        case .noLicenseServerURL:
            return NSLocalizedString("Ensure that you have specified the 'licenseServer' property in the DRM configuration.", comment: "")
        case .licenseRequestFailed:
            return NSLocalizedString("Verify that the license server is functioning correctly and that you're sending the correct data.", comment: "")
        case .noDataFromLicenseRequest:
            return NSLocalizedString("Check if the license server is operational and responding with the expected data.", comment: "")
        case .noSPC:
            return NSLocalizedString("Verify that the content key request is properly configured and that the DRM setup is correct.", comment: "")
        case .noCertificateData:
            return NSLocalizedString("Check if the certificate URL is correct and accessible, and that it returns valid certificate data.", comment: "")
        case .noCertificateURL:
            return NSLocalizedString("Make sure you have specified the 'certificateUrl' property in the DRM configuration.", comment: "")
        case .noDRMData:
            return NSLocalizedString("Ensure that you have provided all necessary DRM-related data in the configuration.", comment: "")
        case .invalidContentId:
            return NSLocalizedString("Verify that the content ID is correct and matches the expected format for your DRM system.", comment: "")
        case .invalidAppCert:
            return NSLocalizedString("Check if the application certificate is valid and properly formatted for your DRM system.", comment: "")
        case .keyRequestCreationFailed:
            return NSLocalizedString("Review your DRM configuration and ensure all required parameters are correctly set.", comment: "")
        case .persistableKeyRequestFailed:
            return NSLocalizedString("Verify that offline playback is supported and properly configured for your content.", comment: "")
        case .embeddedKeyExtractionFailed:
            return NSLocalizedString("Check if the embedded key is present in the URL and the custom scheme is correctly implemented.", comment: "")
        case .offlineDRMNotSupported:
            return NSLocalizedString("Check if localSourceEncryptionKeyScheme is set", comment: "")
        case .unsupportedDRMType:
            return NSLocalizedString("Verify that you are using fairplay (on Apple devices)", comment: "")
        case .simulatorDRMNotSupported:
            return NSLocalizedString("You need to test DRM content on real device", comment: "")
        }
    }
}

// MARK: - RCTVideoErrorHandler

enum RCTVideoErrorHandler {
    static func createError(from error: RCTVideoError) -> [String: Any] {
        return [
            "code": error.errorCode,
            "localizedDescription": error.localizedDescription,
            "localizedFailureReason": error.failureReason ?? "",
            "localizedRecoverySuggestion": error.recoverySuggestion ?? "",
            "domain": "RCTVideo",
        ]
    }
}