import { useState, useMemo } from "react";
import { v4 as uuidv4 } from "uuid";
import {
  Box,
  Typography,
  Paper,
  IconButton,
  TextField,
  Alert,
  Checkbox,
  List,
  ListItem,
  ListItemButton,
  ListItemIcon,
  ListItemText,
  Chip,
  Tooltip,
  FormControlLabel,
  Switch,
  InputAdornment,
} from "@mui/material";
import {
  DragIndicator as DragIcon,
  Search as SearchIcon,
  SelectAll as SelectAllIcon,
  Deselect as DeselectIcon,
  TextFields as TextIcon,
  Numbers as NumberIcon,
  CalendarMonth as DateIcon,
  AttachMoney as CurrencyIcon,
} from "@mui/icons-material";
import { useQueries } from "@tanstack/react-query";
import { reportGeneratorService } from "../../services/reportService";
import type {
  VirtualDatasetSource,
  VirtualDatasetOutputField,
  DatasetTypeDto,
  DataFieldDto,
} from "../../types/report";

interface OutputFieldsEditorProps {
  sources: VirtualDatasetSource[];
  outputFields: VirtualDatasetOutputField[];
  baseDatasets: DatasetTypeDto[];
  onChange: (outputFields: VirtualDatasetOutputField[]) => void;
}

export default function OutputFieldsEditor({
  sources,
  outputFields,
  baseDatasets,
  onChange,
}: OutputFieldsEditorProps) {
  const [search, setSearch] = useState("");
  const [showOnlySelected, setShowOnlySelected] = useState(false);

  // Fetch schemas for all sources
  const schemaQueries = useQueries({
    queries: sources.map((source) => ({
      queryKey: ["dataset-schema", source.datasetId],
      queryFn: () => reportGeneratorService.getSchema(source.datasetId),
      staleTime: 60000,
    })),
  });

  // Build all available fields from all sources
  const allAvailableFields = useMemo(() => {
    const fields: Array<{
      sourceId: string;
      sourceAlias: string;
      sourceName: string;
      field: DataFieldDto;
      fullName: string;
    }> = [];

    sources.forEach((source, index) => {
      const schema = schemaQueries[index]?.data;
      const baseDataset = baseDatasets.find((d) => d.id === source.datasetId);

      if (schema) {
        schema.fields.forEach((field) => {
          fields.push({
            sourceId: source.id,
            sourceAlias: source.alias,
            sourceName: baseDataset?.name || source.datasetId,
            field,
            fullName: `${source.alias}.${field.name}`,
          });
        });
      }
    });

    return fields;
  }, [sources, schemaQueries, baseDatasets]);

  // Filter fields by search
  const filteredFields = useMemo(() => {
    let result = allAvailableFields;

    if (search) {
      const searchLower = search.toLowerCase();
      result = result.filter(
        (f) =>
          f.field.name.toLowerCase().includes(searchLower) ||
          f.field.label.toLowerCase().includes(searchLower) ||
          f.sourceAlias.toLowerCase().includes(searchLower),
      );
    }

    if (showOnlySelected) {
      result = result.filter((f) =>
        outputFields.some(
          (of) =>
            of.sourceId === f.sourceId &&
            of.fieldName === f.field.name &&
            of.included,
        ),
      );
    }

    return result;
  }, [allAvailableFields, search, showOnlySelected, outputFields]);

  // Group fields by source
  const fieldsBySource = useMemo(() => {
    const groups: Record<string, typeof filteredFields> = {};
    filteredFields.forEach((f) => {
      if (!groups[f.sourceId]) {
        groups[f.sourceId] = [];
      }
      groups[f.sourceId].push(f);
    });
    return groups;
  }, [filteredFields]);

  const getFieldIcon = (type: string) => {
    switch (type) {
      case "currency":
        return <CurrencyIcon fontSize="small" />;
      case "number":
        return <NumberIcon fontSize="small" />;
      case "date":
      case "datetime":
      case "time":
        return <DateIcon fontSize="small" />;
      default:
        return <TextIcon fontSize="small" />;
    }
  };

  const isFieldSelected = (sourceId: string, fieldName: string) => {
    const existing = outputFields.find(
      (of) => of.sourceId === sourceId && of.fieldName === fieldName,
    );
    return existing?.included ?? false;
  };

  const handleToggleField = (
    sourceId: string,
    field: DataFieldDto,
    sourceAlias: string,
  ) => {
    const existing = outputFields.find(
      (of) => of.sourceId === sourceId && of.fieldName === field.name,
    );

    if (existing) {
      // Toggle existing
      onChange(
        outputFields.map((of) =>
          of.id === existing.id ? { ...of, included: !of.included } : of,
        ),
      );
    } else {
      // Add new
      const newField: VirtualDatasetOutputField = {
        id: uuidv4(),
        sourceId,
        fieldName: field.name,
        alias: undefined,
        label: field.label,
        group: sourceAlias,
        order: outputFields.length,
        included: true,
      };
      onChange([...outputFields, newField]);
    }
  };

  const handleUpdateFieldConfig = (
    fieldId: string,
    updates: Partial<VirtualDatasetOutputField>,
  ) => {
    onChange(
      outputFields.map((of) =>
        of.id === fieldId ? { ...of, ...updates } : of,
      ),
    );
  };

  const handleSelectAll = () => {
    const newFields: VirtualDatasetOutputField[] = [];
    let order = 0;

    allAvailableFields.forEach(({ sourceId, sourceAlias, field }) => {
      const existing = outputFields.find(
        (of) => of.sourceId === sourceId && of.fieldName === field.name,
      );
      if (existing) {
        newFields.push({ ...existing, included: true, order: order++ });
      } else {
        newFields.push({
          id: uuidv4(),
          sourceId,
          fieldName: field.name,
          label: field.label,
          group: sourceAlias,
          order: order++,
          included: true,
        });
      }
    });

    onChange(newFields);
  };

  const handleDeselectAll = () => {
    onChange(outputFields.map((of) => ({ ...of, included: false })));
  };

  const selectedCount = outputFields.filter((of) => of.included).length;

  if (sources.length === 0) {
    return (
      <Alert severity="info">
        Aggiungi almeno una sorgente dati per selezionare i campi di output.
      </Alert>
    );
  }

  return (
    <Box sx={{ display: "flex", gap: 2, height: "100%" }}>
      {/* Left: Field selector */}
      <Paper
        variant="outlined"
        sx={{ width: 400, display: "flex", flexDirection: "column" }}
      >
        <Box sx={{ p: 2, borderBottom: 1, borderColor: "divider" }}>
          <Typography variant="subtitle2" gutterBottom>
            Campi Disponibili
          </Typography>
          <TextField
            placeholder="Cerca campo..."
            size="small"
            fullWidth
            value={search}
            onChange={(e) => setSearch(e.target.value)}
            InputProps={{
              startAdornment: (
                <InputAdornment position="start">
                  <SearchIcon fontSize="small" />
                </InputAdornment>
              ),
            }}
            sx={{ mb: 1 }}
          />
          <Box
            sx={{
              display: "flex",
              justifyContent: "space-between",
              alignItems: "center",
            }}
          >
            <FormControlLabel
              control={
                <Switch
                  checked={showOnlySelected}
                  onChange={(e) => setShowOnlySelected(e.target.checked)}
                  size="small"
                />
              }
              label={
                <Typography variant="caption">Solo selezionati</Typography>
              }
            />
            <Box>
              <Tooltip title="Seleziona tutti">
                <IconButton size="small" onClick={handleSelectAll}>
                  <SelectAllIcon />
                </IconButton>
              </Tooltip>
              <Tooltip title="Deseleziona tutti">
                <IconButton size="small" onClick={handleDeselectAll}>
                  <DeselectIcon />
                </IconButton>
              </Tooltip>
            </Box>
          </Box>
        </Box>

        <List sx={{ flex: 1, overflow: "auto" }} dense>
          {Object.entries(fieldsBySource).map(([sourceId, fields]) => {
            const source = sources.find((s) => s.id === sourceId);
            const baseDataset = baseDatasets.find(
              (d) => d.id === source?.datasetId,
            );

            return (
              <Box key={sourceId}>
                <ListItem sx={{ bgcolor: "grey.100" }}>
                  <ListItemText
                    primary={`${source?.alias || sourceId} (${baseDataset?.name || ""})`}
                    primaryTypographyProps={{
                      variant: "caption",
                      fontWeight: 600,
                    }}
                  />
                  <Chip
                    label={
                      fields.filter((f) =>
                        isFieldSelected(sourceId, f.field.name),
                      ).length
                    }
                    size="small"
                    color="primary"
                    sx={{ height: 18, fontSize: "0.65rem" }}
                  />
                </ListItem>
                {fields.map(({ field }) => {
                  const selected = isFieldSelected(sourceId, field.name);
                  return (
                    <ListItemButton
                      key={`${sourceId}-${field.name}`}
                      onClick={() =>
                        handleToggleField(
                          sourceId,
                          field,
                          source?.alias || sourceId,
                        )
                      }
                      sx={{ pl: 3 }}
                    >
                      <ListItemIcon sx={{ minWidth: 32 }}>
                        <Checkbox
                          edge="start"
                          checked={selected}
                          size="small"
                        />
                      </ListItemIcon>
                      <ListItemIcon sx={{ minWidth: 28 }}>
                        {getFieldIcon(field.type)}
                      </ListItemIcon>
                      <ListItemText
                        primary={field.label}
                        secondary={field.name}
                        primaryTypographyProps={{ variant: "body2" }}
                        secondaryTypographyProps={{
                          variant: "caption",
                          sx: { fontFamily: "monospace" },
                        }}
                      />
                      <Chip
                        label={field.type}
                        size="small"
                        sx={{ height: 18, fontSize: "0.6rem" }}
                      />
                    </ListItemButton>
                  );
                })}
              </Box>
            );
          })}
        </List>

        <Box
          sx={{
            p: 1,
            borderTop: 1,
            borderColor: "divider",
            bgcolor: "grey.50",
          }}
        >
          <Typography variant="caption" color="text.secondary">
            {selectedCount} campi selezionati su {allAvailableFields.length}
          </Typography>
        </Box>
      </Paper>

      {/* Right: Selected fields configuration */}
      <Box sx={{ flex: 1, display: "flex", flexDirection: "column" }}>
        <Typography variant="subtitle2" gutterBottom>
          Campi Selezionati ({selectedCount})
        </Typography>
        <Typography variant="caption" color="text.secondary" sx={{ mb: 2 }}>
          Configura alias e label per i campi selezionati. Lascia vuoto per
          usare i valori default.
        </Typography>

        {selectedCount === 0 ? (
          <Alert severity="info">
            Seleziona i campi da includere nel dataset dalla lista a sinistra.
            Se non selezioni nessun campo, verranno inclusi tutti
            automaticamente.
          </Alert>
        ) : (
          <Paper variant="outlined" sx={{ flex: 1, overflow: "auto" }}>
            <List dense>
              {outputFields
                .filter((of) => of.included)
                .sort((a, b) => a.order - b.order)
                .map((field) => {
                  const source = sources.find((s) => s.id === field.sourceId);
                  const schema =
                    schemaQueries[
                      sources.findIndex((s) => s.id === field.sourceId)
                    ]?.data;
                  const fieldDef = schema?.fields.find(
                    (f) => f.name === field.fieldName,
                  );

                  return (
                    <ListItem
                      key={field.id}
                      sx={{
                        borderBottom: 1,
                        borderColor: "divider",
                        flexDirection: "column",
                        alignItems: "stretch",
                        py: 1.5,
                      }}
                    >
                      <Box
                        sx={{
                          display: "flex",
                          alignItems: "center",
                          gap: 1,
                          mb: 1,
                        }}
                      >
                        <DragIcon color="action" sx={{ cursor: "grab" }} />
                        <Box sx={{ flex: 1 }}>
                          <Typography variant="body2" fontWeight={500}>
                            {source?.alias}.{field.fieldName}
                          </Typography>
                          <Typography variant="caption" color="text.secondary">
                            {fieldDef?.label} ({fieldDef?.type})
                          </Typography>
                        </Box>
                        <IconButton
                          size="small"
                          onClick={() =>
                            handleToggleField(
                              field.sourceId,
                              fieldDef!,
                              source?.alias || "",
                            )
                          }
                        >
                          <DeselectIcon fontSize="small" />
                        </IconButton>
                      </Box>

                      <Box sx={{ display: "flex", gap: 1, pl: 4 }}>
                        <TextField
                          label="Alias"
                          size="small"
                          value={field.alias || ""}
                          onChange={(e) =>
                            handleUpdateFieldConfig(field.id, {
                              alias: e.target.value || undefined,
                            })
                          }
                          placeholder={`${source?.alias}_${field.fieldName}`}
                          sx={{ flex: 1 }}
                        />
                        <TextField
                          label="Label"
                          size="small"
                          value={field.label || ""}
                          onChange={(e) =>
                            handleUpdateFieldConfig(field.id, {
                              label: e.target.value,
                            })
                          }
                          placeholder={fieldDef?.label}
                          sx={{ flex: 1 }}
                        />
                        <TextField
                          label="Gruppo"
                          size="small"
                          value={field.group || ""}
                          onChange={(e) =>
                            handleUpdateFieldConfig(field.id, {
                              group: e.target.value,
                            })
                          }
                          placeholder={source?.alias}
                          sx={{ width: 120 }}
                        />
                      </Box>
                    </ListItem>
                  );
                })}
            </List>
          </Paper>
        )}
      </Box>
    </Box>
  );
}
