import { useState, useMemo } from 'react';
import {
  Box, Typography, Paper, Chip, IconButton, Button,
  TextField, MenuItem, Select, FormControl,
  InputLabel, Divider, CircularProgress, Autocomplete, Grid, Card, CardContent,
  List, ListItem, ListItemIcon, ListItemText, ListItemSecondaryAction,
} from '@mui/material';
import {
  ArrowBack, Delete as DeleteIcon,
  BugReport, FiberNew, HelpOutline, Send as SendIcon,
  Circle as CircleIcon, Refresh as RefreshIcon, History,
  AttachFile as AttachFileIcon, InsertDriveFile as FileIcon,
  Upload as UploadIcon,
} from '@mui/icons-material';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { useParams, useNavigate } from 'react-router-dom';
import DashboardLayout from '../components/dashboard/DashboardLayout';
import { useNotification } from '../contexts/NotificationContext';
import { usePermissionContext } from '../contexts/PermissionContext';
import { useAuth } from '../contexts/AuthContext';
import { issuesApi } from '../services/issues';
import type { Issue, IssueComment, UpdateIssuePayload, AssignableMember, IssueStatusDef, IssuePriorityDef, IssueHistorie, IssueDatei } from '../types/issue.types';
import { ConfirmDialog, FormDialog, PageHeader } from '../components/templates';

// ── Helpers (copied from Issues.tsx) ──

const formatDate = (iso?: string) =>
  iso ? new Date(iso).toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit' }) : '-';

const formatDateOnly = (iso?: string | null) =>
  iso ? new Date(iso).toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric' }) : '-';

const toInputDate = (iso?: string | null) => {
  if (!iso) return '';
  const d = new Date(iso);
  return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
};

const formatFileSize = (bytes: number | null) => {
  if (!bytes) return '';
  if (bytes < 1024) return `${bytes} B`;
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
  return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
};

const formatIssueId = (issue: Issue) =>
  `${new Date(issue.created_at).getFullYear()}/${issue.id}`;

const STATUS_COLORS: Record<string, string> = {
  offen: 'info', in_bearbeitung: 'warning', erledigt: 'success', abgelehnt: 'error',
};
const STATUS_LABELS: Record<string, string> = {
  offen: 'Offen', in_bearbeitung: 'In Bearbeitung', erledigt: 'Erledigt', abgelehnt: 'Abgelehnt',
};
const PRIO_COLORS: Record<string, string> = {
  hoch: '#d32f2f', mittel: '#ed6c02', niedrig: '#9e9e9e',
};
const PRIO_LABELS: Record<string, string> = {
  hoch: 'Hoch', mittel: 'Mittel', niedrig: 'Niedrig',
};

function getStatusLabel(statuses: IssueStatusDef[], key: string) {
  return statuses.find(s => s.schluessel === key)?.bezeichnung ?? STATUS_LABELS[key] ?? key;
}
function getStatusColor(statuses: IssueStatusDef[], key: string): any {
  return statuses.find(s => s.schluessel === key)?.farbe ?? STATUS_COLORS[key] ?? 'default';
}
function getPrioColor(priorities: IssuePriorityDef[], key: string) {
  return priorities.find(p => p.schluessel === key)?.farbe ?? PRIO_COLORS[key] ?? '#9e9e9e';
}
function getPrioLabel(priorities: IssuePriorityDef[], key: string) {
  return priorities.find(p => p.schluessel === key)?.bezeichnung ?? PRIO_LABELS[key] ?? key;
}

const ICON_MAP: Record<string, JSX.Element> = {
  BugReport: <BugReport fontSize="small" />,
  FiberNew: <FiberNew fontSize="small" />,
  HelpOutline: <HelpOutline fontSize="small" />,
};

function getTypIcon(iconName: string | null, farbe: string | null): JSX.Element {
  const icon = ICON_MAP[iconName || ''] || <HelpOutline fontSize="small" />;
  const colorProp = farbe === 'error' ? 'error' : farbe === 'info' ? 'info' : farbe === 'action' ? 'action' : 'action';
  return <Box component="span" sx={{ display: 'inline-flex', color: `${colorProp}.main` }}>{icon}</Box>;
}

// ══════════════════════════════════════════════════════════════════════════════
// Component
// ══════════════════════════════════════════════════════════════════════════════

export default function IssueDetail() {
  const { id } = useParams<{ id: string }>();
  const navigate = useNavigate();
  const queryClient = useQueryClient();
  const { showSuccess, showError } = useNotification();
  const { hasPermission } = usePermissionContext();
  const { user } = useAuth();

  const issueId = Number(id);
  const userId = user?.id || '';
  const hasEdit = hasPermission('issues:edit');
  const hasChangeStatus = hasPermission('issues:change_status');
  const hasDeletePerm = hasPermission('issues:delete');

  // ── State ──
  const [reopenOpen, setReopenOpen] = useState(false);
  const [reopenComment, setReopenComment] = useState('');
  const [deleteOpen, setDeleteOpen] = useState(false);
  const [commentText, setCommentText] = useState('');

  // ── Queries ──
  const { data: issue, isLoading, isError } = useQuery({
    queryKey: ['issues', issueId],
    queryFn: () => issuesApi.getIssue(issueId),
    enabled: !isNaN(issueId),
  });

  const { data: comments = [], isLoading: commentsLoading } = useQuery({
    queryKey: ['issues', issueId, 'comments'],
    queryFn: () => issuesApi.getComments(issueId),
    enabled: !isNaN(issueId),
  });

  const { data: statuses = [] } = useQuery({
    queryKey: ['issue-statuses'],
    queryFn: issuesApi.getStatuses,
  });

  const { data: priorities = [] } = useQuery({
    queryKey: ['issue-priorities'],
    queryFn: issuesApi.getPriorities,
  });

  const { data: members = [] } = useQuery({
    queryKey: ['issue-members'],
    queryFn: issuesApi.getMembers,
    enabled: hasEdit,
  });

  const { data: historie = [] } = useQuery<IssueHistorie[]>({
    queryKey: ['issues', issueId, 'history'],
    queryFn: () => issuesApi.getHistory(issueId),
    enabled: !isNaN(issueId),
  });

  const { data: files = [] } = useQuery<IssueDatei[]>({
    queryKey: ['issues', issueId, 'files'],
    queryFn: () => issuesApi.getFiles(issueId),
    enabled: !isNaN(issueId),
  });

  // ── Permissions ──
  const isOwner = issue?.erstellt_von === userId;
  const isAssignee = issue?.zugewiesen_an === userId;
  const canDelete = hasDeletePerm || isOwner;
  const canComment = isOwner || isAssignee || hasChangeStatus || hasEdit;
  const canChangeStatus = hasEdit || hasChangeStatus || isAssignee;
  const ownerOnlyErledigt = isOwner && !canChangeStatus;

  const allowedStatuses = useMemo(() => {
    if (!issue) return [];
    const active = statuses.filter(s => s.aktiv);
    if (hasEdit) return active.filter(s => !s.benoetigt_typ_freigabe || issue.typ_erlaubt_abgelehnt);
    if (hasChangeStatus || isAssignee) return active.filter(s => !s.benoetigt_typ_freigabe || issue.typ_erlaubt_abgelehnt);
    if (isOwner) return active.filter(s => s.schluessel === issue.status || s.ist_abschluss);
    return active.filter(s => s.schluessel === issue.status);
  }, [statuses, hasEdit, hasChangeStatus, isAssignee, isOwner, issue]);

  const currentStatusDef = statuses.find(s => s.schluessel === issue?.status);
  const isTerminal = currentStatusDef?.ist_abschluss ?? (issue?.status === 'erledigt');
  const showReopenButton = ownerOnlyErledigt && isTerminal;
  const initialStatusKey = statuses.find(s => s.ist_initial)?.schluessel ?? 'offen';

  // ── Mutations ──
  const updateMut = useMutation({
    mutationFn: (data: UpdateIssuePayload) => issuesApi.updateIssue(issueId, data),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['issues'] });
      queryClient.invalidateQueries({ queryKey: ['issues', issueId, 'history'] });
      showSuccess('Issue aktualisiert');
    },
    onError: () => showError('Fehler beim Aktualisieren'),
  });

  const deleteMut = useMutation({
    mutationFn: () => issuesApi.deleteIssue(issueId),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['issues'] });
      showSuccess('Issue gelöscht');
      navigate('/issues');
    },
    onError: () => showError('Fehler beim Löschen'),
  });

  const addCommentMut = useMutation({
    mutationFn: (inhalt: string) => issuesApi.addComment(issueId, inhalt),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['issues', issueId, 'comments'] });
      setCommentText('');
    },
    onError: () => showError('Kommentar konnte nicht erstellt werden'),
  });

  const uploadFileMut = useMutation({
    mutationFn: (file: File) => issuesApi.uploadFile(issueId, file),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['issues', issueId, 'files'] });
      showSuccess('Datei hochgeladen');
    },
    onError: () => showError('Datei konnte nicht hochgeladen werden'),
  });

  const deleteFileMut = useMutation({
    mutationFn: (fileId: string) => issuesApi.deleteFile(fileId),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['issues', issueId, 'files'] });
      showSuccess('Datei gelöscht');
    },
    onError: () => showError('Datei konnte nicht gelöscht werden'),
  });

  const handleFileUpload = (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (file) uploadFileMut.mutate(file);
    e.target.value = '';
  };

  const handleReopen = () => {
    updateMut.mutate({ status: initialStatusKey, kommentar: reopenComment.trim() }, {
      onSuccess: () => {
        setReopenOpen(false);
        setReopenComment('');
        queryClient.invalidateQueries({ queryKey: ['issues'] });
        showSuccess('Issue wiedereröffnet');
      },
    });
  };

  // ── Loading / Error / 404 ──
  if (isLoading) {
    return (
      <DashboardLayout>
        <Box sx={{ display: 'flex', justifyContent: 'center', py: 8 }}><CircularProgress /></Box>
      </DashboardLayout>
    );
  }

  if (isError || !issue) {
    return (
      <DashboardLayout>
        <Box sx={{ p: 3 }}>
          <Button startIcon={<ArrowBack />} onClick={() => navigate('/issues')} sx={{ mb: 2 }}>
            Zurück
          </Button>
          <Typography color="error">Issue nicht gefunden.</Typography>
        </Box>
      </DashboardLayout>
    );
  }

  return (
    <DashboardLayout>
      <Box sx={{ p: 3 }}>
        <PageHeader
          title={`${formatIssueId(issue)} — ${issue.titel}`}
          backTo="/issues"
          actions={
            <Chip
              label={getStatusLabel(statuses, issue.status)}
              color={getStatusColor(statuses, issue.status)}
            />
          }
        />

        {/* Info cards */}
        <Grid container spacing={2} sx={{ mb: 3 }}>
          <Grid item xs={6} sm={4} md={2}>
            <Card variant="outlined">
              <CardContent sx={{ py: 1.5, '&:last-child': { pb: 1.5 } }}>
                <Typography variant="caption" color="text.secondary">Typ</Typography>
                <Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5, mt: 0.5 }}>
                  {getTypIcon(issue.typ_icon, issue.typ_farbe)}
                  <Typography variant="body2">{issue.typ_name}</Typography>
                </Box>
              </CardContent>
            </Card>
          </Grid>
          <Grid item xs={6} sm={4} md={2}>
            <Card variant="outlined">
              <CardContent sx={{ py: 1.5, '&:last-child': { pb: 1.5 } }}>
                <Typography variant="caption" color="text.secondary">Priorität</Typography>
                <Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5, mt: 0.5 }}>
                  <CircleIcon sx={{ fontSize: 10, color: getPrioColor(priorities, issue.prioritaet) }} />
                  <Typography variant="body2">{getPrioLabel(priorities, issue.prioritaet)}</Typography>
                </Box>
              </CardContent>
            </Card>
          </Grid>
          <Grid item xs={6} sm={4} md={2}>
            <Card variant="outlined">
              <CardContent sx={{ py: 1.5, '&:last-child': { pb: 1.5 } }}>
                <Typography variant="caption" color="text.secondary">Erstellt von</Typography>
                <Typography variant="body2" sx={{ mt: 0.5 }}>{issue.erstellt_von_name || '-'}</Typography>
              </CardContent>
            </Card>
          </Grid>
          <Grid item xs={6} sm={4} md={2}>
            <Card variant="outlined">
              <CardContent sx={{ py: 1.5, '&:last-child': { pb: 1.5 } }}>
                <Typography variant="caption" color="text.secondary">Zugewiesen an</Typography>
                <Typography variant="body2" sx={{ mt: 0.5 }}>{issue.zugewiesen_an_name || '-'}</Typography>
              </CardContent>
            </Card>
          </Grid>
          <Grid item xs={6} sm={4} md={2}>
            <Card variant="outlined">
              <CardContent sx={{ py: 1.5, '&:last-child': { pb: 1.5 } }}>
                <Typography variant="caption" color="text.secondary">Erstellt am</Typography>
                <Typography variant="body2" sx={{ mt: 0.5 }}>{formatDate(issue.created_at)}</Typography>
              </CardContent>
            </Card>
          </Grid>
          <Grid item xs={6} sm={4} md={2}>
            <Card variant="outlined" sx={issue.faellig_am && new Date(issue.faellig_am) < new Date() ? { borderColor: 'error.main' } : undefined}>
              <CardContent sx={{ py: 1.5, '&:last-child': { pb: 1.5 } }}>
                <Typography variant="caption" color="text.secondary">Fällig am</Typography>
                <Typography
                  variant="body2"
                  sx={{ mt: 0.5 }}
                  color={issue.faellig_am && new Date(issue.faellig_am) < new Date() ? 'error' : 'text.primary'}
                >
                  {formatDateOnly(issue.faellig_am)}
                </Typography>
              </CardContent>
            </Card>
          </Grid>
        </Grid>

        {/* Description */}
        {issue.beschreibung && (
          <Paper variant="outlined" sx={{ p: 2, mb: 3 }}>
            <Typography variant="subtitle2" gutterBottom>Beschreibung</Typography>
            <Typography variant="body2" sx={{ whiteSpace: 'pre-wrap' }}>{issue.beschreibung}</Typography>
          </Paper>
        )}

        {/* Attachments */}
        <Paper variant="outlined" sx={{ p: 2, mb: 3 }}>
          <Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', mb: 1 }}>
            <Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
              <AttachFileIcon fontSize="small" />
              <Typography variant="subtitle2">Anhänge ({files.length})</Typography>
            </Box>
            {canComment && (
              <Button
                size="small"
                startIcon={<UploadIcon />}
                component="label"
                disabled={uploadFileMut.isPending}
              >
                {uploadFileMut.isPending ? 'Hochladen...' : 'Datei hochladen'}
                <input type="file" hidden onChange={handleFileUpload} />
              </Button>
            )}
          </Box>
          {files.length === 0 ? (
            <Typography variant="body2" color="text.secondary">Keine Anhänge</Typography>
          ) : (
            <List dense disablePadding>
              {files.map((f) => (
                <ListItem key={f.id} disableGutters>
                  <ListItemIcon sx={{ minWidth: 36 }}>
                    <FileIcon fontSize="small" />
                  </ListItemIcon>
                  <ListItemText
                    primary={f.dateiname}
                    secondary={`${formatFileSize(f.dateigroesse)} — ${formatDate(f.hochgeladen_am)}`}
                  />
                  <ListItemSecondaryAction>
                    {(hasEdit || isOwner) && (
                      <IconButton
                        size="small"
                        edge="end"
                        color="error"
                        onClick={() => deleteFileMut.mutate(f.id)}
                        disabled={deleteFileMut.isPending}
                      >
                        <DeleteIcon fontSize="small" />
                      </IconButton>
                    )}
                  </ListItemSecondaryAction>
                </ListItem>
              ))}
            </List>
          )}
        </Paper>

        {/* Controls row */}
        <Box sx={{ display: 'flex', gap: 1, mb: 2, flexWrap: 'wrap', alignItems: 'center' }}>
          {/* Status control */}
          {showReopenButton ? (
            <Button
              size="small"
              variant="outlined"
              startIcon={<RefreshIcon />}
              onClick={() => setReopenOpen(true)}
            >
              Wiedereröffnen
            </Button>
          ) : canChangeStatus || isOwner ? (
            <FormControl size="small" sx={{ minWidth: 160 }}>
              <InputLabel>Status</InputLabel>
              <Select
                value={issue.status}
                label="Status"
                onChange={(e) => updateMut.mutate({ status: e.target.value })}
              >
                {allowedStatuses.map(s => (
                  <MenuItem key={s.schluessel} value={s.schluessel}>{s.bezeichnung}</MenuItem>
                ))}
              </Select>
            </FormControl>
          ) : null}

          {/* Priority control */}
          {hasEdit && (
            <FormControl size="small" sx={{ minWidth: 140 }}>
              <InputLabel>Priorität</InputLabel>
              <Select
                value={issue.prioritaet}
                label="Priorität"
                onChange={(e) => updateMut.mutate({ prioritaet: e.target.value })}
              >
                {priorities.filter(p => p.aktiv).map(p => (
                  <MenuItem key={p.schluessel} value={p.schluessel}>{p.bezeichnung}</MenuItem>
                ))}
              </Select>
            </FormControl>
          )}

          {/* Assignment */}
          {hasEdit && (
            <Autocomplete
              size="small"
              sx={{ minWidth: 200 }}
              options={members}
              getOptionLabel={(o: AssignableMember) => o.name}
              value={members.find((m: AssignableMember) => m.id === issue.zugewiesen_an) || null}
              onChange={(_e, val) => updateMut.mutate({ zugewiesen_an: val?.id || null })}
              renderInput={(params) => <TextField {...params} label="Zugewiesen an" size="small" />}
              isOptionEqualToValue={(o, v) => o.id === v.id}
            />
          )}

          {/* Due date */}
          {hasEdit && (
            <TextField
              size="small"
              label="Fällig am"
              type="date"
              value={toInputDate(issue.faellig_am)}
              onChange={(e) => updateMut.mutate({ faellig_am: e.target.value || null })}
              InputLabelProps={{ shrink: true }}
              sx={{ minWidth: 160 }}
            />
          )}
        </Box>

        {/* Delete button */}
        {canDelete && (
          <Button
            size="small"
            color="error"
            startIcon={<DeleteIcon />}
            onClick={() => setDeleteOpen(true)}
            sx={{ mb: 2 }}
          >
            Löschen
          </Button>
        )}

        <Divider sx={{ my: 2 }} />

        {/* Comments section */}
        <Typography variant="subtitle2" gutterBottom>Kommentare</Typography>
        {commentsLoading ? (
          <CircularProgress size={20} />
        ) : comments.length === 0 ? (
          <Typography variant="body2" color="text.secondary">Noch keine Kommentare</Typography>
        ) : (
          comments.map((c: IssueComment) => (
            <Box key={c.id} sx={{ mb: 1.5, p: 1.5, bgcolor: 'action.hover', borderRadius: 1 }}>
              <Typography variant="caption" color="text.secondary">
                {c.autor_name || 'Unbekannt'} - {formatDate(c.created_at)}
              </Typography>
              <Typography variant="body2" sx={{ mt: 0.5, whiteSpace: 'pre-wrap' }}>{c.inhalt}</Typography>
            </Box>
          ))
        )}
        {canComment && (
          <Box sx={{ display: 'flex', gap: 1, mt: 1 }}>
            <TextField
              size="small"
              fullWidth
              placeholder="Kommentar schreiben..."
              value={commentText}
              onChange={(e) => setCommentText(e.target.value)}
              onKeyDown={(e) => {
                if (e.key === 'Enter' && !e.shiftKey && commentText.trim()) {
                  e.preventDefault();
                  addCommentMut.mutate(commentText.trim());
                }
              }}
              multiline
              maxRows={4}
            />
            <IconButton
              color="primary"
              disabled={!commentText.trim() || addCommentMut.isPending}
              onClick={() => addCommentMut.mutate(commentText.trim())}
            >
              <SendIcon />
            </IconButton>
          </Box>
        )}

        {/* History section */}
        <Divider sx={{ my: 2 }} />
        <Box sx={{ display: 'flex', alignItems: 'center', gap: 1, mb: 1 }}>
          <History fontSize="small" />
          <Typography variant="subtitle2">Historie</Typography>
        </Box>
        {historie.length === 0 ? (
          <Typography variant="body2" color="text.secondary">Keine Einträge</Typography>
        ) : (
          <Box sx={{ display: 'flex', flexDirection: 'column', gap: 1.5 }}>
            {historie.map((h) => (
              <Box key={h.id} sx={{ display: 'flex', gap: 1 }}>
                <Box sx={{ width: 6, minHeight: '100%', borderRadius: 3, bgcolor: 'divider', flexShrink: 0 }} />
                <Box>
                  <Typography variant="body2">{h.aktion}</Typography>
                  <Typography variant="caption" color="text.secondary">
                    {h.erstellt_von_name || 'System'} &middot; {formatDate(h.erstellt_am)}
                  </Typography>
                  {h.details && (
                    <Typography variant="caption" display="block" color="text.secondary">
                      {Object.entries(h.details).map(([k, v]) => `${k}: ${v}`).join(', ')}
                    </Typography>
                  )}
                </Box>
              </Box>
            ))}
          </Box>
        )}
      </Box>

      {/* Reopen Dialog */}
      <FormDialog
        open={reopenOpen}
        onClose={() => setReopenOpen(false)}
        onSubmit={handleReopen}
        title="Issue wiedereröffnen"
        submitLabel="Wiedereröffnen"
        isSubmitting={updateMut.isPending}
        maxWidth="sm"
      >
        <TextField
          label="Kommentar (Pflicht)"
          required
          multiline
          rows={3}
          fullWidth
          value={reopenComment}
          onChange={(e) => setReopenComment(e.target.value)}
          autoFocus
        />
      </FormDialog>

      {/* Delete Confirmation Dialog */}
      <ConfirmDialog
        open={deleteOpen}
        onClose={() => setDeleteOpen(false)}
        onConfirm={() => deleteMut.mutate()}
        title="Issue löschen"
        message="Soll dieses Issue wirklich gelöscht werden?"
        confirmLabel="Löschen"
        confirmColor="error"
        isLoading={deleteMut.isPending}
      />
    </DashboardLayout>
  );
}
