"""
PHOENIX quantum feasibility sweep -- the screens.

Each screen tests one quantum / quantum-inspired method from the untested list
against a mandatory classical baseline on the calibrated SEVIRI fire/non-fire task
(or a task-appropriate synthetic signal), same metric, with a placebo where a
model is learned. All CPU/simulator, small, laptop-light.

Covered (list item -> screen):
  58/158 quantum kernel / QSVM            -> screen_qsvm_qiskit, screen_qkernel_pennylane
  63/161 quantum tensor networks          -> screen_tensor_network
  59     quantum clustering               -> screen_quantum_clustering
  RX/anomaly (quantum one-class)          -> screen_quantum_anomaly
  61/62  QFT / quantum-wavelet deconv     -> screen_qft_deconvolution
  57/65  quantum Bayesian / particle flt  -> screen_quantum_particle_filter
  64/160 quantum graph fusion             -> screen_quantum_graph_fusion
  60     quantum image representation     -> screen_quantum_image_rep
"""
from __future__ import annotations
import time
import numpy as np
from sklearn.preprocessing import MinMaxScaler, StandardScaler
from sklearn.decomposition import PCA
from sklearn.svm import SVC, OneClassSVM
from sklearn.ensemble import IsolationForest
from sklearn.cluster import KMeans
from sklearn.mixture import GaussianMixture
from sklearn.model_selection import StratifiedKFold
from sklearn.metrics import roc_auc_score

from qsweep_core import (make_seviri_dataset, classical_baselines, ScreenResult,
                         derived_features)


# --------------------------------------------------------------------------
# helpers
# --------------------------------------------------------------------------
def _prep_kernel_features(X, n_features=6, hi=np.pi):
    """PCA-reduce and scale into an angle range for embedding."""
    Xp = PCA(n_components=n_features, random_state=0).fit_transform(StandardScaler().fit_transform(X))
    return MinMaxScaler((0, hi)).fit_transform(Xp)


def _kernel_svc_auc(Kfn, X, y, seed=0, folds=3):
    """CV AUC for a precomputed-kernel SVC given a kernel function K(A,B)."""
    skf = StratifiedKFold(n_splits=folds, shuffle=True, random_state=seed)
    aucs = []
    for tr, te in skf.split(X, y):
        Ktr = Kfn(X[tr], X[tr])
        Kte = Kfn(X[te], X[tr])
        svc = SVC(kernel="precomputed", C=2.0).fit(Ktr, y[tr])
        aucs.append(roc_auc_score(y[te], svc.decision_function(Kte)))
    return float(np.mean(aucs))


# --------------------------------------------------------------------------
# 58/158  Quantum kernel / QSVM  (qiskit-machine-learning fidelity kernel)
# --------------------------------------------------------------------------
def screen_qsvm_qiskit(n=90, seed=0):
    t0 = time.perf_counter()
    from qiskit_machine_learning.kernels import FidelityQuantumKernel
    try:
        from qiskit.circuit.library import zz_feature_map
        fm = zz_feature_map(feature_dimension=6, reps=1)
    except Exception:
        from qiskit.circuit.library import ZZFeatureMap
        fm = ZZFeatureMap(feature_dimension=6, reps=1)
    qk = FidelityQuantumKernel(feature_map=fm)

    def Kfn(A, B):
        return qk.evaluate(x_vec=A, y_vec=B)

    X, y = make_seviri_dataset(n, seed=seed)
    Xk = _prep_kernel_features(X, 6, hi=np.pi)
    q_auc = _kernel_svc_auc(Kfn, Xk, y, seed=seed)
    base = classical_baselines(X, y, seed=seed)
    r = ScreenResult("58/158 quantum kernel (QSVM, ZZ feature map)", "fire vs non-fire (11-band)",
                     q_auc, base["best_classical_full"], None, "AUC",
                     time.perf_counter() - t0,
                     extra={"rbf_svm_full": base["rbf_svm_full"], "n": n})
    return r


# --------------------------------------------------------------------------
# 158  Quantum kernel (PennyLane angle-embedding fidelity kernel)
# --------------------------------------------------------------------------
def screen_qkernel_pennylane(n=90, seed=0, n_q=6):
    t0 = time.perf_counter()
    import pennylane as qml
    dev = qml.device("default.qubit", wires=n_q)

    @qml.qnode(dev)
    def overlap(x1, x2):
        qml.AngleEmbedding(x1, wires=range(n_q))
        qml.adjoint(qml.AngleEmbedding)(x2, wires=range(n_q))
        return qml.probs(wires=range(n_q))

    def Kfn(A, B):
        K = np.zeros((len(A), len(B)))
        for i, a in enumerate(A):
            for j, b in enumerate(B):
                K[i, j] = overlap(a, b)[0]
        return K

    X, y = make_seviri_dataset(n, seed=seed)
    Xk = _prep_kernel_features(X, n_q, hi=np.pi)
    q_auc = _kernel_svc_auc(Kfn, Xk, y, seed=seed)
    base = classical_baselines(X, y, seed=seed)
    return ScreenResult("158 quantum kernel (PennyLane angle embedding)", "fire vs non-fire (11-band)",
                        q_auc, base["best_classical_full"], None, "AUC",
                        time.perf_counter() - t0, extra={"n": n})


if __name__ == "__main__":
    for fn in (screen_qsvm_qiskit, screen_qkernel_pennylane):
        r = fn()
        print(f"{r.name:<48} qAUC={r.quantum_metric:.3f}  classical={r.classical_metric:.3f}  "
              f"{r.latency_s:.1f}s")
