import { useState, useMemo } from 'react';
import {
  Box, Typography, Container, Button, Chip,
  TextField, Autocomplete, ToggleButton, ToggleButtonGroup,
  Stack, Divider, LinearProgress, MenuItem,
} from '@mui/material';
import { Assignment as AssignmentIcon } from '@mui/icons-material';
import { useQuery, useQueryClient } from '@tanstack/react-query';
import { useParams, useNavigate } from 'react-router-dom';
import DashboardLayout from '../components/dashboard/DashboardLayout';
import { PageHeader } from '../components/templates';
import { useNotification } from '../contexts/NotificationContext';
import { usePermissionContext } from '../contexts/PermissionContext';
import { ausruestungsanfrageApi } from '../services/ausruestungsanfrage';
import { personalEquipmentApi } from '../services/personalEquipment';
import { vehiclesApi } from '../services/vehicles';
import { membersService } from '../services/members';
import type { AusruestungAnfragePosition, AusruestungEigenschaft } from '../types/ausruestungsanfrage.types';

type AssignmentTyp = 'ausruestung' | 'persoenlich' | 'keine';

interface PositionAssignment {
  typ: AssignmentTyp;
  fahrzeugId?: string;
  standort?: string;
  userId?: string;
  benutzerName?: string;
  eigenschaften?: Record<number, string>; // eigenschaft_id → wert
}

function getUnassignedPositions(positions: AusruestungAnfragePosition[]): AusruestungAnfragePosition[] {
  return positions.filter((p) => p.geliefert && (!p.zuweisung_typ || p.zuweisung_typ === 'keine'));
}

export default function AusruestungsanfrageZuweisung() {
  const { id } = useParams<{ id: string }>();
  const navigate = useNavigate();
  const { showSuccess, showError } = useNotification();
  const anfrageId = Number(id);
  const queryClient = useQueryClient();
  const { hasPermission } = usePermissionContext();
  const canManageCatalog = hasPermission('ausruestungsanfrage:manage_catalog');

  const [createArtikelFor, setCreateArtikelFor] = useState<number | null>(null);
  const [newArtikelBezeichnung, setNewArtikelBezeichnung] = useState('');
  const [newArtikelSubmitting, setNewArtikelSubmitting] = useState(false);

  const { data: detail, isLoading, isError } = useQuery({
    queryKey: ['ausruestungsanfrage', 'request', anfrageId],
    queryFn: () => ausruestungsanfrageApi.getRequest(anfrageId),
    enabled: !isNaN(anfrageId),
    retry: 1,
  });

  const unassigned = useMemo(() => {
    if (!detail) return [];
    return getUnassignedPositions(detail.positionen);
  }, [detail]);

  const [assignments, setAssignments] = useState<Record<number, PositionAssignment>>({});

  // Collect unique artikel_ids from unassigned positions to batch-load their eigenschaften
  const uniqueArtikelIds = useMemo(
    () => [...new Set(unassigned.filter(p => p.artikel_id).map(p => p.artikel_id!))],
    [unassigned],
  );

  const { data: artikelEigenschaftenMap = {} } = useQuery<Record<number, AusruestungEigenschaft[]>>({
    queryKey: ['ausruestungsanfrage', 'eigenschaften-batch', uniqueArtikelIds],
    queryFn: async () => {
      const results: Record<number, AusruestungEigenschaft[]> = {};
      await Promise.all(
        uniqueArtikelIds.map(async (aid) => {
          results[aid] = await ausruestungsanfrageApi.getArtikelEigenschaften(aid);
        }),
      );
      return results;
    },
    enabled: uniqueArtikelIds.length > 0,
    staleTime: 5 * 60 * 1000,
  });

  // Initialize assignments when unassigned positions load
  useMemo(() => {
    if (unassigned.length > 0 && Object.keys(assignments).length === 0) {
      const init: Record<number, PositionAssignment> = {};
      for (const p of unassigned) {
        // Pre-fill eigenschaften from position values
        const prefilled: Record<number, string> = {};
        for (const e of p.eigenschaften ?? []) {
          prefilled[e.eigenschaft_id] = e.wert;
        }
        init[p.id] = { typ: 'persoenlich', eigenschaften: prefilled };
      }
      setAssignments(init);
    }
  }, [unassigned]);

  const { data: vehicleList } = useQuery({
    queryKey: ['vehicles', 'sidebar'],
    queryFn: () => vehiclesApi.getAll(),
    staleTime: 2 * 60 * 1000,
  });

  const { data: membersList } = useQuery({
    queryKey: ['members-list-compact'],
    queryFn: () => membersService.getMembers({ pageSize: 500 }),
    staleTime: 5 * 60 * 1000,
  });

  const memberOptions = (membersList?.items ?? []).map((m) => ({
    id: m.id,
    name: [m.given_name, m.family_name].filter(Boolean).join(' ') || m.email,
  }));

  const vehicleOptions = (vehicleList ?? []).map((v) => ({
    id: v.id,
    name: v.bezeichnung ?? v.kurzname,
  }));

  const { data: allPersonalItems = [] } = useQuery({
    queryKey: ['persoenliche-ausruestung', 'all-for-count'],
    queryFn: () => personalEquipmentApi.getAll(),
    staleTime: 2 * 60 * 1000,
  });

  const [submitting, setSubmitting] = useState(false);

  const updateAssignment = (posId: number, patch: Partial<PositionAssignment>) => {
    setAssignments((prev) => ({
      ...prev,
      [posId]: { ...prev[posId], ...patch },
    }));
  };

  const handleSkipAll = () => {
    const updated: Record<number, PositionAssignment> = {};
    for (const p of unassigned) {
      updated[p.id] = { typ: 'keine' };
    }
    setAssignments(updated);
  };

  const handleCreateArtikel = async (posId: number) => {
    if (!newArtikelBezeichnung.trim()) return;
    setNewArtikelSubmitting(true);
    try {
      const newArtikel = await ausruestungsanfrageApi.createItem({ bezeichnung: newArtikelBezeichnung.trim(), aktiv: true });
      await ausruestungsanfrageApi.linkPositionToArtikel(posId, newArtikel.id);
      queryClient.invalidateQueries({ queryKey: ['ausruestungsanfrage', 'request', anfrageId] });
      setCreateArtikelFor(null);
      showSuccess('Katalogartikel erstellt und Position verknüpft');
    } catch {
      showError('Fehler beim Erstellen des Katalogartikels');
    } finally {
      setNewArtikelSubmitting(false);
    }
  };

  const handleSubmit = async () => {
    if (!detail) return;
    setSubmitting(true);
    try {
      const anfrage = detail.anfrage;
      const posMap = Object.fromEntries(unassigned.map(p => [p.id, p]));
      const payload = Object.entries(assignments).map(([posId, a]) => {
        const pos = posMap[Number(posId)];
        const artikelEigs: AusruestungEigenschaft[] = pos?.artikel_id
          ? (artikelEigenschaftenMap[pos.artikel_id] ?? [])
          : [];
        return {
          positionId: Number(posId),
          typ: a.typ,
          fahrzeugId: a.typ === 'ausruestung' ? a.fahrzeugId : undefined,
          standort: a.typ === 'ausruestung' ? a.standort : undefined,
          userId: a.typ === 'persoenlich' ? a.userId : undefined,
          benutzerName: a.typ === 'persoenlich' ? (a.benutzerName || anfrage.fuer_benutzer_name || anfrage.anfrager_name) : undefined,
          eigenschaften: a.typ === 'persoenlich' && a.eigenschaften
            ? Object.entries(a.eigenschaften)
                .filter(([, v]) => v.trim())
                .map(([eid, wert]) => ({
                  eigenschaft_id: Number(eid),
                  name: artikelEigs.find(e => e.id === Number(eid))?.name ?? '',
                  wert,
                }))
            : undefined,
        };
      });
      await ausruestungsanfrageApi.assignItems(anfrageId, payload);
      showSuccess('Gegenstände zugewiesen');
      navigate(`/ausruestungsanfrage/${id}`);
      queryClient.invalidateQueries({ queryKey: ['persoenliche-ausruestung'] });
      queryClient.invalidateQueries({ queryKey: ['ausruestungsanfrage'] });
    } catch {
      showError('Fehler beim Zuweisen');
    } finally {
      setSubmitting(false);
    }
  };

  const backPath = `/ausruestungsanfrage/${id}`;

  return (
    <DashboardLayout>
      <Container maxWidth="md">
        <PageHeader
          title="Gegenstände zuweisen"
          subtitle={detail?.anfrage.bezeichnung || undefined}
          backTo={backPath}
        />

        {isLoading ? (
          <LinearProgress />
        ) : isError || !detail ? (
          <Typography color="error">Fehler beim Laden der Anfrage.</Typography>
        ) : unassigned.length === 0 ? (
          <Typography color="text.secondary">Keine unzugewiesenen Positionen vorhanden.</Typography>
        ) : (
          <>
            <Typography variant="body2" color="text.secondary" sx={{ mb: 3 }}>
              Wähle für jeden gelieferten Gegenstand, wie er erfasst werden soll.
            </Typography>

            <Stack spacing={3} divider={<Divider />}>
              {unassigned.map((pos) => {
                const a = assignments[pos.id] ?? { typ: 'persoenlich' as const };
                return (
                  <Box key={pos.id}>
                    <Box sx={{ display: 'flex', alignItems: 'center', gap: 1, mb: 1.5 }}>
                      <Typography variant="body2" fontWeight={600}>
                        {pos.bezeichnung}
                      </Typography>
                      <Chip label={`${pos.menge}x`} size="small" variant="outlined" />
                    </Box>

                    {!pos.artikel_id && (
                      <Box sx={{ mb: 1 }}>
                        <Chip label="Nicht im Katalog" color="warning" size="small" sx={{ mb: 1 }} />
                        {canManageCatalog && createArtikelFor !== pos.id && (
                          <Button
                            size="small"
                            variant="outlined"
                            color="warning"
                            sx={{ ml: 1 }}
                            onClick={() => { setCreateArtikelFor(pos.id); setNewArtikelBezeichnung(pos.bezeichnung); }}
                          >
                            Als Katalogartikel anlegen
                          </Button>
                        )}
                        {createArtikelFor === pos.id && (
                          <Box sx={{ display: 'flex', gap: 1, alignItems: 'center', mt: 1 }}>
                            <TextField
                              size="small"
                              label="Bezeichnung"
                              value={newArtikelBezeichnung}
                              onChange={(e) => setNewArtikelBezeichnung(e.target.value)}
                              sx={{ flex: 1 }}
                            />
                            <Button
                              size="small"
                              variant="contained"
                              disabled={newArtikelSubmitting || !newArtikelBezeichnung.trim()}
                              onClick={() => handleCreateArtikel(pos.id)}
                            >
                              Erstellen
                            </Button>
                            <Button
                              size="small"
                              onClick={() => setCreateArtikelFor(null)}
                            >
                              Abbrechen
                            </Button>
                          </Box>
                        )}
                      </Box>
                    )}

                    <ToggleButtonGroup
                      value={a.typ}
                      exclusive
                      size="small"
                      onChange={(_e, val) => val && updateAssignment(pos.id, { typ: val })}
                      sx={{ mb: 1.5 }}
                    >
                      <ToggleButton value="ausruestung" disabled={!pos.artikel_id}>Ausrüstung</ToggleButton>
                      <ToggleButton value="persoenlich" disabled={!pos.artikel_id}>Persönlich</ToggleButton>
                      <ToggleButton value="keine">Nicht zuweisen</ToggleButton>
                    </ToggleButtonGroup>

                    {a.typ === 'ausruestung' && (
                      <Box sx={{ display: 'flex', gap: 1.5, flexWrap: 'wrap' }}>
                        <Autocomplete
                          size="small"
                          options={vehicleOptions}
                          getOptionLabel={(o) => o.name}
                          value={vehicleOptions.find((v) => v.id === a.fahrzeugId) ?? null}
                          onChange={(_e, v) => updateAssignment(pos.id, { fahrzeugId: v?.id })}
                          renderInput={(params) => <TextField {...params} label="Fahrzeug" />}
                          sx={{ minWidth: 200, flex: 1 }}
                        />
                        <TextField
                          size="small"
                          label="Standort"
                          value={a.standort ?? ''}
                          onChange={(e) => updateAssignment(pos.id, { standort: e.target.value })}
                          sx={{ minWidth: 160, flex: 1 }}
                        />
                      </Box>
                    )}

                    {a.typ === 'persoenlich' && (
                      <Box sx={{ display: 'flex', flexDirection: 'column', gap: 1.5 }}>
                        <Box sx={{ display: 'flex', gap: 1.5, flexWrap: 'wrap', alignItems: 'center' }}>
                          <Autocomplete
                            size="small"
                            options={memberOptions}
                            getOptionLabel={(o) => o.name}
                            value={memberOptions.find((m) => m.id === a.userId) ?? null}
                            onChange={(_e, v) => updateAssignment(pos.id, { userId: v?.id, benutzerName: v?.name })}
                            renderInput={(params) => (
                              <TextField
                                {...params}
                                label="Benutzer"
                                placeholder={detail.anfrage.fuer_benutzer_name || detail.anfrage.anfrager_name || ''}
                              />
                            )}
                            sx={{ minWidth: 200, flex: 1 }}
                          />
                          {(() => {
                            if (!a.userId || !pos.artikel_id) return null;
                            const count = allPersonalItems.filter(i => i.user_id === a.userId && i.artikel_id === pos.artikel_id).length;
                            if (count === 0) return null;
                            return <Typography variant="caption" color="text.secondary">Hat bereits {count} Stk.</Typography>;
                          })()}
                        </Box>
                        {/* Editable characteristic fields from article definitions */}
                        {pos.artikel_id && (artikelEigenschaftenMap[pos.artikel_id] ?? []).map(e =>
                          e.typ === 'options' && e.optionen?.length ? (
                            <TextField
                              key={e.id}
                              select
                              size="small"
                              label={e.name}
                              required={e.pflicht}
                              value={a.eigenschaften?.[e.id] ?? ''}
                              onChange={ev => updateAssignment(pos.id, {
                                eigenschaften: { ...a.eigenschaften, [e.id]: ev.target.value },
                              })}
                            >
                              <MenuItem value="">—</MenuItem>
                              {e.optionen.map(opt => <MenuItem key={opt} value={opt}>{opt}</MenuItem>)}
                            </TextField>
                          ) : (
                            <TextField
                              key={e.id}
                              size="small"
                              label={e.name}
                              required={e.pflicht}
                              value={a.eigenschaften?.[e.id] ?? ''}
                              onChange={ev => updateAssignment(pos.id, {
                                eigenschaften: { ...a.eigenschaften, [e.id]: ev.target.value },
                              })}
                            />
                          )
                        )}
                      </Box>
                    )}
                  </Box>
                );
              })}
            </Stack>

            <Box sx={{ display: 'flex', gap: 1, justifyContent: 'flex-end', mt: 4 }}>
              <Button onClick={handleSkipAll} color="inherit">
                Alle überspringen
              </Button>
              <Button onClick={() => navigate(backPath)}>Abbrechen</Button>
              <Button
                variant="contained"
                onClick={handleSubmit}
                disabled={submitting}
                startIcon={<AssignmentIcon />}
              >
                Zuweisen
              </Button>
            </Box>
          </>
        )}
      </Container>
    </DashboardLayout>
  );
}
