import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import { v5 as uuidv5 } from 'uuid';
import {
  Alert,
  Box,
  Button,
  Card,
  CardContent,
  Chip,
  CircularProgress,
  Container,
  Divider,
  List,
  ListItemButton,
  ListItemText,
  Stack,
  TextField,
  Typography,
} from '@mui/material';
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
import SaveIcon from '@mui/icons-material/Save';
import TableChartIcon from '@mui/icons-material/TableChart';

import { examRepository } from '../../services/exam/examRepository';
import type { BatchQueueResponse, ExamQuestion, ExamTemplateDetail, StudentSubmission } from '../../types/exam.types';

const MARK_NAMESPACE = '3f2dbbeb-9b15-4f99-9b71-8c535f8dc3d0';

function stableMarkId(batchId: string, submissionId: string, questionId: string) {
  return uuidv5(`${batchId}:${submissionId}:${questionId}`, MARK_NAMESPACE);
}

const ExamMarkingPage: React.FC = () => {
  const { batchId } = useParams<{ batchId: string }>();
  const navigate = useNavigate();
  const [queue, setQueue] = useState<BatchQueueResponse | null>(null);
  const [template, setTemplate] = useState<ExamTemplateDetail | null>(null);
  const [selectedId, setSelectedId] = useState<string | null>(null);
  const [marks, setMarks] = useState<Record<string, string>>({});
  const [comments, setComments] = useState<Record<string, string>>({});
  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);
  const [message, setMessage] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);

  const load = useCallback(async () => {
    if (!batchId) return;
    setLoading(true);
    setError(null);
    try {
      const nextQueue = await examRepository.getBatchQueue(batchId);
      setQueue(nextQueue);
      setTemplate(await examRepository.getTemplate(nextQueue.batch.template_id));
      setSelectedId((current) => current ?? nextQueue.submissions[0]?.id ?? null);
    } catch (e) {
      setError(e instanceof Error ? e.message : String(e));
    } finally {
      setLoading(false);
    }
  }, [batchId]);

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

  const markableQuestions = useMemo(
    () => (template?.questions ?? []).filter((q) => !q.is_container).sort((a, b) => a.order - b.order),
    [template],
  );
  const selected = queue?.submissions.find((s) => s.id === selectedId) ?? null;

  const saveSelected = async () => {
    if (!batchId || !selected) return;
    setSaving(true);
    setError(null);
    setMessage(null);
    try {
      const writes = markableQuestions
        .map((q) => ({ q, raw: marks[q.id], comment: comments[q.id] }))
        .filter(({ raw, comment }) => raw !== undefined && raw !== '' || !!comment?.trim());
      for (const { q, raw, comment } of writes) {
        const awarded = raw === undefined || raw === '' ? 0 : Number(raw);
        if (Number.isNaN(awarded) || awarded < 0 || awarded > (q.max_marks ?? Number.MAX_SAFE_INTEGER)) {
          throw new Error(`Invalid mark for ${q.label}`);
        }
        await examRepository.upsertMark(stableMarkId(batchId, selected.id, q.id), {
          submission_id: selected.id,
          question_id: q.id,
          awarded_marks: awarded,
          comment: comment?.trim() || undefined,
          confirmed: true,
        });
      }
      setMessage(`Saved ${writes.length} mark${writes.length === 1 ? '' : 's'} for ${selected.student_name || selected.student_id || 'student'}.`);
      setMarks({});
      setComments({});
      await load();
    } catch (e) {
      setError(e instanceof Error ? e.message : String(e));
    } finally {
      setSaving(false);
    }
  };

  const chooseStudent = (submission: StudentSubmission) => {
    setSelectedId(submission.id);
    setMarks({});
    setComments({});
    setMessage(null);
  };

  if (loading) {
    return <Box sx={{ display: 'flex', justifyContent: 'center', py: 8 }}><CircularProgress /></Box>;
  }

  if (error && !queue) {
    return (
      <Container maxWidth="lg" sx={{ py: 4 }}>
        <Alert severity="error">{error}</Alert>
        <Button sx={{ mt: 2 }} startIcon={<ArrowBackIcon />} onClick={() => navigate('/exam-marker')}>
          Back to Exam Marker
        </Button>
      </Container>
    );
  }

  return (
    <Container maxWidth="xl" sx={{ py: 3 }}>
      <Stack spacing={2}>
        <Box sx={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 2, flexWrap: 'wrap' }}>
          <Box>
            <Button size="small" startIcon={<ArrowBackIcon />} onClick={() => navigate('/exam-marker')} sx={{ mb: 1 }}>
              Exam Marker
            </Button>
            <Typography variant="h4" component="h1" fontWeight={700}>{queue?.batch.title || 'Mark exam'}</Typography>
            <Typography variant="body2" color="text.secondary">
              {template?.title || queue?.batch.template_id} · {queue?.progress.total ?? 0} students in queue
            </Typography>
          </Box>
          <Button variant="outlined" startIcon={<TableChartIcon />} onClick={() => batchId && navigate(`/exam-marker/${batchId}/results`)}>
            Results
          </Button>
        </Box>

        {error && <Alert severity="error" onClose={() => setError(null)}>{error}</Alert>}
        {message && <Alert severity="success" onClose={() => setMessage(null)}>{message}</Alert>}
        {markableQuestions.length === 0 && (
          <Alert severity="warning">
            This template has no markable parts yet. Add parts in template setup before entering marks.
          </Alert>
        )}

        <Stack direction={{ xs: 'column', md: 'row' }} spacing={2} alignItems="stretch">
          <Card variant="outlined" sx={{ width: { xs: '100%', md: 340 }, flexShrink: 0 }}>
            <CardContent>
              <Typography variant="h6" gutterBottom>Marking queue</Typography>
              <Stack direction="row" spacing={1} sx={{ mb: 1 }} flexWrap="wrap" useFlexGap>
                <Chip size="small" label={`${queue?.progress.total ?? 0} total`} />
                <Chip size="small" label={`${queue?.progress.absent ?? 0} absent`} color="warning" variant="outlined" />
                <Chip size="small" label={`${queue?.progress.complete ?? 0} complete`} color="success" variant="outlined" />
              </Stack>
              <List dense disablePadding>
                {(queue?.submissions ?? []).map((submission) => (
                  <ListItemButton
                    key={submission.id}
                    selected={submission.id === selectedId}
                    onClick={() => chooseStudent(submission)}
                    sx={{ borderRadius: 1, mb: 0.5 }}
                  >
                    <ListItemText
                      primary={submission.student_name || submission.student_id || 'Unknown student'}
                      secondary={`${submission.status} · ${submission.mark_entry_count ?? 0} marks`}
                    />
                    <Chip size="small" label={submission.status} color={submission.status === 'absent' ? 'warning' : 'default'} variant="outlined" />
                  </ListItemButton>
                ))}
              </List>
            </CardContent>
          </Card>

          <Card variant="outlined" sx={{ flex: 1 }}>
            <CardContent>
              {selected ? (
                <Stack spacing={2}>
                  <Box>
                    <Typography variant="h6">{selected.student_name || selected.student_id || 'Unknown student'}</Typography>
                    <Typography variant="body2" color="text.secondary">Status: {selected.status}</Typography>
                  </Box>
                  <Divider />
                  {markableQuestions.map((q: ExamQuestion) => (
                    <Stack key={q.id} direction={{ xs: 'column', sm: 'row' }} spacing={1.5} alignItems={{ xs: 'stretch', sm: 'center' }}>
                      <Box sx={{ minWidth: 150 }}>
                        <Typography variant="body2" fontWeight={700}>{q.label}</Typography>
                        <Typography variant="caption" color="text.secondary">/ {q.max_marks} marks</Typography>
                      </Box>
                      <TextField
                        label="Mark"
                        type="number"
                        size="small"
                        inputProps={{ min: 0, max: q.max_marks, step: 0.5 }}
                        value={marks[q.id] ?? ''}
                        onChange={(e) => setMarks((prev) => ({ ...prev, [q.id]: e.target.value }))}
                        sx={{ width: { xs: '100%', sm: 120 } }}
                      />
                      <TextField
                        label="Comment"
                        size="small"
                        value={comments[q.id] ?? ''}
                        onChange={(e) => setComments((prev) => ({ ...prev, [q.id]: e.target.value }))}
                        sx={{ flex: 1 }}
                      />
                    </Stack>
                  ))}
                  <Box sx={{ display: 'flex', justifyContent: 'flex-end', gap: 1 }}>
                    <Button onClick={() => navigate(`/exam-marker/${batchId}/results`)}>Skip to results</Button>
                    <Button variant="contained" startIcon={<SaveIcon />} onClick={saveSelected} disabled={saving || markableQuestions.length === 0}>
                      {saving ? 'Saving…' : 'Save marks'}
                    </Button>
                  </Box>
                </Stack>
              ) : (
                <Typography color="text.secondary" sx={{ py: 4, textAlign: 'center' }}>No submissions in this batch.</Typography>
              )}
            </CardContent>
          </Card>
        </Stack>
      </Stack>
    </Container>
  );
};

export default ExamMarkingPage;
