import { useQuery, useMutation } from "@tanstack/react-query";
import { queryClient, apiRequest } from "@/lib/queryClient";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Brain, Play, Search, CheckCircle2, XCircle, Clock, TrendingUp } from "lucide-react";
import { format } from "date-fns";
import type { TrainingHistory } from "@shared/schema";
import { useToast } from "@/hooks/use-toast";
import { useState } from "react";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
  DialogFooter,
} from "@/components/ui/dialog";
import {
  Form,
  FormControl,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
  FormDescription,
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { Checkbox } from "@/components/ui/checkbox";

interface MLStatsResponse {
  source?: string;
  ml_backend_status?: string;
  logs?: { total: number; last_hour: number };
  detections?: { total: number; blocked: number; critical?: number; unique_ips?: number };
  routers?: { active: number };
  latest_training?: any;
  logs_24h?: number;
}

const trainFormSchema = z.object({
  max_records: z.coerce.number().min(1, "Minimo 1 record").max(1000000, "Massimo 1M record"),
  hours_back: z.coerce.number().min(1, "Minimo 1 ora").max(720, "Massimo 720 ore (30 giorni)"),
});

const detectFormSchema = z.object({
  max_records: z.coerce.number().min(1, "Minimo 1 record").max(1000000, "Massimo 1M record"),
  hours_back: z.coerce.number().min(1, "Minimo 1 ora").max(720, "Massimo 720 ore"),
  risk_threshold: z.coerce.number().min(0, "Minimo 0").max(100, "Massimo 100"),
  auto_block: z.boolean().default(true),
});

export default function TrainingPage() {
  const { toast } = useToast();
  const [isTrainDialogOpen, setIsTrainDialogOpen] = useState(false);
  const [isDetectDialogOpen, setIsDetectDialogOpen] = useState(false);

  const trainForm = useForm<z.infer<typeof trainFormSchema>>({
    resolver: zodResolver(trainFormSchema),
    defaultValues: {
      max_records: 100000,
      hours_back: 24,
    },
  });

  const detectForm = useForm<z.infer<typeof detectFormSchema>>({
    resolver: zodResolver(detectFormSchema),
    defaultValues: {
      max_records: 50000,
      hours_back: 1,
      risk_threshold: 75,
      auto_block: true,
    },
  });

  const { data: history, isLoading } = useQuery<TrainingHistory[]>({
    queryKey: ["/api/training-history"],
    refetchInterval: 10000,
  });

  const { data: mlStats } = useQuery<MLStatsResponse>({
    queryKey: ["/api/ml/stats"],
    refetchInterval: 10000,
  });

  const trainMutation = useMutation({
    mutationFn: async (params: z.infer<typeof trainFormSchema>) => {
      return await apiRequest("POST", "/api/ml/train", params);
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["/api/training-history"] });
      queryClient.invalidateQueries({ queryKey: ["/api/ml/stats"] });
      toast({
        title: "Training avviato",
        description: "Il modello ML è in addestramento. Controlla lo storico tra qualche minuto.",
      });
      setIsTrainDialogOpen(false);
      trainForm.reset();
    },
    onError: (error: any) => {
      toast({
        title: "Errore",
        description: error.message || "Impossibile avviare il training",
        variant: "destructive",
      });
    },
  });

  const detectMutation = useMutation({
    mutationFn: async (params: z.infer<typeof detectFormSchema>) => {
      return await apiRequest("POST", "/api/ml/detect", params);
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["/api/detections"] });
      queryClient.invalidateQueries({ queryKey: ["/api/stats"] });
      toast({
        title: "Detection avviata",
        description: "Analisi anomalie in corso. Controlla i rilevamenti tra qualche secondo.",
      });
      setIsDetectDialogOpen(false);
      detectForm.reset();
    },
    onError: (error: any) => {
      toast({
        title: "Errore",
        description: error.message || "Impossibile avviare la detection",
        variant: "destructive",
      });
    },
  });

  const onTrainSubmit = (data: z.infer<typeof trainFormSchema>) => {
    trainMutation.mutate(data);
  };

  const onDetectSubmit = (data: z.infer<typeof detectFormSchema>) => {
    detectMutation.mutate(data);
  };

  return (
    <div className="flex flex-col gap-6 p-6" data-testid="page-training">
      <div>
        <h1 className="text-3xl font-semibold" data-testid="text-page-title">Machine Learning</h1>
        <p className="text-muted-foreground" data-testid="text-page-subtitle">
          Training e detection del modello Isolation Forest
        </p>
      </div>

      {/* ML Backend Status Warning */}
      {mlStats?.ml_backend_status === "offline" && (
        <Card className="border-orange-300 dark:border-orange-700" data-testid="card-ml-offline-warning">
          <CardContent className="flex items-center gap-3 py-3">
            <XCircle className="h-5 w-5 text-orange-500 shrink-0" />
            <div>
              <p className="font-medium text-sm">ML Backend Python offline</p>
              <p className="text-xs text-muted-foreground">
                Le statistiche mostrate provengono dal database. Training e detection manuali non sono disponibili fino al riavvio del servizio.
              </p>
            </div>
          </CardContent>
        </Card>
      )}

      {/* ML Stats */}
      {mlStats && (
        <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
          <Card data-testid="card-ml-logs">
            <CardHeader className="flex flex-row items-center justify-between gap-2 space-y-0 pb-2">
              <CardTitle className="text-sm font-medium">
                {mlStats.source === "database_fallback" ? "Log Ultime 24h" : "Log Totali"}
              </CardTitle>
              <Brain className="h-4 w-4 text-muted-foreground" />
            </CardHeader>
            <CardContent>
              <div className="text-2xl font-semibold" data-testid="text-ml-logs-total">
                {(mlStats.source === "database_fallback" 
                  ? mlStats.logs_24h 
                  : mlStats.logs?.total
                )?.toLocaleString() || 0}
              </div>
              {mlStats.source !== "database_fallback" && (
                <p className="text-xs text-muted-foreground mt-1">
                  Ultima ora: {mlStats.logs?.last_hour?.toLocaleString() || 0}
                </p>
              )}
            </CardContent>
          </Card>

          <Card data-testid="card-ml-detections">
            <CardHeader className="flex flex-row items-center justify-between gap-2 space-y-0 pb-2">
              <CardTitle className="text-sm font-medium">Detection Totali</CardTitle>
              <Search className="h-4 w-4 text-muted-foreground" />
            </CardHeader>
            <CardContent>
              <div className="text-2xl font-semibold" data-testid="text-ml-detections-total">
                {mlStats.detections?.total?.toLocaleString() || 0}
              </div>
              <p className="text-xs text-muted-foreground mt-1">
                Bloccati: {mlStats.detections?.blocked?.toLocaleString() || 0}
                {mlStats.detections?.critical !== undefined && (
                  <span> | Critici: {mlStats.detections.critical.toLocaleString()}</span>
                )}
              </p>
            </CardContent>
          </Card>

          <Card data-testid="card-ml-routers">
            <CardHeader className="flex flex-row items-center justify-between gap-2 space-y-0 pb-2">
              <CardTitle className="text-sm font-medium">
                {mlStats.source === "database_fallback" ? "IP Unici" : "Router Attivi"}
              </CardTitle>
              <TrendingUp className="h-4 w-4 text-muted-foreground" />
            </CardHeader>
            <CardContent>
              <div className="text-2xl font-semibold" data-testid="text-ml-routers-active">
                {(mlStats.source === "database_fallback"
                  ? mlStats.detections?.unique_ips
                  : mlStats.routers?.active
                )?.toLocaleString() || 0}
              </div>
            </CardContent>
          </Card>
        </div>
      )}

      {/* Actions */}
      <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
        <Card data-testid="card-train-action">
          <CardHeader>
            <div className="flex items-center justify-between">
              <CardTitle className="flex items-center gap-2">
                <Brain className="h-5 w-5" />
                Addestramento Modello
              </CardTitle>
              <Badge variant="secondary" className="bg-blue-50 text-blue-700 dark:bg-blue-950 dark:text-blue-300" data-testid="badge-model-version">
                Hybrid ML v2.0.0
              </Badge>
            </div>
          </CardHeader>
          <CardContent className="space-y-4">
            <p className="text-sm text-muted-foreground">
              Addestra il modello Hybrid ML (Isolation Forest + Ensemble Classifier) analizzando i log recenti per rilevare pattern di traffico normale.
            </p>
            <Dialog open={isTrainDialogOpen} onOpenChange={setIsTrainDialogOpen}>
              <DialogTrigger asChild>
                <Button className="w-full" disabled={mlStats?.ml_backend_status === "offline"} data-testid="button-start-training">
                  <Play className="h-4 w-4 mr-2" />
                  {mlStats?.ml_backend_status === "offline" ? "ML Backend Offline" : "Avvia Training"}
                </Button>
              </DialogTrigger>
              <DialogContent data-testid="dialog-training">
                <DialogHeader>
                  <DialogTitle>Avvia Training ML</DialogTitle>
                  <DialogDescription>
                    Configura i parametri per l'addestramento del modello
                  </DialogDescription>
                </DialogHeader>
                <Form {...trainForm}>
                  <form onSubmit={trainForm.handleSubmit(onTrainSubmit)} className="space-y-4 py-4">
                    <FormField
                      control={trainForm.control}
                      name="max_records"
                      render={({ field }) => (
                        <FormItem>
                          <FormLabel>Numero Record</FormLabel>
                          <FormControl>
                            <Input type="number" {...field} data-testid="input-train-records" />
                          </FormControl>
                          <FormDescription>Consigliato: 100000</FormDescription>
                          <FormMessage />
                        </FormItem>
                      )}
                    />
                    <FormField
                      control={trainForm.control}
                      name="hours_back"
                      render={({ field }) => (
                        <FormItem>
                          <FormLabel>Ore Precedenti</FormLabel>
                          <FormControl>
                            <Input type="number" {...field} data-testid="input-train-hours" />
                          </FormControl>
                          <FormDescription>Consigliato: 24</FormDescription>
                          <FormMessage />
                        </FormItem>
                      )}
                    />
                    <DialogFooter>
                      <Button 
                        type="button" 
                        variant="outline" 
                        onClick={() => setIsTrainDialogOpen(false)} 
                        data-testid="button-cancel-training"
                      >
                        Annulla
                      </Button>
                      <Button type="submit" disabled={trainMutation.isPending || mlStats?.ml_backend_status === "offline"} data-testid="button-confirm-training">
                        {trainMutation.isPending ? "Avvio..." : "Avvia Training"}
                      </Button>
                    </DialogFooter>
                  </form>
                </Form>
              </DialogContent>
            </Dialog>
          </CardContent>
        </Card>

        <Card data-testid="card-detect-action">
          <CardHeader>
            <div className="flex items-center justify-between">
              <CardTitle className="flex items-center gap-2">
                <Search className="h-5 w-5" />
                Rilevamento Anomalie
              </CardTitle>
              <Badge variant="secondary" className="bg-green-50 text-green-700 dark:bg-green-950 dark:text-green-300" data-testid="badge-detection-version">
                Hybrid ML v2.0.0
              </Badge>
            </div>
          </CardHeader>
          <CardContent className="space-y-4">
            <p className="text-sm text-muted-foreground">
              Analizza i log recenti per rilevare anomalie e IP sospetti con il modello Hybrid ML. Blocca automaticamente gli IP critici (risk_score ≥ 80).
            </p>
            <Dialog open={isDetectDialogOpen} onOpenChange={setIsDetectDialogOpen}>
              <DialogTrigger asChild>
                <Button variant="secondary" className="w-full" disabled={mlStats?.ml_backend_status === "offline"} data-testid="button-start-detection">
                  <Search className="h-4 w-4 mr-2" />
                  {mlStats?.ml_backend_status === "offline" ? "ML Backend Offline" : "Avvia Detection"}
                </Button>
              </DialogTrigger>
              <DialogContent data-testid="dialog-detection">
                <DialogHeader>
                  <DialogTitle>Avvia Detection Anomalie</DialogTitle>
                  <DialogDescription>
                    Configura i parametri per il rilevamento anomalie
                  </DialogDescription>
                </DialogHeader>
                <Form {...detectForm}>
                  <form onSubmit={detectForm.handleSubmit(onDetectSubmit)} className="space-y-4 py-4">
                    <FormField
                      control={detectForm.control}
                      name="max_records"
                      render={({ field }) => (
                        <FormItem>
                          <FormLabel>Numero Record</FormLabel>
                          <FormControl>
                            <Input type="number" {...field} data-testid="input-detect-records" />
                          </FormControl>
                          <FormDescription>Consigliato: 50000</FormDescription>
                          <FormMessage />
                        </FormItem>
                      )}
                    />
                    <FormField
                      control={detectForm.control}
                      name="hours_back"
                      render={({ field }) => (
                        <FormItem>
                          <FormLabel>Ore Precedenti</FormLabel>
                          <FormControl>
                            <Input type="number" {...field} data-testid="input-detect-hours" />
                          </FormControl>
                          <FormDescription>Consigliato: 1</FormDescription>
                          <FormMessage />
                        </FormItem>
                      )}
                    />
                    <FormField
                      control={detectForm.control}
                      name="risk_threshold"
                      render={({ field }) => (
                        <FormItem>
                          <FormLabel>Soglia Rischio (%)</FormLabel>
                          <FormControl>
                            <Input type="number" min="0" max="100" {...field} data-testid="input-detect-threshold" />
                          </FormControl>
                          <FormDescription>Consigliato: 75</FormDescription>
                          <FormMessage />
                        </FormItem>
                      )}
                    />
                    <FormField
                      control={detectForm.control}
                      name="auto_block"
                      render={({ field }) => (
                        <FormItem className="flex flex-row items-start space-x-3 space-y-0">
                          <FormControl>
                            <Checkbox
                              checked={field.value}
                              onCheckedChange={field.onChange}
                              data-testid="checkbox-auto-block"
                            />
                          </FormControl>
                          <div className="space-y-1 leading-none">
                            <FormLabel>Blocco automatico IP critici (≥80)</FormLabel>
                          </div>
                        </FormItem>
                      )}
                    />
                    <DialogFooter>
                      <Button 
                        type="button" 
                        variant="outline" 
                        onClick={() => setIsDetectDialogOpen(false)} 
                        data-testid="button-cancel-detection"
                      >
                        Annulla
                      </Button>
                      <Button type="submit" disabled={detectMutation.isPending || mlStats?.ml_backend_status === "offline"} data-testid="button-confirm-detection">
                        {detectMutation.isPending ? "Avvio..." : "Avvia Detection"}
                      </Button>
                    </DialogFooter>
                  </form>
                </Form>
              </DialogContent>
            </Dialog>
          </CardContent>
        </Card>
      </div>

      {/* Training History */}
      <Card data-testid="card-training-history">
        <CardHeader>
          <CardTitle className="flex items-center gap-2">
            <Clock className="h-5 w-5" />
            Storico Training ({history?.length || 0})
          </CardTitle>
        </CardHeader>
        <CardContent>
          {isLoading ? (
            <div className="text-center py-8 text-muted-foreground" data-testid="text-loading">
              Caricamento...
            </div>
          ) : history && history.length > 0 ? (
            <div className="space-y-3">
              {history.map((item) => (
                <div
                  key={item.id}
                  className="p-4 rounded-lg border hover-elevate"
                  data-testid={`training-item-${item.id}`}
                >
                  <div className="flex items-start justify-between gap-4">
                    <div className="flex-1 space-y-1">
                      <div className="flex items-center gap-2">
                        <p className="font-medium" data-testid={`text-version-${item.id}`}>
                          Versione {item.modelVersion}
                        </p>
                        {item.status === "success" ? (
                          <Badge variant="outline" className="bg-green-50" data-testid={`badge-status-${item.id}`}>
                            <CheckCircle2 className="h-3 w-3 mr-1" />
                            Successo
                          </Badge>
                        ) : (
                          <Badge variant="destructive" data-testid={`badge-status-${item.id}`}>
                            <XCircle className="h-3 w-3 mr-1" />
                            Fallito
                          </Badge>
                        )}
                      </div>
                      <div className="grid grid-cols-2 md:grid-cols-4 gap-2 text-sm text-muted-foreground">
                        <div>
                          <span className="font-medium">Record:</span> {item.recordsProcessed.toLocaleString()}
                        </div>
                        <div>
                          <span className="font-medium">Feature:</span> {item.featuresCount}
                        </div>
                        {item.accuracy && (
                          <div>
                            <span className="font-medium">Accuracy:</span> {item.accuracy}%
                          </div>
                        )}
                        {item.trainingDuration && (
                          <div>
                            <span className="font-medium">Durata:</span> {item.trainingDuration}s
                          </div>
                        )}
                      </div>
                      <p className="text-xs text-muted-foreground" data-testid={`text-date-${item.id}`}>
                        {format(new Date(item.trainedAt), "dd/MM/yyyy HH:mm:ss")}
                      </p>
                      {item.notes && (
                        <p className="text-sm text-muted-foreground" data-testid={`text-notes-${item.id}`}>
                          {item.notes}
                        </p>
                      )}
                    </div>
                  </div>
                </div>
              ))}
            </div>
          ) : (
            <div className="text-center py-12 text-muted-foreground" data-testid="text-empty">
              <Brain className="h-12 w-12 mx-auto mb-4 opacity-50" />
              <p className="font-medium">Nessun training eseguito</p>
              <p className="text-sm mt-2">Avvia il primo training per addestrare il modello ML</p>
            </div>
          )}
        </CardContent>
      </Card>
    </div>
  );
}
