import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import {
  Alert,
  Box,
  Button,
  Chip,
  CircularProgress,
  Container,
  Dialog,
  DialogActions,
  DialogContent,
  DialogTitle,
  Grid,
  IconButton,
  Paper,
  Stack,
  TextField,
  Tooltip,
  Typography,
} from '@mui/material';
import AddIcon from '@mui/icons-material/Add';
import ArchiveIcon from '@mui/icons-material/Archive';
import AssignmentIcon from '@mui/icons-material/Assignment';
import ContentCopyIcon from '@mui/icons-material/ContentCopy';
import EditIcon from '@mui/icons-material/Edit';
import GradingIcon from '@mui/icons-material/Grading';

import { useAuth } from '../../contexts/AuthContext';
import { examRepository } from '../../services/exam/examRepository';
import type { ExamTemplate } from '../../types/exam.types';
import { logger } from '../../debugConfig';

const STATUS_COLOR: Record<string, 'default' | 'info' | 'success' | 'warning'> = {
  draft: 'warning',
  ready: 'success',
  archived: 'default',
};

const VERSION_SEPARATOR = ' · ';
const VERSION_RE = /(?:^|\s)[vV](\d+(?:\.\d+)*)$/;

type DialogMode = 'create' | 'edit' | 'duplicate';

type TemplateDialogState = {
  mode: DialogMode;
  template?: ExamTemplate;
} | null;

function splitTemplateTitle(title: string): { name: string; version: string } {
  const parts = title.split(VERSION_SEPARATOR);
  const possibleVersion = parts[parts.length - 1]?.trim() ?? '';
  if (parts.length > 1 && VERSION_RE.test(possibleVersion)) {
    return { name: parts.slice(0, -1).join(VERSION_SEPARATOR).trim(), version: possibleVersion };
  }
  return { name: title, version: 'v1' };
}

function composeTemplateTitle(name: string, version: string): string {
  const cleanName = name.trim();
  const cleanVersion = version.trim();
  return cleanVersion ? `${cleanName}${VERSION_SEPARATOR}${cleanVersion}` : cleanName;
}

function nextVersionLabel(version: string): string {
  const match = version.trim().match(VERSION_RE);
  if (!match) return 'v2';
  const segments = match[1].split('.');
  const last = Number(segments[segments.length - 1]);
  segments[segments.length - 1] = Number.isFinite(last) ? String(last + 1) : '2';
  return `v${segments.join('.')}`;
}

function paperKey(t: ExamTemplate): string {
  return t.exam_id ?? t.source_file_id ?? t.exam_code ?? t.subject ?? 'custom-paper';
}

function paperLabel(t: ExamTemplate): string {
  if (t.exam_code) return t.exam_code;
  if (t.subject) return t.subject;
  if (t.source_file_id) return 'Uploaded paper';
  return 'Custom paper';
}

const ExamDashboardPage: React.FC = () => {
  const navigate = useNavigate();
  const { bootstrapData } = useAuth();
  const instituteId = bootstrapData?.active_institute?.id ?? undefined;

  const [templates, setTemplates] = useState<ExamTemplate[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  const [dialog, setDialog] = useState<TemplateDialogState>(null);
  const [templateName, setTemplateName] = useState('');
  const [version, setVersion] = useState('v1');
  const [subject, setSubject] = useState('');
  const [saving, setSaving] = useState(false);

  const load = useCallback(async () => {
    setLoading(true);
    setError(null);
    try {
      setTemplates(await examRepository.listTemplates());
    } catch (e) {
      const msg = e instanceof Error ? e.message : String(e);
      logger.warn('cc-exam-marker', 'Failed to load templates', { message: msg });
      setError(msg);
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    void load();
  }, [load, instituteId]);

  const groupedTemplates = useMemo(() => {
    const groups = new Map<string, { label: string; templates: ExamTemplate[] }>();
    templates.forEach((template) => {
      const key = paperKey(template);
      const existing = groups.get(key);
      if (existing) {
        existing.templates.push(template);
      } else {
        groups.set(key, { label: paperLabel(template), templates: [template] });
      }
    });
    return Array.from(groups.entries()).map(([key, group]) => ({ key, ...group }));
  }, [templates]);

  const openCreate = () => {
    setTemplateName('New template');
    setVersion('v1');
    setSubject('');
    setDialog({ mode: 'create' });
  };

  const openEdit = (template: ExamTemplate, ev: React.MouseEvent) => {
    ev.stopPropagation();
    const parsed = splitTemplateTitle(template.title);
    setTemplateName(parsed.name);
    setVersion(parsed.version);
    setSubject(template.subject ?? '');
    setDialog({ mode: 'edit', template });
  };

  const openDuplicate = (template: ExamTemplate, ev: React.MouseEvent) => {
    ev.stopPropagation();
    const parsed = splitTemplateTitle(template.title);
    setTemplateName(parsed.name);
    setVersion(nextVersionLabel(parsed.version));
    setSubject(template.subject ?? '');
    setDialog({ mode: 'duplicate', template });
  };

  const closeDialog = () => {
    if (!saving) setDialog(null);
  };

  const handleSaveDialog = async () => {
    if (!dialog || !templateName.trim()) return;
    const title = composeTemplateTitle(templateName, version);
    setSaving(true);
    try {
      if (dialog.mode === 'create') {
        const created = await examRepository.createTemplate({
          title,
          subject: subject.trim() || undefined,
          institute_id: instituteId,
        });
        setDialog(null);
        navigate(`/exam-marker/${created.id}/setup`);
        return;
      }

      if (!dialog.template) return;

      if (dialog.mode === 'duplicate') {
        const created = await examRepository.duplicateTemplate(dialog.template.id, title);
        setTemplates((prev) => [created, ...prev]);
        setDialog(null);
        navigate(`/exam-marker/${created.id}/setup`);
        return;
      }

      const updated = await examRepository.updateTemplateMeta(dialog.template.id, {
        title,
        subject: subject.trim() || null,
      });
      setTemplates((prev) => prev.map((t) => (t.id === updated.id ? updated : t)));
      setDialog(null);
    } catch (e) {
      const msg = e instanceof Error ? e.message : String(e);
      logger.error('cc-exam-marker', 'Template action failed', { message: msg, mode: dialog.mode });
      setError(msg);
    } finally {
      setSaving(false);
    }
  };

  const handleArchive = async (template: ExamTemplate, ev: React.MouseEvent) => {
    ev.stopPropagation();
    const parsed = splitTemplateTitle(template.title);
    if (!window.confirm(`Archive ${parsed.name} ${parsed.version}? This hides it from the dashboard but keeps the work recoverable.`)) {
      return;
    }
    try {
      await examRepository.archiveTemplate(template.id);
      setTemplates((prev) => prev.filter((t) => t.id !== template.id));
    } catch (e) {
      const msg = e instanceof Error ? e.message : String(e);
      logger.error('cc-exam-marker', 'Archive failed', { message: msg });
      setError(msg);
    }
  };

  const dialogTitle = dialog?.mode === 'edit'
    ? 'Rename template / edit version'
    : dialog?.mode === 'duplicate'
      ? 'Duplicate as new version'
      : 'New exam template';

  return (
    <Container maxWidth="lg" sx={{ py: 6 }}>
      <Stack spacing={4}>
        <Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', flexWrap: 'wrap', gap: 2 }}>
          <Box>
            <Typography variant="h3" component="h1" gutterBottom>
              Exam Marker
            </Typography>
            <Typography variant="body1" color="text.secondary" sx={{ maxWidth: 620 }}>
              Build multiple named templates for the same paper, version them as your setup changes, and archive drafts you no longer need.
            </Typography>
          </Box>
          <Button variant="contained" startIcon={<AddIcon />} onClick={openCreate}>
            New template
          </Button>
        </Box>

        {error && (
          <Alert severity="error" onClose={() => setError(null)}>
            {error}
          </Alert>
        )}

        {loading ? (
          <Box sx={{ display: 'flex', justifyContent: 'center', py: 8 }}>
            <CircularProgress />
          </Box>
        ) : templates.length === 0 ? (
          <Paper variant="outlined" sx={{ p: 6, textAlign: 'center' }}>
            <AssignmentIcon sx={{ fontSize: 48, color: 'text.disabled', mb: 1 }} />
            <Typography variant="h6" gutterBottom>No exam templates yet</Typography>
            <Typography variant="body2" color="text.secondary" sx={{ mb: 2 }}>
              Create your first named template to start mapping an exam paper.
            </Typography>
            <Button variant="outlined" startIcon={<AddIcon />} onClick={openCreate}>
              New template
            </Button>
          </Paper>
        ) : (
          <Stack spacing={3}>
            {groupedTemplates.map((group) => (
              <Box key={group.key}>
                <Stack direction="row" spacing={1} alignItems="center" sx={{ mb: 1 }}>
                  <Typography variant="h6">{group.label}</Typography>
                  <Chip size="small" label={`${group.templates.length} template${group.templates.length === 1 ? '' : 's'}`} variant="outlined" />
                </Stack>
                <Grid container spacing={3}>
                  {group.templates.map((t) => {
                    const parsed = splitTemplateTitle(t.title);
                    return (
                      <Grid item xs={12} sm={6} md={4} key={t.id}>
                        <Paper
                          elevation={2}
                          sx={{
                            p: 3,
                            height: '100%',
                            cursor: 'pointer',
                            display: 'flex',
                            flexDirection: 'column',
                            gap: 1,
                            transition: 'box-shadow 120ms',
                            '&:hover': { boxShadow: 6 },
                          }}
                          onClick={() => navigate(`/exam-marker/${t.id}/setup`)}
                        >
                          <Box sx={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 1 }}>
                            <Box sx={{ minWidth: 0 }}>
                              <Typography variant="h6" sx={{ pr: 1 }}>{parsed.name}</Typography>
                              <Chip size="small" label={parsed.version} color="info" variant="outlined" sx={{ mt: 0.5 }} />
                            </Box>
                            <Stack direction="row" spacing={0.5}>
                              <Tooltip title="Rename / edit version">
                                <IconButton size="small" onClick={(e) => openEdit(t, e)} aria-label="rename template">
                                  <EditIcon fontSize="small" />
                                </IconButton>
                              </Tooltip>
                              <Tooltip title="Duplicate as new version">
                                <IconButton size="small" onClick={(e) => openDuplicate(t, e)} aria-label="duplicate template">
                                  <ContentCopyIcon fontSize="small" />
                                </IconButton>
                              </Tooltip>
                              <Tooltip title="Archive">
                                <IconButton size="small" onClick={(e) => handleArchive(t, e)} aria-label="archive template">
                                  <ArchiveIcon fontSize="small" />
                                </IconButton>
                              </Tooltip>
                            </Stack>
                          </Box>
                          {t.subject && (
                            <Typography variant="body2" color="text.secondary">{t.subject}</Typography>
                          )}
                          {t.exam_code && (
                            <Typography variant="caption" color="text.secondary">{t.exam_code}</Typography>
                          )}
                          <Box sx={{ mt: 'auto', pt: 1, display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
                            <Chip size="small" label={t.status} color={STATUS_COLOR[t.status] ?? 'default'} variant="outlined" />
                            <Typography variant="caption" color="text.secondary">
                              Updated {new Date(t.updated_at).toLocaleDateString()}
                            </Typography>
                          </Box>
                          <Stack direction="row" spacing={1} sx={{ pt: 0.5 }}>
                            <Button
                              size="small"
                              variant="outlined"
                              onClick={(e) => { e.stopPropagation(); navigate(`/exam-marker/${t.id}/marks`); }}
                              startIcon={<GradingIcon fontSize="small" />}
                            >
                              Edit marks
                            </Button>
                          </Stack>
                        </Paper>
                      </Grid>
                    );
                  })}
                </Grid>
              </Box>
            ))}
          </Stack>
        )}
      </Stack>

      <Dialog open={Boolean(dialog)} onClose={closeDialog} fullWidth maxWidth="sm">
        <DialogTitle>{dialogTitle}</DialogTitle>
        <DialogContent>
          <Stack spacing={2} sx={{ mt: 1 }}>
            <TextField
              label="Template name"
              value={templateName}
              onChange={(e) => setTemplateName(e.target.value)}
              fullWidth
              autoFocus
              required
              helperText="User-facing name. Several templates can share the same paper."
            />
            <TextField
              label="Version"
              value={version}
              onChange={(e) => setVersion(e.target.value)}
              fullWidth
              helperText="Stored in the template title until the API grows a dedicated version column."
            />
            <TextField
              label="Paper / subject label"
              value={subject}
              onChange={(e) => setSubject(e.target.value)}
              fullWidth
              disabled={dialog?.mode === 'duplicate'}
            />
          </Stack>
        </DialogContent>
        <DialogActions>
          <Button onClick={closeDialog} disabled={saving}>Cancel</Button>
          <Button variant="contained" onClick={handleSaveDialog} disabled={saving || !templateName.trim()}>
            {saving ? 'Saving…' : dialog?.mode === 'duplicate' ? 'Create version' : 'Save'}
          </Button>
        </DialogActions>
      </Dialog>
    </Container>
  );
};

export default ExamDashboardPage;
