import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import Dialog from '@mui/material/Dialog';
import DialogTitle from '@mui/material/DialogTitle';
import DialogContent from '@mui/material/DialogContent';
import DialogActions from '@mui/material/DialogActions';
import Button from '@mui/material/Button';
import TextField from '@mui/material/TextField';
import Box from '@mui/material/Box';
import Typography from '@mui/material/Typography';
import Table from '@mui/material/Table';
import TableHead from '@mui/material/TableHead';
import TableRow from '@mui/material/TableRow';
import TableCell from '@mui/material/TableCell';
import TableBody from '@mui/material/TableBody';
import IconButton from '@mui/material/IconButton';
import FormControl from '@mui/material/FormControl';
import InputLabel from '@mui/material/InputLabel';
import Select from '@mui/material/Select';
import MenuItem from '@mui/material/MenuItem';
import FormHelperText from '@mui/material/FormHelperText';
import Alert from '@mui/material/Alert';
import Tabs from '@mui/material/Tabs';
import Tab from '@mui/material/Tab';
import DeleteIcon from '@mui/icons-material/Delete';
import { Trans } from '@lingui/macro';
import axios from 'B/axios';
import $ from 'jquery';
import 'jstree';
// Falls das JsTree-Theme-CSS nicht global geladen wird:
// import 'jstree/dist/themes/default/style.css';

interface FolderOption { id: number | string; label: string } // legacy
type FolderGroup = { id: string; label: string; items: { id: string | number; label: string }[] }; // legacy

interface CreateListDialogProps {
  open: boolean;
  onClose: () => void;
  onCreate: (args: {
    name: string;
    type: string;
    folderId: number | string;
    sources?: { idShort: string; type: string; text: string }[];
  }) => Promise<{ newId: number | string }>;
  availableTypes?: string[];
  availableFolders?: FolderOption[];   // legacy
  availableAreaGroups?: FolderGroup[]; // legacy
}

type SourceRow = { idShort: string; type: string; text: string; icon: string };
const ICONS: Record<string, string> = {
  WTG: 'wtg24.png', MWT: 'mwt24.png', DYN: 'dyn24.png', STR: 'str24.png',
  BST: 'bst24.png', GRP: 'grp24.png', MLD: 'mld24.png', REP: 'pdf24.png', DEX: 'exp24.png', BER: 'ber24.png',
  INF: 'inf24.png',
};

const AREA_ID_PREFIX = 'BER'; // Prefix der Bereichs-IDs aus /TreeREP
const AREA_ICON_PATH = '/icon8/ber24.png';
const FOLDER_ICON_PATH = `/icon8/${ICONS.GRP}`;

const typeFromNodeId = (id?: string) => (id ?? '').substring(3, 6);
const shortIdFromNodeId = (id?: string) => (id ?? '').substring(3);
const iconForType = (type: string) => ICONS[type] ?? 'wtg24.png';

type JsTreeServerNode = {
  id: string;
  text: string;
  children: boolean | JsTreeServerNode[];
  type?: string;
  icon?: string | boolean;
};

type TabPanelProps = {
  children: React.ReactNode;
  value: number;
  index: number;
};

const TabPanel = ({ children, value, index }: TabPanelProps) => {
  const isActive = value === index;
  return (
    <div
      role="tabpanel"
      hidden={!isActive}
      id={`create-list-tabpanel-${index}`}
      aria-labelledby={`create-list-tab-${index}`}
    >
      {isActive && <Box mt={2}>{children}</Box>}
    </div>
  );
};

type SummaryItemProps = { label: React.ReactNode; value: React.ReactNode };

const SummaryItem = ({ label, value }: SummaryItemProps) => (
  <Box>
    <Typography variant="caption" color="textSecondary">
      {label}
    </Typography>
    <Typography variant="body2">{value || '–'}</Typography>
  </Box>
);


// ---------- Helpers: tolerant parsen & normalisieren ----------
function safeParseJson(data: any) {
  if (data == null) return null;
  if (typeof data === 'string') {
    try { return JSON.parse(data); } catch { return data; }
  }
  return data;
}

// /TreeREP → Array von Bereichs-Knoten (type='area')
function normalizeTreeRepToAreas(raw: any): JsTreeServerNode[] {
  const data = safeParseJson(raw);

  // Sammle mögliche Arrays
  let rows: any[] = [];
  if (Array.isArray(data)) rows = data;
  else if (data && Array.isArray((data as any).rows)) rows = (data as any).rows;
  else if (data && Array.isArray((data as any).data)) rows = (data as any).data;
  else if (data && typeof data === 'object') rows = [data]; // Einzelobjekt fallback

  // DTO-Format: [{ ber_id, ber_name }]
  if (rows.length && (('ber_id' in rows[0]) || ('ber_name' in rows[0]))) {
    return rows
      .filter(r => r?.ber_id != null)
      .map(r => ({
        id: `${AREA_ID_PREFIX}${r.ber_id}`,
        text: String(r.ber_name ?? r.ber_id),
        children: true,
        type: 'area',
        icon: AREA_ICON_PATH,
      }));
  }

  // JsTree-ähnlich: [{ id, text, children? }]
  if (rows.length && ('id' in rows[0]) && ('text' in rows[0])) {
    return rows.map((n: any) => ({
      ...n,
      children: n.children ?? true,
      type: n.type ?? 'area',
      icon: n.icon ?? true,
    }));
  }

  return [];
}

function areaGroupsToAreas(groups: FolderGroup[] = []): JsTreeServerNode[] {
  const map = new Map<string, JsTreeServerNode>();
  for (const grp of groups) {
    for (const item of grp?.items ?? []) {
      const id = String(item.id);
      if (map.has(id)) continue;
      map.set(id, {
        id,
        text: String(item.label ?? item.id),
        children: true,
        type: 'area',
        icon: AREA_ICON_PATH,
      });
    }
  }
  return Array.from(map.values());
}

// --- getAreas: einmal pro Dialog laden & cachen, beide Trees nutzen dieselben Daten ---
let _areasCache: JsTreeServerNode[] | null = null;
async function fetchTreeRepAreas(): Promise<JsTreeServerNode[]> {
  if (_areasCache) return _areasCache;
  try {
    const resp = await axios.get('/TreeREP', { responseType: 'text' });
    const areas = normalizeTreeRepToAreas(resp.data);
    _areasCache = areas;
    return areas;
  } catch (error) {
    console.error('TreeREP fetch failed', error);
    return [];
  }
}

const CreateListDialog: React.FC<CreateListDialogProps> = ({
  open,
  onClose,
  onCreate,
  availableTypes = [],
  availableAreaGroups = [],
}) => {
  const firstType = useMemo(() => availableTypes[0] ?? '', [availableTypes]);
  const fallbackAreas = useMemo(() => areaGroupsToAreas(availableAreaGroups), [availableAreaGroups]);

  const [name, setName] = useState('');
  const [type, setType] = useState<string>('');               // bei Öffnen auf firstType
  const [folderId, setFolderId] = useState<number | string>('');      // finaler Ordner
  const [folderPathLabel, setFolderPathLabel] = useState<string>(''); // „A / B / C“
  const [busy, setBusy] = useState(false);
  const [error, setError] = useState<string>('');
  const [sources, setSources] = useState<SourceRow[]>([]);
  const [activeTab, setActiveTab] = useState(0);

  // UI-Hinweise
  const [folderTreeHint, setFolderTreeHint] = useState<string>('');
  const [sourcesTreeHint, setSourcesTreeHint] = useState<string>('');

  // Tree-Refs
  const treeRef = useRef<HTMLDivElement | null>(null);        // Datenquellen (immer sichtbar)
  const folderTreeRef = useRef<HTMLDivElement | null>(null);  // Ordnerauswahl

  const folderSelected = !(folderId === '' || folderId === null || folderId === undefined);

  const handleTabChange = (_event: React.SyntheticEvent, newValue: number) => {
    setActiveTab(newValue);
  };

  const goNextTab = () => setActiveTab((v) => Math.min(3, v + 1));
  const goPrevTab = () => setActiveTab((v) => Math.max(0, v - 1));

  // Reset bei Öffnen
  useEffect(() => {
    if (!open) return;
    setName('');
    setType(firstType);
    setFolderId('');
    setFolderPathLabel('');
    setBusy(false);
    setError('');
    setSources([]);
    setFolderTreeHint('');
    setSourcesTreeHint('');
    setActiveTab(0);
    _areasCache = null; // Cache pro Öffnen resetten
  }, [open, firstType]);

  /** ------------ Datenquellen-Tree (immer sichtbar) ------------ */
  const jsTreeTypes = useMemo(() => {
    const typesMap: Record<string, any> = { folder: { icon: true }, area: { icon: true } };
    for (const key of Object.keys(ICONS)) typesMap[key] = { icon: `/icon8/${ICONS[key]}` };
    return typesMap;
  }, []);

  const loadSourcesTreeData = useCallback((node: any, cb: (data: JsTreeServerNode[]) => void) => {
    if (node.id === '#') {
      fetchTreeRepAreas().then((areas) => {
        const finalAreas = areas.length ? areas : fallbackAreas;
        if (!finalAreas.length) {
          setSourcesTreeHint('Keine Bereiche gefunden. Prüfe /TreeREP-Response.');
        } else if (!areas.length) {
          setSourcesTreeHint('Keine Bereiche aus /TreeREP – zeige lokale Fallback-Daten.');
        }
        const items = finalAreas.map(a => ({ ...a, type: 'folder' as const, icon: AREA_ICON_PATH }));
        cb(items);
      });
      return;
    }

    const url = `/TreeSTTNode/${encodeURIComponent(node.id)}`;
    axios.get(url, { responseType: 'text' })
      .then((resp) => {
        const raw = safeParseJson(resp.data);
        const arr = Array.isArray(raw) ? raw : (raw?.rows ?? raw?.data ?? []);
        const items = (arr ?? []).map((n: any) => {
          const isFolder = n.children === true || Array.isArray(n.children);
          if (isFolder) return { ...n, type: n.type ?? 'folder', icon: true };
          const t = typeFromNodeId(n.id);
          const iconFile = iconForType(t);
          return { ...n, type: n.type ?? t, icon: `/icon8/${iconFile}` };
        });
        cb(items);
      })
      .catch((error) => {
        console.error('TreeSTTNode fetch failed', url, error);
        cb([]);
      });
  }, [fallbackAreas]);

  const jsTreeConfigSources = useMemo(() => ({
    core: {
      animation: 0,
      check_callback: true,
      themes: { dots: true, icons: true },
      data: loadSourcesTreeData,
      worker: false,
    },
    types: jsTreeTypes,
    plugins: ['dnd', 'state', 'types', 'wholerow'],
  }), [jsTreeTypes, loadSourcesTreeData]);

  useEffect(() => {
    if (!open || activeTab !== 1) return;

    let rafId: number | null = null;
    let $tree: JQuery<HTMLElement> | null = null;

    const handleDblClick = (e: JQuery.DoubleClickEvent) => {
      const li = $(e.currentTarget as HTMLElement).closest('li')[0] as HTMLLIElement | undefined;
      if (!li || !$tree) return;
      const inst = $tree.jstree(true);
      const node = inst?.get_node(li.id);
      if (!node) return;

      const idShort = shortIdFromNodeId(node.id);
      const t = typeFromNodeId(node.id);
      const icon = iconForType(t);

      setSources(prev =>
        prev.some(r => r.idShort === idShort) ? prev : [...prev, { idShort, type: t, text: String(node.text ?? ''), icon }]
      );
    };

    const initTree = () => {
      if (!treeRef.current) {
        rafId = window.requestAnimationFrame(initTree);
        return;
      }

      $tree = $(treeRef.current);

      try {
        $tree
          .jstree(jsTreeConfigSources)
          .on('dblclick.jstree', '.jstree-anchor', handleDblClick);
      } catch (err) {
        console.error('Error while initializing sources jsTree', err, jsTreeConfigSources);
      }
    };

    initTree();

    return () => {
      if (rafId != null) window.cancelAnimationFrame(rafId);
      if ($tree) {
        try {
          $tree.off('dblclick.jstree', '.jstree-anchor', handleDblClick);
          $tree.jstree(true).destroy();
        } catch { /* ignore */ }
      }
    };
  }, [open, activeTab, jsTreeConfigSources]);

  const removeRow = (idShort: string) => setSources(prev => prev.filter(r => r.idShort !== idShort));

  /** ------------ Ordner-Picker-Tree: Root = ALLE BEREICHE (nicht selektierbar), darunter Ordner ------------ */
  const loadFolderTreeData = useCallback((node: any, cb: (data: JsTreeServerNode[]) => void) => {
    if (node.id === '#') {
      fetchTreeRepAreas().then((areas) => {
        const finalAreas = areas.length ? areas : fallbackAreas;
        if (!finalAreas.length) {
          setFolderTreeHint('Keine Bereiche gefunden. Prüfe /TreeREP-Response.');
        } else if (!areas.length) {
          setFolderTreeHint('Keine Bereiche aus /TreeREP – zeige lokale Fallback-Daten.');
        }
        // Im Ordner-Picker bleiben Bereiche type='area' (nicht selektierbar)
        cb(finalAreas.map(a => ({ ...a, type: 'area' as const, icon: AREA_ICON_PATH })));
      });
      return;
    }

    const url = `/TreeSTTNode/${encodeURIComponent(node.id)}`;
    axios.get(url, { responseType: 'text' })
      .then((resp) => {
        const raw = safeParseJson(resp.data);
        const arr = Array.isArray(raw) ? raw : (raw?.rows ?? raw?.data ?? []);
        const mapped = (arr ?? [])
          .filter((n: any) => n.children === true || Array.isArray(n.children))
          .map((n: any) => ({ ...n, type: 'folder', icon: FOLDER_ICON_PATH }));
        cb(mapped);
      })
      .catch((error) => {
        console.error('Folder tree fetch failed', url, error);
        cb([]);
      });
  }, [fallbackAreas]);

  useEffect(() => {
    if (!open || activeTab !== 2) return;

    let rafId: number | null = null;
    let $tree: JQuery<HTMLElement> | null = null;

    const config = {
      core: {
        animation: 0,
        check_callback: true,
        themes: { dots: true, icons: true },
        data: loadFolderTreeData,
        worker: false,
      },
      types: { area: { icon: AREA_ICON_PATH }, folder: { icon: FOLDER_ICON_PATH } },
      plugins: ['types', 'wholerow'],
    };

    const handleSelect = (_e: any, data: any) => {
      const node = data?.node;
      if (!node || !$tree) return;

      const isFolder =
        node.type === 'folder' ||
        node.children === true ||
        (Array.isArray(node.children) && node.children.length > 0);

      if (!isFolder || node.type === 'area') return;

      setFolderId(node.id);
      const inst = $tree.jstree(true);
      const path = inst?.get_path(node, ' / ') ?? node.text;
      setFolderPathLabel(path);
    };

    const initTree = () => {
      if (!folderTreeRef.current) {
        rafId = window.requestAnimationFrame(initTree);
        return;
      }

      $tree = $(folderTreeRef.current);

      try {
        $tree.jstree(config).on('select_node.jstree', handleSelect);
      } catch (err) {
        console.error('Error while initializing folder jsTree', err, config);
      }
    };

    initTree();

    return () => {
      if (rafId != null) window.cancelAnimationFrame(rafId);
      if ($tree) {
        try { $tree.off('select_node.jstree', handleSelect).jstree(true).destroy(); } catch { /* ignore */ }
      }
    };
  }, [open, activeTab, loadFolderTreeData]);

  // ---------- Submit ----------
  const handleSubmit = async (e?: React.FormEvent) => {
    e?.preventDefault();
    if (busy) return;

    if (!name.trim()) { setError('Bitte einen Namen eingeben.'); setActiveTab(0); return; }
    if (!type) { setError('Bitte einen Typ auswählen.'); setActiveTab(0); return; }
    if (!folderSelected) {
      setError('Bitte einen Speicherordner wählen.'); setActiveTab(2); return;
    }

    setError('');
    setBusy(true);
    try {
      await onCreate({
        name: name.trim(),
        type,
        folderId,
        sources: sources.map(({ idShort, type, text }) => ({ idShort, type, text })),
      });
      setBusy(false);
      onClose();
    } catch (err) {
      console.error(err);
      setBusy(false);
      setError('Konnte nicht speichern. Bitte erneut versuchen.');
    }
  };

  return (
    <Dialog open={open} onClose={() => !busy && onClose()} fullWidth maxWidth="md">
      <form onSubmit={handleSubmit}>
        <DialogTitle><Trans>Neue Liste erstellen</Trans></DialogTitle>

        <DialogContent dividers>
          <Tabs
            value={activeTab}
            onChange={handleTabChange}
            variant="fullWidth"
            textColor="primary"
            indicatorColor="primary"
          >
            <Tab label={<Trans>Details</Trans>} id="create-list-tab-0" aria-controls="create-list-tabpanel-0" />
            <Tab label={<Trans>Datenquellen</Trans>} id="create-list-tab-1" aria-controls="create-list-tabpanel-1" />
            <Tab label={<Trans>Zielort</Trans>} id="create-list-tab-2" aria-controls="create-list-tabpanel-2" />
            <Tab label={<Trans>Zusammenfassung</Trans>} id="create-list-tab-3" aria-controls="create-list-tabpanel-3" />
          </Tabs>

          <TabPanel value={activeTab} index={0}>
            <Box display="grid" gridTemplateColumns="repeat(auto-fit, minmax(220px, 1fr))" gap={2}>
              <TextField
                label={<Trans>Name der Liste</Trans>}
                value={name}
                onChange={(e) => setName(e.target.value)}
                fullWidth
                disabled={busy}
              />

              <FormControl fullWidth disabled={busy}>
                <InputLabel id="type-label"><Trans>Typ</Trans></InputLabel>
                <Select
                  labelId="type-label"
                  label="Typ"
                  value={type}
                  onChange={(e) => setType(String(e.target.value))}
                  displayEmpty={false}
                >
                  {availableTypes.length === 0 && (
                    <MenuItem value="">
                      <em><Trans>Keine Typen verfügbar</Trans></em>
                    </MenuItem>
                  )}
                  {availableTypes.map(t => (
                    <MenuItem key={t} value={t}>{t}</MenuItem>
                  ))}
                </Select>
                {availableTypes.length === 0 && (
                  <FormHelperText><Trans>Es sind keine Typen konfiguriert.</Trans></FormHelperText>
                )}
              </FormControl>
            </Box>

            {!!error && activeTab === 0 && (
              <Box mt={2}>
                <Typography variant="body2" color="error">{error}</Typography>
              </Box>
            )}
          </TabPanel>

          <TabPanel value={activeTab} index={1}>
            <Box>
              <Typography variant="subtitle1">
                <Trans>Datenquellen auswählen</Trans>
              </Typography>
              <Typography variant="body2" color="textSecondary">
                <Trans>Doppelklick im linken Baum fügt rechts hinzu.</Trans>
              </Typography>

              <Box mt={1} display="grid" gridTemplateColumns="1fr 1fr" gap={2}>
                <div
                  ref={treeRef}
                  id="agbTree"
                  style={{ border: '1px solid rgba(0,0,0,0.12)', borderRadius: 8, minHeight: 320, padding: 8, overflow: 'auto' }}
                />

                <div
                  id="values"
                  style={{ border: '1px solid rgba(0,0,0,0.12)', borderRadius: 8, minHeight: 320, padding: 8, overflow: 'auto' }}
                >
                  <Table size="small">
                    <TableHead>
                      <TableRow>
                        <TableCell><Trans>Typ</Trans></TableCell>
                        <TableCell><Trans>Name</Trans></TableCell>
                        <TableCell align="right"><Trans>Aktion</Trans></TableCell>
                      </TableRow>
                    </TableHead>
                    <TableBody>
                      {sources.map((s) => (
                        <TableRow key={s.idShort} hover>
                          <TableCell style={{ whiteSpace: 'nowrap' }}>
                            <img src={`/icon8/${s.icon}`} alt={s.type} style={{ verticalAlign: 'middle' }} />
                          </TableCell>
                          <TableCell><span className="name">{s.text}</span></TableCell>
                          <TableCell align="right">
                            <IconButton aria-label="Zeile löschen" size="small" onClick={() => removeRow(s.idShort)}>
                              <DeleteIcon fontSize="small" />
                            </IconButton>
                          </TableCell>
                        </TableRow>
                      ))}
                      {sources.length === 0 && (
                        <TableRow>
                          <TableCell colSpan={3}>
                            <Typography variant="caption" color="textSecondary">
                              <Trans>Noch keine Datenquelle ausgewählt.</Trans>
                            </Typography>
                          </TableCell>
                        </TableRow>
                      )}
                    </TableBody>
                  </Table>
                </div>
              </Box>
              {sourcesTreeHint && (
                <Box mt={1}><Alert severity="warning" variant="outlined">{sourcesTreeHint}</Alert></Box>
              )}
            </Box>
          </TabPanel>

          <TabPanel value={activeTab} index={2}>
            <Box>
              <Typography variant="subtitle1">
                <Trans>Zielordner wählen</Trans>
              </Typography>
              <Typography variant="body2" color="textSecondary">
                <Trans>Wähle einen Ordner, in dem die definierte Liste gespeichert werden soll.</Trans>
              </Typography>
              <Box mt={1} sx={{ border: '1px solid rgba(0,0,0,0.12)', borderRadius: 8, minHeight: 280, p: 1, overflow: 'auto' }}>
                <div ref={folderTreeRef} id="folderPickerTree" />
              </Box>
              {folderTreeHint && (
                <Box mt={1}><Alert severity="warning" variant="outlined">{folderTreeHint}</Alert></Box>
              )}
              <Box mt={1}>
                <Typography variant="caption" color={folderSelected ? 'textPrimary' : 'textSecondary'}>
                  {folderSelected ? <Trans>Gewählter Ordner:</Trans> : <Trans>Noch kein Ordner gewählt.</Trans>} {folderPathLabel || ''}
                </Typography>
              </Box>
            </Box>
          </TabPanel>

          <TabPanel value={activeTab} index={3}>
            <Box mt={1} p={2} sx={{ border: '1px solid rgba(0,0,0,0.08)', borderRadius: 8, backgroundColor: '#fafafa' }}>
              <Typography variant="subtitle2" gutterBottom>
                <Trans>Zusammenfassung</Trans>
              </Typography>
              <Box display="grid" gridTemplateColumns="repeat(auto-fit, minmax(220px, 1fr))" gap={1.5}>
                <SummaryItem label={<Trans>Name</Trans>} value={name || '–'} />
                <SummaryItem label={<Trans>Typ</Trans>} value={type || '–'} />
                <SummaryItem label={<Trans>Ausgewählte Quellen</Trans>} value={sources.length ? sources.map(s => s.text).join(', ') : '–'} />
                <SummaryItem label={<Trans>Ordner</Trans>} value={folderSelected ? folderPathLabel || '—' : '–'} />
              </Box>
            </Box>

            {!!error && (
              <Box mt={2}>
                <Typography variant="body2" color="error">{error}</Typography>
              </Box>
            )}
          </TabPanel>
        </DialogContent>

        <DialogActions sx={{ justifyContent: 'space-between' }}>
          <Button onClick={() => !busy && onClose()} disabled={busy}><Trans>Abbrechen</Trans></Button>
          <Box display="flex" gap={1}>
            <Button onClick={goPrevTab} disabled={busy || activeTab === 0}>
              <Trans>Zurück</Trans>
            </Button>
            {activeTab < 3 ? (
              <Button
                variant="contained"
                onClick={goNextTab}
                disabled={
                  busy ||
                  (activeTab === 0 && (!name.trim() || !type)) ||
                  (activeTab === 2 && !folderSelected)
                }
              >
                <Trans>Weiter</Trans>
              </Button>
            ) : (
              <Button
                type="submit"
                color="primary"
                variant="contained"
                disabled={busy || !name.trim() || !type || !folderSelected}
              >
                {busy ? <Trans>Speichern…</Trans> : <Trans>Speichern</Trans>}
              </Button>
            )}
          </Box>
        </DialogActions>
      </form>
    </Dialog>
  );
};

export default CreateListDialog;
