package com.tencent.qian.webview.model;

import androidx.annotation.NonNull;

import java.util.List;
import java.util.Objects;

/**
 * SDK 内部事件，用于将容器层非协议性观测点上报给业务方。
 *
 * <p>sealed class 翻译为 abstract class + static final 子类。
 * 客户使用 {@code instanceof} 模式匹配事件类型。
 */
public abstract class SdkEvent {

    private SdkEvent() {}

    // ────────── 页面生命周期 ──────────

    public static final class PageStarted extends SdkEvent {
        @NonNull private final String url;
        public PageStarted(@NonNull String url) { this.url = url; }
        @NonNull public String getUrl() { return url; }
        @Override public boolean equals(Object o) { return o instanceof PageStarted && Objects.equals(url, ((PageStarted) o).url); }
        @Override public int hashCode() { return Objects.hash(url); }
        @Override @NonNull public String toString() { return "PageStarted{url='" + url + "'}"; }
    }

    public static final class PageFinished extends SdkEvent {
        @NonNull private final String url;
        public PageFinished(@NonNull String url) { this.url = url; }
        @NonNull public String getUrl() { return url; }
        @Override public boolean equals(Object o) { return o instanceof PageFinished && Objects.equals(url, ((PageFinished) o).url); }
        @Override public int hashCode() { return Objects.hash(url); }
        @Override @NonNull public String toString() { return "PageFinished{url='" + url + "'}"; }
    }

    // ────────── 权限 ──────────

    public static final class PermissionGranted extends SdkEvent {
        @NonNull private final List<String> permissions;
        public PermissionGranted(@NonNull List<String> permissions) { this.permissions = permissions; }
        @NonNull public List<String> getPermissions() { return permissions; }
        @Override public boolean equals(Object o) { return o instanceof PermissionGranted && Objects.equals(permissions, ((PermissionGranted) o).permissions); }
        @Override public int hashCode() { return Objects.hash(permissions); }
        @Override @NonNull public String toString() { return "PermissionGranted{permissions=" + permissions + "}"; }
    }

    public static final class PermissionDenied extends SdkEvent {
        @NonNull private final List<String> permissions;
        public PermissionDenied(@NonNull List<String> permissions) { this.permissions = permissions; }
        @NonNull public List<String> getPermissions() { return permissions; }
        @Override public boolean equals(Object o) { return o instanceof PermissionDenied && Objects.equals(permissions, ((PermissionDenied) o).permissions); }
        @Override public int hashCode() { return Objects.hash(permissions); }
        @Override @NonNull public String toString() { return "PermissionDenied{permissions=" + permissions + "}"; }
    }

    // ────────── Scheme 拦截 ──────────

    public static final class SchemeIntercepted extends SdkEvent {
        @NonNull private final String scheme;
        @NonNull private final String url;
        public SchemeIntercepted(@NonNull String scheme, @NonNull String url) { this.scheme = scheme; this.url = url; }
        @NonNull public String getScheme() { return scheme; }
        @NonNull public String getUrl() { return url; }
        @Override public boolean equals(Object o) { return o instanceof SchemeIntercepted && Objects.equals(scheme, ((SchemeIntercepted) o).scheme) && Objects.equals(url, ((SchemeIntercepted) o).url); }
        @Override public int hashCode() { return Objects.hash(scheme, url); }
        @Override @NonNull public String toString() { return "SchemeIntercepted{scheme='" + scheme + "', url='" + url + "'}"; }
    }

    public static final class SchemeNotMatched extends SdkEvent {
        @NonNull private final String url;
        public SchemeNotMatched(@NonNull String url) { this.url = url; }
        @NonNull public String getUrl() { return url; }
        @Override public boolean equals(Object o) { return o instanceof SchemeNotMatched && Objects.equals(url, ((SchemeNotMatched) o).url); }
        @Override public int hashCode() { return Objects.hash(url); }
        @Override @NonNull public String toString() { return "SchemeNotMatched{url='" + url + "'}"; }
    }

    // ────────── 网络与渲染错误 ──────────

    public static final class LoadError extends SdkEvent {
        @NonNull private final String url;
        private final int errorCode;
        @NonNull private final String description;
        public LoadError(@NonNull String url, int errorCode, @NonNull String description) { this.url = url; this.errorCode = errorCode; this.description = description; }
        @NonNull public String getUrl() { return url; }
        public int getErrorCode() { return errorCode; }
        @NonNull public String getDescription() { return description; }
        @Override public boolean equals(Object o) { return o instanceof LoadError && errorCode == ((LoadError) o).errorCode && Objects.equals(url, ((LoadError) o).url) && Objects.equals(description, ((LoadError) o).description); }
        @Override public int hashCode() { return Objects.hash(url, errorCode, description); }
        @Override @NonNull public String toString() { return "LoadError{url='" + url + "', errorCode=" + errorCode + ", description='" + description + "'}"; }
    }

    public static final class HttpError extends SdkEvent {
        @NonNull private final String url;
        private final int statusCode;
        @NonNull private final String reasonPhrase;
        public HttpError(@NonNull String url, int statusCode, @NonNull String reasonPhrase) { this.url = url; this.statusCode = statusCode; this.reasonPhrase = reasonPhrase; }
        @NonNull public String getUrl() { return url; }
        public int getStatusCode() { return statusCode; }
        @NonNull public String getReasonPhrase() { return reasonPhrase; }
        @Override public boolean equals(Object o) { return o instanceof HttpError && statusCode == ((HttpError) o).statusCode && Objects.equals(url, ((HttpError) o).url) && Objects.equals(reasonPhrase, ((HttpError) o).reasonPhrase); }
        @Override public int hashCode() { return Objects.hash(url, statusCode, reasonPhrase); }
        @Override @NonNull public String toString() { return "HttpError{url='" + url + "', statusCode=" + statusCode + ", reasonPhrase='" + reasonPhrase + "'}"; }
    }

    public static final class SslError extends SdkEvent {
        @NonNull private final String url;
        private final int primaryError;
        public SslError(@NonNull String url, int primaryError) { this.url = url; this.primaryError = primaryError; }
        @NonNull public String getUrl() { return url; }
        public int getPrimaryError() { return primaryError; }
        @Override public boolean equals(Object o) { return o instanceof SslError && primaryError == ((SslError) o).primaryError && Objects.equals(url, ((SslError) o).url); }
        @Override public int hashCode() { return Objects.hash(url, primaryError); }
        @Override @NonNull public String toString() { return "SslError{url='" + url + "', primaryError=" + primaryError + "}"; }
    }

    // ────────── 下载 ──────────

    public static final class DownloadStart extends SdkEvent {
        @NonNull private final String url;
        @NonNull private final String mimeType;
        @NonNull private final String contentDisposition;
        public DownloadStart(@NonNull String url, @NonNull String mimeType, @NonNull String contentDisposition) { this.url = url; this.mimeType = mimeType; this.contentDisposition = contentDisposition; }
        @NonNull public String getUrl() { return url; }
        @NonNull public String getMimeType() { return mimeType; }
        @NonNull public String getContentDisposition() { return contentDisposition; }
        @Override public boolean equals(Object o) { return o instanceof DownloadStart && Objects.equals(url, ((DownloadStart) o).url) && Objects.equals(mimeType, ((DownloadStart) o).mimeType) && Objects.equals(contentDisposition, ((DownloadStart) o).contentDisposition); }
        @Override public int hashCode() { return Objects.hash(url, mimeType, contentDisposition); }
        @Override @NonNull public String toString() { return "DownloadStart{url='" + url + "', mimeType='" + mimeType + "'}"; }
    }

    public static final class DownloadFailed extends SdkEvent {
        @NonNull private final String url;
        @NonNull private final String reason;
        public DownloadFailed(@NonNull String url, @NonNull String reason) { this.url = url; this.reason = reason; }
        @NonNull public String getUrl() { return url; }
        @NonNull public String getReason() { return reason; }
        @Override public boolean equals(Object o) { return o instanceof DownloadFailed && Objects.equals(url, ((DownloadFailed) o).url) && Objects.equals(reason, ((DownloadFailed) o).reason); }
        @Override public int hashCode() { return Objects.hash(url, reason); }
        @Override @NonNull public String toString() { return "DownloadFailed{url='" + url + "', reason='" + reason + "'}"; }
    }

    // ────────── 渲染进程崩溃 ──────────

    public static final class RenderProcessGone extends SdkEvent {
        private final boolean didCrash;
        @NonNull private final String url;
        public RenderProcessGone(boolean didCrash, @NonNull String url) { this.didCrash = didCrash; this.url = url; }
        public boolean isDidCrash() { return didCrash; }
        @NonNull public String getUrl() { return url; }
        @Override public boolean equals(Object o) { return o instanceof RenderProcessGone && didCrash == ((RenderProcessGone) o).didCrash && Objects.equals(url, ((RenderProcessGone) o).url); }
        @Override public int hashCode() { return Objects.hash(didCrash, url); }
        @Override @NonNull public String toString() { return "RenderProcessGone{didCrash=" + didCrash + ", url='" + url + "'}"; }
    }

    // ────────── UA 注入失败 ──────────

    public static final class UserAgentInjectFailed extends SdkEvent {
        @NonNull private final String reason;
        public UserAgentInjectFailed(@NonNull String reason) { this.reason = reason; }
        @NonNull public String getReason() { return reason; }
        @Override public boolean equals(Object o) { return o instanceof UserAgentInjectFailed && Objects.equals(reason, ((UserAgentInjectFailed) o).reason); }
        @Override public int hashCode() { return Objects.hash(reason); }
        @Override @NonNull public String toString() { return "UserAgentInjectFailed{reason='" + reason + "'}"; }
    }
}
