import React, { useCallback, useEffect, useState } from "react";

import {
  Alert, Box, Button, Checkbox, Chip, Divider, IconButton, LinearProgress, MenuItem, Paper,
  Skeleton, Stack, TextField, Tooltip, Typography,
} from "@mui/material";
import DeleteOutlineIcon from "@mui/icons-material/DeleteOutline";

import { getApiErrorMessage } from "../api";
import {
  FollowUp, INTERVIEW_PREP_CATEGORIES, InterviewPrepBoard, InterviewPrepItem, interviewPrepApi,
} from "../applicationWorkspace";

// Phase 5.5 — Interview preparation and follow-up.
//
// The prep content is the user's: this component never generates anything. AI suggestions live in the
// AI panel below and only become prep items when the user adds them.
// docs/architecture/application-workspace.md.

function Shell({ title, subtitle, loading, error, children }: {
  title: string;
  subtitle?: string;
  loading: boolean;
  error: string | null;
  children: React.ReactNode;
}) {
  return (
    <Paper sx={{ p: { xs: 2, sm: 2.5 }, borderRadius: 3 }}>
      <Typography variant="subtitle2" sx={{ fontWeight: 800 }}>{title}</Typography>
      {subtitle && <Typography variant="caption" color="text.secondary">{subtitle}</Typography>}
      <Divider sx={{ my: 1.5 }} />
      {loading ? (
        <Stack spacing={1}>{[0, 1, 2].map((i) => <Skeleton key={i} variant="rounded" height={44} />)}</Stack>
      ) : error ? (
        <Alert severity="error">{error}</Alert>
      ) : (
        children
      )}
    </Paper>
  );
}

export function ApplicationInterviewPrep({ jobId }: { jobId: number }) {
  const [board, setBoard] = useState<InterviewPrepBoard | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [loading, setLoading] = useState(true);
  const [busy, setBusy] = useState(false);
  const [title, setTitle] = useState("");
  const [category, setCategory] = useState(INTERVIEW_PREP_CATEGORIES[0].key);

  const load = useCallback(async () => {
    setLoading(true);
    try {
      setBoard(await interviewPrepApi.get(jobId));
      setError(null);
    } catch (err) {
      setError(getApiErrorMessage(err, "Could not load interview preparation."));
    } finally {
      setLoading(false);
    }
  }, [jobId]);

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

  const mutate = async (run: () => Promise<unknown>) => {
    setBusy(true);
    try {
      await run();
      await load();
    } catch (err) {
      setError(getApiErrorMessage(err, "Could not update interview preparation."));
    } finally {
      setBusy(false);
    }
  };

  const add = (e: React.FormEvent) => {
    e.preventDefault();
    const value = title.trim();
    if (!value) return;
    setTitle("");
    return mutate(() => interviewPrepApi.add(jobId, { category, title: value }));
  };

  return (
    <Stack spacing={2}>
      <Shell
        title="Interview preparation"
        subtitle="Your own research, answers and questions. Nothing here is generated or overwritten."
        loading={loading}
        error={error}
      >
        <Stack spacing={2}>
          {board && !board.isInterviewStage && (
            <Alert severity="info" sx={{ borderRadius: 2 }}>
              This application has not reached an interview stage yet. Preparing early is fine.
            </Alert>
          )}

          {board && board.total > 0 && (
            <Box>
              <Stack direction="row" justifyContent="space-between" alignItems="baseline" sx={{ mb: 0.75 }}>
                <Typography variant="caption" color="text.secondary" sx={{ fontWeight: 700 }}>
                  Preparation progress
                </Typography>
                <Typography variant="body2" color="text.secondary">
                  {board.prepared} of {board.total} ready
                </Typography>
              </Stack>
              <LinearProgress
                variant="determinate"
                value={board.percent}
                aria-label="Interview preparation progress"
                sx={{ height: 8, borderRadius: 4 }}
              />
            </Box>
          )}

          {board && board.total === 0 ? (
            <Typography variant="body2" color="text.secondary">
              Nothing prepared yet. Add a question you expect, a company fact worth knowing, or a STAR
              example you want ready.
            </Typography>
          ) : (
            (board?.groups ?? []).map((group) => (
              <Box key={group.category}>
                <Typography variant="caption" sx={{ fontWeight: 800, textTransform: "uppercase", letterSpacing: ".06em", color: "text.secondary" }}>
                  {group.label}
                </Typography>
                <Stack sx={{ mt: 0.5 }}>
                  {group.items.map((item) => (
                    <PrepRow
                      key={item.id}
                      jobId={jobId}
                      item={item}
                      busy={busy}
                      onChanged={load}
                      onError={setError}
                    />
                  ))}
                </Stack>
              </Box>
            ))
          )}

          <Box component="form" onSubmit={add}>
            <Stack direction={{ xs: "column", sm: "row" }} spacing={1}>
              <TextField
                select
                size="small"
                label="Category"
                value={category}
                disabled={busy}
                onChange={(e) => setCategory(e.target.value)}
                sx={{ minWidth: { sm: 200 } }}
              >
                {INTERVIEW_PREP_CATEGORIES.map((c) => (
                  <MenuItem key={c.key} value={c.key}>{c.label}</MenuItem>
                ))}
              </TextField>
              <TextField
                fullWidth
                size="small"
                label="Add a question, topic or note"
                value={title}
                disabled={busy}
                onChange={(e) => setTitle(e.target.value)}
              />
              <Button type="submit" variant="contained" disabled={busy || !title.trim()}>Add</Button>
            </Stack>
          </Box>
        </Stack>
      </Shell>

      <ApplicationFollowUp jobId={jobId} />
    </Stack>
  );
}

// One prep entry. The answer is a local draft until saved, so a background reload never eats typing.
function PrepRow({ jobId, item, busy, onChanged, onError }: {
  jobId: number;
  item: InterviewPrepItem;
  busy: boolean;
  onChanged: () => void;
  onError: (message: string) => void;
}) {
  const [draft, setDraft] = useState<string | null>(null);
  const [saving, setSaving] = useState(false);
  const content = draft ?? item.content ?? "";
  const dirty = draft !== null && draft !== (item.content ?? "");

  const run = async (fn: () => Promise<unknown>) => {
    setSaving(true);
    try {
      await fn();
      setDraft(null);
      onChanged();
    } catch (err) {
      onError(getApiErrorMessage(err, "Could not save this answer."));
    } finally {
      setSaving(false);
    }
  };

  return (
    <Box sx={{ py: 1, borderBottom: "1px solid", borderColor: "divider" }}>
      <Stack direction="row" alignItems="flex-start" spacing={1}>
        <Checkbox
          size="small"
          checked={item.isPrepared}
          disabled={busy || saving}
          inputProps={{ "aria-label": `Ready: ${item.title}` }}
          onChange={() => run(() => interviewPrepApi.update(jobId, item.id, { isPrepared: !item.isPrepared }))}
          sx={{ mt: -0.5 }}
        />
        <Box sx={{ flexGrow: 1, minWidth: 0 }}>
          <Stack direction="row" spacing={0.75} alignItems="center" flexWrap="wrap">
            <Typography variant="body2" sx={{ fontWeight: 600 }}>{item.title}</Typography>
            {item.source === "ai" && (
              <Chip size="small" label="From AI" variant="outlined" />
            )}
          </Stack>
          <TextField
            multiline
            minRows={2}
            fullWidth
            size="small"
            placeholder="Your answer, in your own words."
            value={content}
            disabled={busy || saving}
            onChange={(e) => setDraft(e.target.value)}
            sx={{ mt: 0.75 }}
          />
          {dirty && (
            <Stack direction="row" spacing={1} sx={{ mt: 0.75 }}>
              <Button
                size="small"
                variant="contained"
                disabled={saving}
                onClick={() => run(() => interviewPrepApi.update(jobId, item.id, { content }))}
              >
                Save answer
              </Button>
              <Button size="small" disabled={saving} onClick={() => setDraft(null)}>Discard</Button>
            </Stack>
          )}
        </Box>
        <Tooltip title="Delete">
          <span>
            <IconButton
              size="small"
              disabled={busy || saving}
              aria-label={`Delete: ${item.title}`}
              onClick={() => run(() => interviewPrepApi.remove(jobId, item.id))}
            >
              <DeleteOutlineIcon fontSize="inherit" />
            </IconButton>
          </span>
        </Tooltip>
      </Stack>
    </Box>
  );
}

export function ApplicationFollowUp({ jobId }: { jobId: number }) {
  const [data, setData] = useState<FollowUp | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [loading, setLoading] = useState(true);
  const [busy, setBusy] = useState(false);
  const [date, setDate] = useState<string>("");
  const [action, setAction] = useState<string>("");

  const load = useCallback(async () => {
    setLoading(true);
    try {
      const result = await interviewPrepApi.followUp(jobId);
      setData(result);
      setDate(result.followUpAt ? result.followUpAt.slice(0, 10) : "");
      setAction(result.nextAction ?? "");
      setError(null);
    } catch (err) {
      setError(getApiErrorMessage(err, "Could not load follow-up."));
    } finally {
      setLoading(false);
    }
  }, [jobId]);

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

  const save = async () => {
    setBusy(true);
    try {
      const result = await interviewPrepApi.setFollowUp(jobId, date || null, action || null);
      setData(result);
      setError(null);
    } catch (err) {
      setError(getApiErrorMessage(err, "Could not save the follow-up."));
    } finally {
      setBusy(false);
    }
  };

  return (
    <Shell
      title="Follow-up"
      subtitle="The same date the reminder service already uses. Follow-up tasks live in the checklist."
      loading={loading}
      error={error}
    >
      <Stack spacing={2}>
        {data && data.openFollowUpTasks > 0 && (
          <Alert severity="info" sx={{ borderRadius: 2 }}>
            {data.openFollowUpTasks} open follow-up {data.openFollowUpTasks === 1 ? "task" : "tasks"} on
            the checklist.
          </Alert>
        )}

        <Stack direction={{ xs: "column", sm: "row" }} spacing={1}>
          <TextField
            type="date"
            size="small"
            label="Follow up on"
            value={date}
            disabled={busy}
            onChange={(e) => setDate(e.target.value)}
            InputLabelProps={{ shrink: true }}
          />
          <TextField
            fullWidth
            size="small"
            label="Next action"
            value={action}
            disabled={busy}
            onChange={(e) => setAction(e.target.value)}
          />
          <Button variant="contained" disabled={busy} onClick={save}>Save</Button>
        </Stack>

        {data && !data.followUpAt && (
          <Typography variant="body2" color="text.secondary">
            No follow-up scheduled. Applications without one go quiet.
          </Typography>
        )}
      </Stack>
    </Shell>
  );
}
