import { useState, useEffect, useMemo } from "react";
import { v4 as uuidv4 } from "uuid";
import {
  Dialog,
  DialogContent,
  DialogActions,
  Button,
  Box,
  Typography,
  TextField,
  Tabs,
  Tab,
  List,
  ListItem,
  ListItemButton,
  ListItemIcon,
  ListItemText,
  IconButton,
  Chip,
  Alert,
  Paper,
  FormControl,
  InputLabel,
  Select,
  MenuItem,
  Tooltip,
  alpha,
} from "@mui/material";
import {
  Add as AddIcon,
  Delete as DeleteIcon,
  Edit as EditIcon,
  ContentCopy as CopyIcon,
  Event as EventIcon,
  People as PeopleIcon,
  Place as PlaceIcon,
  Inventory as InventoryIcon,
  Person as PersonIcon,
  Category as CategoryIcon,
  TableChart as TableIcon,
  Link as LinkIcon,
  FilterList as FilterIcon,
  ViewColumn as FieldsIcon,
  Check as CheckIcon,
  Save as SaveIcon,
  Dataset as DatasetIcon,
} from "@mui/icons-material";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import {
  virtualDatasetService,
  reportGeneratorService,
} from "../../services/reportService";
import type {
  VirtualDatasetDto,
  VirtualDatasetConfiguration,
  VirtualDatasetSource,
  DatasetTypeDto,
  VirtualDatasetValidationResult,
} from "../../types/report";
import { defaultVirtualDatasetConfiguration } from "../../types/report";
import RelationshipEditor from "./RelationshipEditor";
import FilterBuilder from "./FilterBuilder";
import OutputFieldsEditor from "./OutputFieldsEditor";

interface DatasetManagerDialogProps {
  open: boolean;
  onClose: () => void;
  onDatasetCreated?: (dataset: VirtualDatasetDto) => void;
}

interface TabPanelProps {
  children?: React.ReactNode;
  index: number;
  value: number;
}

function TabPanel({ children, value, index }: TabPanelProps) {
  return (
    <Box
      role="tabpanel"
      hidden={value !== index}
      sx={{ flex: 1, overflow: "auto", p: 2 }}
    >
      {value === index && children}
    </Box>
  );
}

export default function DatasetManagerDialog({
  open,
  onClose,
  onDatasetCreated,
}: DatasetManagerDialogProps) {
  const queryClient = useQueryClient();

  // State
  const [mode, setMode] = useState<"list" | "edit">("list");
  const [selectedDataset, setSelectedDataset] =
    useState<VirtualDatasetDto | null>(null);
  const [editingConfig, setEditingConfig] =
    useState<VirtualDatasetConfiguration>(defaultVirtualDatasetConfiguration);
  const [editingInfo, setEditingInfo] = useState({
    nome: "",
    displayName: "",
    descrizione: "",
    icon: "dataset",
    categoria: "Personalizzato",
  });
  const [activeTab, setActiveTab] = useState(0);
  const [validationResult, setValidationResult] =
    useState<VirtualDatasetValidationResult | null>(null);

  // Queries
  const { data: virtualDatasets = [] } = useQuery({
    queryKey: ["virtual-datasets"],
    queryFn: () => virtualDatasetService.getAll(),
    enabled: open,
  });

  const { data: baseDatasets = [] } = useQuery({
    queryKey: ["base-datasets"],
    queryFn: () => reportGeneratorService.getAvailableDatasets(),
    enabled: open,
  });

  // Filter only base datasets (not virtual, not lists)
  const availableBaseDatasets = useMemo(() => {
    return baseDatasets.filter(
      (ds) => ds.category === "Principale" || ds.category === "Configurazione",
    );
  }, [baseDatasets]);

  // Mutations
  const createMutation = useMutation({
    mutationFn: virtualDatasetService.create,
    onSuccess: (newDataset) => {
      queryClient.invalidateQueries({ queryKey: ["virtual-datasets"] });
      onDatasetCreated?.(newDataset);
      setMode("list");
      setSelectedDataset(null);
    },
  });

  const updateMutation = useMutation({
    mutationFn: ({
      id,
      data,
    }: {
      id: number;
      data: Parameters<typeof virtualDatasetService.update>[1];
    }) => virtualDatasetService.update(id, data),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["virtual-datasets"] });
      setMode("list");
      setSelectedDataset(null);
    },
  });

  const deleteMutation = useMutation({
    mutationFn: virtualDatasetService.delete,
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["virtual-datasets"] });
    },
  });

  const cloneMutation = useMutation({
    mutationFn: virtualDatasetService.clone,
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["virtual-datasets"] });
    },
  });

  // Reset state when dialog opens
  useEffect(() => {
    if (open) {
      setMode("list");
      setSelectedDataset(null);
      setActiveTab(0);
      setValidationResult(null);
    }
  }, [open]);

  // Validation
  const validateConfig = async () => {
    try {
      const result = await virtualDatasetService.validate(editingConfig);
      setValidationResult(result);
      return result.isValid;
    } catch {
      setValidationResult({
        isValid: false,
        errors: ["Errore durante la validazione"],
        warnings: [],
      });
      return false;
    }
  };

  // Handlers
  const handleNewDataset = () => {
    setSelectedDataset(null);
    setEditingConfig(defaultVirtualDatasetConfiguration);
    setEditingInfo({
      nome: "",
      displayName: "",
      descrizione: "",
      icon: "dataset",
      categoria: "Personalizzato",
    });
    setValidationResult(null);
    setActiveTab(0);
    setMode("edit");
  };

  const handleEditDataset = (dataset: VirtualDatasetDto) => {
    setSelectedDataset(dataset);
    setEditingConfig(
      dataset.configuration || defaultVirtualDatasetConfiguration,
    );
    setEditingInfo({
      nome: dataset.nome,
      displayName: dataset.displayName,
      descrizione: dataset.descrizione || "",
      icon: dataset.icon,
      categoria: dataset.categoria,
    });
    setValidationResult(null);
    setActiveTab(0);
    setMode("edit");
  };

  const handleDeleteDataset = async (dataset: VirtualDatasetDto) => {
    if (confirm(`Eliminare il dataset "${dataset.displayName}"?`)) {
      await deleteMutation.mutateAsync(dataset.id);
    }
  };

  const handleCloneDataset = async (dataset: VirtualDatasetDto) => {
    await cloneMutation.mutateAsync(dataset.id);
  };

  const handleSave = async () => {
    const isValid = await validateConfig();
    if (!isValid) {
      setActiveTab(0); // Mostra errori
      return;
    }

    if (selectedDataset) {
      await updateMutation.mutateAsync({
        id: selectedDataset.id,
        data: {
          ...editingInfo,
          configuration: editingConfig,
        },
      });
    } else {
      await createMutation.mutateAsync({
        ...editingInfo,
        configuration: editingConfig,
      });
    }
  };

  // Source management
  const handleAddSource = (baseDataset: DatasetTypeDto) => {
    const newSource: VirtualDatasetSource = {
      id: uuidv4(),
      datasetId: baseDataset.id,
      alias: baseDataset.id,
      isPrimary: editingConfig.sources.length === 0,
    };
    setEditingConfig((prev) => ({
      ...prev,
      sources: [...prev.sources, newSource],
      primarySourceId:
        prev.sources.length === 0 ? newSource.id : prev.primarySourceId,
    }));
  };

  const handleRemoveSource = (sourceId: string) => {
    setEditingConfig((prev) => {
      const newSources = prev.sources.filter((s) => s.id !== sourceId);
      const newRelationships = prev.relationships.filter(
        (r) => r.fromSourceId !== sourceId && r.toSourceId !== sourceId,
      );
      const newFilters = prev.filters.filter((f) => f.sourceId !== sourceId);
      const newOutputFields = prev.outputFields.filter(
        (f) => f.sourceId !== sourceId,
      );

      // Se era il primary, assegna il primo disponibile
      let newPrimaryId = prev.primarySourceId;
      if (prev.primarySourceId === sourceId && newSources.length > 0) {
        newPrimaryId = newSources[0].id;
        newSources[0].isPrimary = true;
      }

      return {
        ...prev,
        sources: newSources,
        relationships: newRelationships,
        filters: newFilters,
        outputFields: newOutputFields,
        primarySourceId: newPrimaryId,
      };
    });
  };

  const handleSetPrimary = (sourceId: string) => {
    setEditingConfig((prev) => ({
      ...prev,
      sources: prev.sources.map((s) => ({
        ...s,
        isPrimary: s.id === sourceId,
      })),
      primarySourceId: sourceId,
    }));
  };

  const handleUpdateSourceAlias = (sourceId: string, alias: string) => {
    setEditingConfig((prev) => ({
      ...prev,
      sources: prev.sources.map((s) =>
        s.id === sourceId ? { ...s, alias } : s,
      ),
    }));
  };

  const getDatasetIcon = (icon: string) => {
    switch (icon) {
      case "event":
        return <EventIcon />;
      case "people":
        return <PeopleIcon />;
      case "place":
        return <PlaceIcon />;
      case "inventory":
        return <InventoryIcon />;
      case "person":
        return <PersonIcon />;
      case "category":
        return <CategoryIcon />;
      case "dataset":
        return <DatasetIcon />;
      default:
        return <TableIcon />;
    }
  };

  const getSourceDataset = (source: VirtualDatasetSource) => {
    return availableBaseDatasets.find((d) => d.id === source.datasetId);
  };

  // Render list mode
  const renderList = () => (
    <Box sx={{ height: "100%", display: "flex", flexDirection: "column" }}>
      <Box
        sx={{
          p: 2,
          borderBottom: 1,
          borderColor: "divider",
          display: "flex",
          justifyContent: "space-between",
          alignItems: "center",
        }}
      >
        <Typography variant="h6">Dataset Virtuali</Typography>
        <Button
          variant="contained"
          startIcon={<AddIcon />}
          onClick={handleNewDataset}
        >
          Nuovo Dataset
        </Button>
      </Box>

      {virtualDatasets.length === 0 ? (
        <Box sx={{ p: 4, textAlign: "center" }}>
          <DatasetIcon sx={{ fontSize: 64, color: "grey.400", mb: 2 }} />
          <Typography variant="h6" color="text.secondary" gutterBottom>
            Nessun Dataset Virtuale
          </Typography>
          <Typography variant="body2" color="text.secondary" mb={2}>
            Crea dataset virtuali per combinare e filtrare i dati da più
            sorgenti.
          </Typography>
          <Button
            variant="outlined"
            startIcon={<AddIcon />}
            onClick={handleNewDataset}
          >
            Crea il primo dataset
          </Button>
        </Box>
      ) : (
        <List sx={{ flex: 1, overflow: "auto" }}>
          {virtualDatasets.map((dataset) => (
            <ListItem
              key={dataset.id}
              secondaryAction={
                <Box>
                  <Tooltip title="Modifica">
                    <IconButton onClick={() => handleEditDataset(dataset)}>
                      <EditIcon />
                    </IconButton>
                  </Tooltip>
                  <Tooltip title="Duplica">
                    <IconButton onClick={() => handleCloneDataset(dataset)}>
                      <CopyIcon />
                    </IconButton>
                  </Tooltip>
                  <Tooltip title="Elimina">
                    <IconButton
                      onClick={() => handleDeleteDataset(dataset)}
                      color="error"
                    >
                      <DeleteIcon />
                    </IconButton>
                  </Tooltip>
                </Box>
              }
              disablePadding
            >
              <ListItemButton onClick={() => handleEditDataset(dataset)}>
                <ListItemIcon>{getDatasetIcon(dataset.icon)}</ListItemIcon>
                <ListItemText
                  primary={dataset.displayName}
                  secondary={
                    <Box component="span">
                      {dataset.descrizione || "Nessuna descrizione"}
                      <Box component="span" sx={{ display: "block", mt: 0.5 }}>
                        <Chip
                          label={dataset.categoria}
                          size="small"
                          sx={{ height: 20, fontSize: "0.7rem" }}
                        />
                        <Chip
                          label={`${dataset.configuration?.sources.length || 0} sorgenti`}
                          size="small"
                          sx={{
                            ml: 0.5,
                            height: 20,
                            fontSize: "0.7rem",
                          }}
                        />
                      </Box>
                    </Box>
                  }
                  secondaryTypographyProps={{ component: "div" }}
                />
              </ListItemButton>
            </ListItem>
          ))}
        </List>
      )}
    </Box>
  );

  // Render edit mode
  const renderEdit = () => (
    <Box sx={{ height: "100%", display: "flex", flexDirection: "column" }}>
      {/* Header */}
      <Box sx={{ p: 2, borderBottom: 1, borderColor: "divider" }}>
        <Typography variant="h6">
          {selectedDataset ? "Modifica Dataset" : "Nuovo Dataset Virtuale"}
        </Typography>
      </Box>

      {/* Validation alerts */}
      {validationResult && (
        <Box sx={{ px: 2, pt: 2 }}>
          {validationResult.errors.length > 0 && (
            <Alert severity="error" sx={{ mb: 1 }}>
              <Typography variant="subtitle2">Errori:</Typography>
              <ul style={{ margin: 0, paddingLeft: 20 }}>
                {validationResult.errors.map((err, i) => (
                  <li key={i}>{err}</li>
                ))}
              </ul>
            </Alert>
          )}
          {validationResult.warnings.length > 0 && (
            <Alert severity="warning">
              <Typography variant="subtitle2">Avvisi:</Typography>
              <ul style={{ margin: 0, paddingLeft: 20 }}>
                {validationResult.warnings.map((warn, i) => (
                  <li key={i}>{warn}</li>
                ))}
              </ul>
            </Alert>
          )}
          {validationResult.isValid &&
            validationResult.warnings.length === 0 && (
              <Alert severity="success">Configurazione valida</Alert>
            )}
        </Box>
      )}

      {/* Tabs */}
      <Tabs
        value={activeTab}
        onChange={(_, v) => setActiveTab(v)}
        sx={{ borderBottom: 1, borderColor: "divider" }}
      >
        <Tab label="Info" icon={<DatasetIcon />} iconPosition="start" />
        <Tab
          label={`Sorgenti (${editingConfig.sources.length})`}
          icon={<TableIcon />}
          iconPosition="start"
        />
        <Tab
          label={`Relazioni (${editingConfig.relationships.length})`}
          icon={<LinkIcon />}
          iconPosition="start"
        />
        <Tab
          label={`Filtri (${editingConfig.filters.filter((f) => f.enabled).length})`}
          icon={<FilterIcon />}
          iconPosition="start"
        />
        <Tab
          label={`Campi (${editingConfig.outputFields.filter((f) => f.included).length})`}
          icon={<FieldsIcon />}
          iconPosition="start"
        />
      </Tabs>

      {/* Tab: Info */}
      <TabPanel value={activeTab} index={0}>
        <Box
          sx={{
            display: "flex",
            flexDirection: "column",
            gap: 2,
            maxWidth: 500,
          }}
        >
          <TextField
            label="Nome Identificativo"
            value={editingInfo.nome}
            onChange={(e) =>
              setEditingInfo((prev) => ({
                ...prev,
                nome: e.target.value.replace(/\s/g, "_").toLowerCase(),
              }))
            }
            required
            helperText="Nome univoco usato internamente (senza spazi)"
          />
          <TextField
            label="Nome Visualizzato"
            value={editingInfo.displayName}
            onChange={(e) =>
              setEditingInfo((prev) => ({
                ...prev,
                displayName: e.target.value,
              }))
            }
            required
          />
          <TextField
            label="Descrizione"
            value={editingInfo.descrizione}
            onChange={(e) =>
              setEditingInfo((prev) => ({
                ...prev,
                descrizione: e.target.value,
              }))
            }
            multiline
            rows={2}
          />
          <FormControl>
            <InputLabel>Categoria</InputLabel>
            <Select
              value={editingInfo.categoria}
              label="Categoria"
              onChange={(e) =>
                setEditingInfo((prev) => ({
                  ...prev,
                  categoria: e.target.value,
                }))
              }
            >
              <MenuItem value="Personalizzato">Personalizzato</MenuItem>
              <MenuItem value="Report Eventi">Report Eventi</MenuItem>
              <MenuItem value="Report Clienti">Report Clienti</MenuItem>
              <MenuItem value="Report Articoli">Report Articoli</MenuItem>
              <MenuItem value="Analisi">Analisi</MenuItem>
            </Select>
          </FormControl>
          <FormControl>
            <InputLabel>Icona</InputLabel>
            <Select
              value={editingInfo.icon}
              label="Icona"
              onChange={(e) =>
                setEditingInfo((prev) => ({ ...prev, icon: e.target.value }))
              }
            >
              <MenuItem value="dataset">
                <ListItemIcon>
                  <DatasetIcon />
                </ListItemIcon>
                Dataset
              </MenuItem>
              <MenuItem value="event">
                <ListItemIcon>
                  <EventIcon />
                </ListItemIcon>
                Evento
              </MenuItem>
              <MenuItem value="people">
                <ListItemIcon>
                  <PeopleIcon />
                </ListItemIcon>
                Persone
              </MenuItem>
              <MenuItem value="place">
                <ListItemIcon>
                  <PlaceIcon />
                </ListItemIcon>
                Location
              </MenuItem>
              <MenuItem value="inventory">
                <ListItemIcon>
                  <InventoryIcon />
                </ListItemIcon>
                Inventario
              </MenuItem>
            </Select>
          </FormControl>
        </Box>
      </TabPanel>

      {/* Tab: Sorgenti */}
      <TabPanel value={activeTab} index={1}>
        <Box sx={{ display: "flex", gap: 2, height: "100%" }}>
          {/* Dataset disponibili */}
          <Paper variant="outlined" sx={{ width: 280, p: 2 }}>
            <Typography variant="subtitle2" gutterBottom>
              Dataset Disponibili
            </Typography>
            <Typography
              variant="caption"
              color="text.secondary"
              display="block"
              mb={2}
            >
              Clicca per aggiungere una sorgente
            </Typography>
            <List dense>
              {availableBaseDatasets.map((dataset) => (
                <ListItemButton
                  key={dataset.id}
                  onClick={() => handleAddSource(dataset)}
                  sx={{ borderRadius: 1, mb: 0.5 }}
                >
                  <ListItemIcon sx={{ minWidth: 36 }}>
                    {getDatasetIcon(dataset.icon)}
                  </ListItemIcon>
                  <ListItemText
                    primary={dataset.name}
                    secondary={dataset.description}
                    primaryTypographyProps={{ variant: "body2" }}
                    secondaryTypographyProps={{
                      variant: "caption",
                      noWrap: true,
                    }}
                  />
                </ListItemButton>
              ))}
            </List>
          </Paper>

          {/* Sorgenti selezionate */}
          <Box sx={{ flex: 1 }}>
            <Typography variant="subtitle2" gutterBottom>
              Sorgenti nel Dataset ({editingConfig.sources.length})
            </Typography>
            {editingConfig.sources.length === 0 ? (
              <Alert severity="info">
                Aggiungi almeno una sorgente dati dal pannello a sinistra
              </Alert>
            ) : (
              <List>
                {editingConfig.sources.map((source) => {
                  const baseDataset = getSourceDataset(source);
                  return (
                    <Paper
                      key={source.id}
                      variant="outlined"
                      sx={{
                        mb: 1,
                        p: 2,
                        bgcolor: source.isPrimary
                          ? (theme) => alpha(theme.palette.primary.main, 0.08)
                          : "inherit",
                      }}
                    >
                      <Box
                        sx={{ display: "flex", alignItems: "center", gap: 2 }}
                      >
                        <Box
                          sx={{
                            display: "flex",
                            alignItems: "center",
                            gap: 1,
                            flex: 1,
                          }}
                        >
                          {baseDataset && getDatasetIcon(baseDataset.icon)}
                          <Box>
                            <Typography variant="subtitle2">
                              {baseDataset?.name || source.datasetId}
                            </Typography>
                            <Typography
                              variant="caption"
                              color="text.secondary"
                            >
                              ID: {source.datasetId}
                            </Typography>
                          </Box>
                        </Box>

                        <TextField
                          label="Alias"
                          size="small"
                          value={source.alias}
                          onChange={(e) =>
                            handleUpdateSourceAlias(source.id, e.target.value)
                          }
                          sx={{ width: 120 }}
                        />

                        {source.isPrimary ? (
                          <Chip
                            icon={<CheckIcon />}
                            label="Primario"
                            color="primary"
                            size="small"
                          />
                        ) : (
                          <Button
                            size="small"
                            onClick={() => handleSetPrimary(source.id)}
                          >
                            Imposta Primario
                          </Button>
                        )}

                        <IconButton
                          size="small"
                          color="error"
                          onClick={() => handleRemoveSource(source.id)}
                        >
                          <DeleteIcon />
                        </IconButton>
                      </Box>
                    </Paper>
                  );
                })}
              </List>
            )}
          </Box>
        </Box>
      </TabPanel>

      {/* Tab: Relazioni */}
      <TabPanel value={activeTab} index={2}>
        <RelationshipEditor
          sources={editingConfig.sources}
          relationships={editingConfig.relationships}
          baseDatasets={availableBaseDatasets}
          onChange={(relationships) =>
            setEditingConfig((prev) => ({ ...prev, relationships }))
          }
        />
      </TabPanel>

      {/* Tab: Filtri */}
      <TabPanel value={activeTab} index={3}>
        <FilterBuilder
          sources={editingConfig.sources}
          filters={editingConfig.filters}
          baseDatasets={availableBaseDatasets}
          onChange={(filters) =>
            setEditingConfig((prev) => ({ ...prev, filters }))
          }
        />
      </TabPanel>

      {/* Tab: Campi Output */}
      <TabPanel value={activeTab} index={4}>
        <OutputFieldsEditor
          sources={editingConfig.sources}
          outputFields={editingConfig.outputFields}
          baseDatasets={availableBaseDatasets}
          onChange={(outputFields) =>
            setEditingConfig((prev) => ({ ...prev, outputFields }))
          }
        />
      </TabPanel>
    </Box>
  );

  return (
    <Dialog
      open={open}
      onClose={onClose}
      maxWidth="lg"
      fullWidth
      PaperProps={{ sx: { height: "85vh" } }}
    >
      <DialogContent sx={{ p: 0, display: "flex", flexDirection: "column" }}>
        {mode === "list" ? renderList() : renderEdit()}
      </DialogContent>

      <DialogActions
        sx={{ px: 3, py: 2, borderTop: 1, borderColor: "divider" }}
      >
        {mode === "list" ? (
          <Button onClick={onClose}>Chiudi</Button>
        ) : (
          <>
            <Button onClick={() => setMode("list")}>Annulla</Button>
            <Button variant="outlined" onClick={validateConfig}>
              Valida
            </Button>
            <Button
              variant="contained"
              startIcon={<SaveIcon />}
              onClick={handleSave}
              disabled={
                !editingInfo.nome ||
                !editingInfo.displayName ||
                createMutation.isPending ||
                updateMutation.isPending
              }
            >
              {createMutation.isPending || updateMutation.isPending
                ? "Salvataggio..."
                : "Salva"}
            </Button>
          </>
        )}
      </DialogActions>
    </Dialog>
  );
}
