import { useState, useMemo } from 'react';
import {
  Box, Tab, Tabs, Typography, Chip, IconButton, Button, TextField,
  CircularProgress, FormControlLabel, Switch,
  Autocomplete, ToggleButtonGroup, ToggleButton, Tooltip,
} from '@mui/material';
import {
  Add as AddIcon,
  BugReport, FiberNew, HelpOutline,
  Circle as CircleIcon,
  ViewList as ViewListIcon, ViewKanban as ViewKanbanIcon,
  Settings as SettingsIcon,
} from '@mui/icons-material';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { useSearchParams, useNavigate } from 'react-router-dom';
import DashboardLayout from '../components/dashboard/DashboardLayout';
import ChatAwareFab from '../components/shared/ChatAwareFab';
import { DataTable } from '../components/templates';
import type { Column } from '../components/templates';
import { useNotification } from '../contexts/NotificationContext';
import { usePermissionContext } from '../contexts/PermissionContext';
import { useAuth } from '../contexts/AuthContext';
import { issuesApi } from '../services/issues';
import type { Issue, IssueTyp, IssueFilters, AssignableMember, IssueStatusDef, IssuePriorityDef } from '../types/issue.types';
import KanbanBoard from '../components/issues/KanbanBoard';

// ── Helpers ──

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 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>;
}

// ── Tab Panel ──

interface TabPanelProps { children: React.ReactNode; index: number; value: number }
function TabPanel({ children, value, index }: TabPanelProps) {
  if (value !== index) return null;
  return <Box sx={{ pt: 3 }}>{children}</Box>;
}

// ── Issue Table ──

function IssueTable({
  issues,
  statuses,
  priorities,
}: {
  issues: Issue[];
  statuses: IssueStatusDef[];
  priorities: IssuePriorityDef[];
}) {
  const navigate = useNavigate();

  const columns: Column<Issue>[] = [
    { key: 'id', label: 'ID', width: 80, render: (row) => formatIssueId(row) },
    {
      key: 'titel', label: 'Titel', render: (row) => (
        <Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
          {getTypIcon(row.typ_icon, row.typ_farbe)}
          <Typography variant="body2">{row.titel}</Typography>
        </Box>
      ),
    },
    { key: 'typ_name', label: 'Typ', render: (row) => <Chip label={row.typ_name} size="small" variant="outlined" /> },
    {
      key: 'prioritaet', label: 'Priorität', render: (row) => (
        <Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}>
          <CircleIcon sx={{ fontSize: 10, color: getPrioColor(priorities, row.prioritaet) }} />
          <Typography variant="body2">{getPrioLabel(priorities, row.prioritaet)}</Typography>
        </Box>
      ),
    },
    {
      key: 'status', label: 'Status', render: (row) => (
        <Chip label={getStatusLabel(statuses, row.status)} size="small" color={getStatusColor(statuses, row.status)} />
      ),
    },
    { key: 'erstellt_von_name', label: 'Erstellt von', render: (row) => row.erstellt_von_name || '-' },
    { key: 'zugewiesen_an_name', label: 'Zugewiesen an', render: (row) => row.zugewiesen_an_name || '-' },
    { key: 'created_at', label: 'Erstellt am', render: (row) => formatDate(row.created_at) },
  ];

  return (
    <DataTable
      columns={columns}
      data={issues}
      rowKey={(row) => row.id}
      onRowClick={(row) => navigate(`/issues/${row.id}`)}
      emptyMessage="Keine Issues vorhanden"
      searchEnabled={false}
      paginationEnabled={false}
    />
  );
}

// ── Filter Bar (for "Alle Issues" tab) ──

function FilterBar({
  filters,
  onChange,
  types,
  members,
  statuses,
  priorities,
}: {
  filters: IssueFilters;
  onChange: (f: IssueFilters) => void;
  types: IssueTyp[];
  members: AssignableMember[];
  statuses: IssueStatusDef[];
  priorities: IssuePriorityDef[];
}) {
  return (
    <Box sx={{ display: 'flex', gap: 1.5, mb: 2, flexWrap: 'wrap', alignItems: 'center' }}>
      {/* Type filter */}
      <Autocomplete
        multiple
        size="small"
        sx={{ minWidth: 200 }}
        options={types}
        getOptionLabel={(t) => t.name}
        value={types.filter(t => filters.typ_id?.includes(t.id))}
        onChange={(_e, val) => onChange({ ...filters, typ_id: val.map(v => v.id) })}
        renderInput={(params) => <TextField {...params} label="Typ" size="small" />}
        isOptionEqualToValue={(o, v) => o.id === v.id}
      />

      {/* Priority filter */}
      <Autocomplete
        multiple
        size="small"
        sx={{ minWidth: 180 }}
        options={priorities.filter(p => p.aktiv).map(p => p.schluessel)}
        getOptionLabel={(key) => getPrioLabel(priorities, key)}
        value={filters.prioritaet || []}
        onChange={(_e, val) => onChange({ ...filters, prioritaet: val })}
        renderInput={(params) => <TextField {...params} label="Priorität" size="small" />}
      />

      {/* Status filter */}
      <Autocomplete
        multiple
        size="small"
        sx={{ minWidth: 200 }}
        options={statuses.filter(s => s.aktiv).map(s => s.schluessel)}
        getOptionLabel={(key) => getStatusLabel(statuses, key)}
        value={filters.status || []}
        onChange={(_e, val) => onChange({ ...filters, status: val })}
        renderInput={(params) => <TextField {...params} label="Status" size="small" />}
      />

      {/* Erstellt von */}
      <Autocomplete
        size="small"
        sx={{ minWidth: 180 }}
        options={members}
        getOptionLabel={(m) => m.name}
        value={members.find(m => m.id === filters.erstellt_von) || null}
        onChange={(_e, val) => onChange({ ...filters, erstellt_von: val?.id })}
        renderInput={(params) => <TextField {...params} label="Erstellt von" size="small" />}
        isOptionEqualToValue={(o, v) => o.id === v.id}
      />

      {/* Clear */}
      {(filters.typ_id?.length || filters.prioritaet?.length || filters.status?.length || filters.erstellt_von) && (
        <Button size="small" onClick={() => onChange({})}>Filter zurücksetzen</Button>
      )}
    </Box>
  );
}

// ── Main Page ──

export default function Issues() {
  const [searchParams, setSearchParams] = useSearchParams();
  const navigate = useNavigate();
  const queryClient = useQueryClient();
  const { hasPermission } = usePermissionContext();
  const { user } = useAuth();
  const { showSuccess, showError } = useNotification();

  const canViewAll = hasPermission('issues:view_all');
  const hasEdit = hasPermission('issues:edit');
  const hasEditSettings = hasPermission('issues:edit_settings');
  const canCreate = hasPermission('issues:create');
  const userId = user?.id || '';

  // Build tab list dynamically
  const tabs = useMemo(() => {
    const t: { label: string; key: string }[] = [
      { label: 'Meine Issues', key: 'mine' },
      { label: 'Zugewiesene Issues', key: 'assigned' },
    ];
    if (canViewAll) t.push({ label: 'Alle Issues', key: 'all' });
    return t;
  }, [canViewAll]);

  const tabParam = parseInt(searchParams.get('tab') || '0', 10);
  const tab = isNaN(tabParam) || tabParam < 0 || tabParam >= tabs.length ? 0 : tabParam;

  const [showDoneMine, setShowDoneMine] = useState(false);
  const [showDoneAssigned, setShowDoneAssigned] = useState(false);
  const [filters, setFilters] = useState<IssueFilters>({});
  const [viewMode, setViewMode] = useState<'list' | 'kanban'>(() => {
    try { return (localStorage.getItem('issues-view-mode') as 'list' | 'kanban') || 'list'; }
    catch { return 'list'; }
  });

  const handleViewModeChange = (_: unknown, val: 'list' | 'kanban' | null) => {
    if (!val) return;
    setViewMode(val);
    localStorage.setItem('issues-view-mode', val);
  };

  // Mutation for kanban drag-and-drop status change
  const updateStatusMut = useMutation({
    mutationFn: ({ id, status }: { id: number; status: string }) =>
      issuesApi.updateIssue(id, { status }),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['issues'] });
      showSuccess('Status aktualisiert');
    },
    onError: () => showError('Fehler beim Aktualisieren'),
  });

  // Fetch all issues for mine/assigned tabs
  const { data: issues = [], isLoading } = useQuery({
    queryKey: ['issues'],
    queryFn: () => issuesApi.getIssues(),
  });

  // Fetch filtered issues for "Alle Issues" tab
  const activeTab = tabs[tab]?.key;
  const { data: filteredIssues = [], isLoading: isFilteredLoading } = useQuery({
    queryKey: ['issues', 'filtered', filters],
    queryFn: () => issuesApi.getIssues(filters),
    enabled: activeTab === 'all',
  });

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

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

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

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

  const handleTabChange = (_: unknown, newValue: number) => {
    setSearchParams({ tab: String(newValue) });
  };

  // Filter logic for client-side tabs
  const isDone = (i: Issue) => {
    const def = issueStatuses.find(s => s.schluessel === i.status);
    return def?.ist_abschluss ?? (i.status === 'erledigt' || i.status === 'abgelehnt');
  };
  const myIssues = issues.filter((i: Issue) => i.erstellt_von === userId);
  const myIssuesFiltered = showDoneMine ? myIssues : myIssues.filter((i: Issue) => !isDone(i));
  const assignedIssues = issues.filter((i: Issue) => i.zugewiesen_an === userId);
  const assignedFiltered = showDoneAssigned ? assignedIssues : assignedIssues.filter((i: Issue) => !isDone(i));

  return (
    <DashboardLayout>
      <Box sx={{ p: 3 }}>
        <Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 1 }}>
          <Typography variant="h5">Issues</Typography>
          <Box sx={{ display: 'flex', gap: 1, alignItems: 'center' }}>
            {hasEditSettings && (
              <Tooltip title="Einstellungen">
                <IconButton onClick={() => navigate('/admin/settings?tab=1&subtab=issues')}>
                  <SettingsIcon />
                </IconButton>
              </Tooltip>
            )}
            <ToggleButtonGroup
              value={viewMode}
              exclusive
              onChange={handleViewModeChange}
              size="small"
            >
              <ToggleButton value="list" aria-label="Listenansicht">
                <ViewListIcon fontSize="small" />
              </ToggleButton>
              <ToggleButton value="kanban" aria-label="Kanban-Ansicht">
                <ViewKanbanIcon fontSize="small" />
              </ToggleButton>
            </ToggleButtonGroup>
          </Box>
        </Box>

        <Tabs value={tab} onChange={handleTabChange} sx={{ mb: 0 }}>
          {tabs.map((t, i) => <Tab key={i} label={t.label} />)}
        </Tabs>

        {/* Tab 0: Meine Issues */}
        <TabPanel value={tab} index={0}>
          <Box sx={{ display: 'flex', alignItems: 'center', gap: 2, mb: 1 }}>
            {viewMode === 'list' && (
              <FormControlLabel
                control={<Switch checked={showDoneMine} onChange={(e) => setShowDoneMine(e.target.checked)} size="small" />}
                label="Erledigte anzeigen"
              />
            )}
          </Box>
          {isLoading ? (
            <Box sx={{ display: 'flex', justifyContent: 'center', py: 4 }}><CircularProgress /></Box>
          ) : viewMode === 'kanban' ? (
            <KanbanBoard
              issues={myIssuesFiltered}
              statuses={issueStatuses}
              priorities={issuePriorities}
              onNavigate={(id) => navigate(`/issues/${id}`)}
              onStatusChange={(id, status) => updateStatusMut.mutate({ id, status })}
            />
          ) : (
            <IssueTable issues={myIssuesFiltered} statuses={issueStatuses} priorities={issuePriorities} />
          )}
        </TabPanel>

        {/* Tab 1: Zugewiesene Issues */}
        <TabPanel value={tab} index={1}>
          <Box sx={{ display: 'flex', alignItems: 'center', gap: 2, mb: 1 }}>
            {viewMode === 'list' && (
              <FormControlLabel
                control={<Switch checked={showDoneAssigned} onChange={(e) => setShowDoneAssigned(e.target.checked)} size="small" />}
                label="Erledigte anzeigen"
              />
            )}
          </Box>
          {isLoading ? (
            <Box sx={{ display: 'flex', justifyContent: 'center', py: 4 }}><CircularProgress /></Box>
          ) : viewMode === 'kanban' ? (
            <KanbanBoard
              issues={assignedFiltered}
              statuses={issueStatuses}
              priorities={issuePriorities}
              onNavigate={(id) => navigate(`/issues/${id}`)}
              onStatusChange={(id, status) => updateStatusMut.mutate({ id, status })}
            />
          ) : (
            <IssueTable issues={assignedFiltered} statuses={issueStatuses} priorities={issuePriorities} />
          )}
        </TabPanel>

        {/* Tab 2: Alle Issues (conditional) */}
        {canViewAll && (
          <TabPanel value={tab} index={tabs.findIndex(t => t.key === 'all')}>
            <FilterBar filters={filters} onChange={setFilters} types={types} members={members} statuses={issueStatuses} priorities={issuePriorities} />
            {isFilteredLoading ? (
              <Box sx={{ display: 'flex', justifyContent: 'center', py: 4 }}><CircularProgress /></Box>
            ) : viewMode === 'kanban' ? (
              <KanbanBoard
                issues={filteredIssues}
                statuses={issueStatuses}
                priorities={issuePriorities}
                onNavigate={(id) => navigate(`/issues/${id}`)}
                onStatusChange={(id, status) => updateStatusMut.mutate({ id, status })}
              />
            ) : (
              <IssueTable issues={filteredIssues} statuses={issueStatuses} priorities={issuePriorities} />
            )}
          </TabPanel>
        )}

      </Box>

      {/* FAB */}
      {canCreate && (
        <ChatAwareFab
          color="primary"
          aria-label="Neues Issue"
          onClick={() => navigate('/issues/neu')}
        >
          <AddIcon />
        </ChatAwareFab>
      )}
    </DashboardLayout>
  );
}
