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 AutoFixHighIcon from "@mui/icons-material/AutoFixHigh";

import { getApiErrorMessage } from "../api";
import {
  FollowUp, INTERVIEW_PREP_CATEGORIES, InterviewPrepBoard, InterviewPrepItem, interviewPrepApi,
  ApplicationCv, applicationAssetsApi,
} from "../applicationWorkspace";
import { aiWorkspaceApi } from "../aiWorkspace";
import { useAccountPlan } from "../accountPlan";
import { useI18n } from "../i18n/I18nProvider";
import { useConfirm } from "../confirm";

// Phase 5.5 — Interview preparation and follow-up.
//
// The prep content is the user's. AI suggestions are generated in this dedicated workspace and only
// become prep items after an explicit accept action.
// 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 { t } = useI18n();
  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, t("interviewPrepLoadFailed")));
    } finally {
      setLoading(false);
    }
  }, [jobId, t]);

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

  const mutate = async (run: () => Promise<unknown>) => {
    setBusy(true);
    try {
      await run();
      await load();
    } catch (err) {
      setError(getApiErrorMessage(err, t("interviewPrepUpdateFailed")));
    } 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={t("interviewPrepTitle")}
        subtitle={t("interviewPrepSubtitle")}
        loading={loading}
        error={error}
      >
        <Stack spacing={2}>
          {board && !board.isInterviewStage && (
            <Alert severity="info" sx={{ borderRadius: 2 }}>
              {t("interviewPrepEarly")}
            </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 }}>
                  {t("interviewPrepProgress")}
                </Typography>
                <Typography variant="body2" color="text.secondary">
                  {t("interviewPrepReadyCount", { prepared: board.prepared, total: board.total })}
                </Typography>
              </Stack>
              <LinearProgress
                variant="determinate"
                value={board.percent}
                aria-label={t("interviewPrepProgress")}
                sx={{ height: 8, borderRadius: 4 }}
              />
            </Box>
          )}

          {board && board.total === 0 ? (
            <Typography variant="body2" color="text.secondary">
              {t("interviewPrepEmpty")}
            </Typography>
          ) : (
            (board?.groups ?? []).map((group) => (
              <Box key={group.category}>
                <Typography variant="caption" sx={{ fontWeight: 800, textTransform: "uppercase", letterSpacing: ".06em", color: "text.secondary" }}>
                  {interviewCategoryLabel(t, group.category)}
                </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={t("interviewPrepCategory")}
                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}>{interviewCategoryLabel(t, c.key)}</MenuItem>
                ))}
              </TextField>
              <TextField
                fullWidth
                size="small"
                label={t("interviewPrepAddLabel")}
                value={title}
                disabled={busy}
                onChange={(e) => setTitle(e.target.value)}
              />
              <Button type="submit" variant="contained" disabled={busy || !title.trim()}>{t("interviewPrepAdd")}</Button>
            </Stack>
          </Box>
        </Stack>
      </Shell>

      <InterviewAiAssistant jobId={jobId} onAccepted={load} />

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

const INTERVIEW_AI_FOCUS = [
  { key: "full", labelKey: "interviewAiFull", category: "note" },
  { key: "technical", labelKey: "interviewAiTechnical", category: "technical" },
  { key: "behavioural", labelKey: "interviewAiBehavioural", category: "behavioural" },
  { key: "star", labelKey: "interviewAiStar", category: "star" },
  { key: "gaps", labelKey: "interviewAiGaps", category: "note" },
] as const;

function InterviewAiAssistant({ jobId, onAccepted }: { jobId: number; onAccepted: () => void }) {
  const { canUseAi } = useAccountPlan();
  const { language: uiLanguage, t } = useI18n();
  const [cv, setCv] = useState<ApplicationCv | null>(null);
  const [focus, setFocus] = useState<(typeof INTERVIEW_AI_FOCUS)[number]["key"]>("full");
  const [language, setLanguage] = useState<"en" | "nb-NO">(() => uiLanguage === "nb" ? "nb-NO" : "en");
  const [instructions, setInstructions] = useState("");
  const [suggestion, setSuggestion] = useState("");
  const [busy, setBusy] = useState(false);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    let active = true;
    applicationAssetsApi.cv(jobId)
      .then((result) => { if (active) setCv(result); })
      .catch(() => { if (active) setCv(null); });
    return () => { active = false; };
  }, [jobId]);

  const selected = INTERVIEW_AI_FOCUS.find((item) => item.key === focus) ?? INTERVIEW_AI_FOCUS[0];
  const generate = async () => {
    setBusy(true);
    setError(null);
    try {
      const focusLabel = t(selected.labelKey);
      const extraContext = [
        `Focus this preparation on: ${focusLabel}.`,
        instructions.trim(),
      ].filter(Boolean).join("\n");
      const result = await aiWorkspaceApi.generate(jobId, {
        module: "interview",
        targetLanguage: language,
        extraContext,
      });
      setSuggestion(result.result.text?.trim() ?? "");
    } catch (err) {
      setError(getApiErrorMessage(err, t("interviewAiFailed")));
    } finally {
      setBusy(false);
    }
  };

  const accept = async () => {
    if (!suggestion) return;
    setBusy(true);
    setError(null);
    try {
      await interviewPrepApi.add(jobId, {
        category: selected.category,
        title: t(selected.labelKey),
        content: suggestion,
        source: "ai",
      });
      setSuggestion("");
      onAccepted();
    } catch (err) {
      setError(getApiErrorMessage(err, t("interviewAiAcceptFailed")));
    } finally {
      setBusy(false);
    }
  };

  const hasCv = !!cv?.attachedVariantId;
  return (
    <Shell title={t("interviewAiTitle")} subtitle={t("interviewAiSubtitle")} loading={false} error={null}>
      <Stack spacing={2}>
        {hasCv ? (
          <Alert severity="success" variant="outlined">{t("interviewAiUsing")} <strong>{cv?.attachedVariantName}</strong></Alert>
        ) : (
          <Alert severity="info">{t("interviewAiSelectCv")}</Alert>
        )}
        <Stack direction={{ xs: "column", sm: "row" }} spacing={1.5}>
          <TextField select size="small" label={t("interviewAiFocus")} value={focus} onChange={(event) => setFocus(event.target.value as typeof focus)} sx={{ minWidth: 220 }}>
            {INTERVIEW_AI_FOCUS.map((item) => <MenuItem key={item.key} value={item.key}>{t(item.labelKey)}</MenuItem>)}
          </TextField>
          <TextField select size="small" label={t("coverAiDocumentLanguage")} value={language} onChange={(event) => setLanguage(event.target.value as "en" | "nb-NO")} sx={{ minWidth: 190 }}>
            <MenuItem value="en">{t("languageEnglish")}</MenuItem>
            <MenuItem value="nb-NO">{t("languageNorwegianBokmal")}</MenuItem>
          </TextField>
        </Stack>
        <TextField multiline minRows={2} fullWidth label={t("coverAiAdditionalInstructions")} value={instructions} onChange={(event) => setInstructions(event.target.value)} />
        {error && <Alert severity="error">{error}</Alert>}
        <Button variant="contained" startIcon={<AutoFixHighIcon />} disabled={!canUseAi || !hasCv || busy} onClick={() => void generate()} sx={{ alignSelf: "flex-start" }}>
          {busy ? t("interviewAiGenerating") : canUseAi ? t("interviewAiGenerate") : t("interviewAiProRequired")}
        </Button>
        {suggestion && (
          <Paper variant="outlined" sx={{ p: 2, borderColor: "primary.main" }}>
            <Typography variant="overline" color="primary">{t("coverAiSuggestion")}</Typography>
            <Typography variant="body2" sx={{ whiteSpace: "pre-wrap", overflowWrap: "anywhere" }}>{suggestion}</Typography>
            <Stack direction="row" spacing={1} sx={{ mt: 2 }}>
              <Button size="small" variant="contained" disabled={busy} onClick={() => void accept()}>{t("interviewAiAddToPrep")}</Button>
              <Button size="small" disabled={busy} onClick={() => setSuggestion("")}>{t("coverAiReject")}</Button>
            </Stack>
          </Paper>
        )}
      </Stack>
    </Shell>
  );
}

// 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 { t } = useI18n();
  const { confirm } = useConfirm();
  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, t("interviewPrepAnswerSaveFailed")));
    } 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": t("interviewPrepReadyLabel", { title: 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={t("interviewPrepFromAi")} variant="outlined" />
            )}
          </Stack>
          <TextField
            multiline
            minRows={2}
            fullWidth
            size="small"
            placeholder={t("interviewPrepAnswerPlaceholder")}
            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 }))}
              >
                {t("interviewPrepSaveAnswer")}
              </Button>
              <Button size="small" disabled={saving} onClick={() => setDraft(null)}>{t("interviewPrepDiscard")}</Button>
            </Stack>
          )}
        </Box>
        <Tooltip title={t("interviewPrepDelete")}>
          <span>
            <IconButton
              size="small"
              disabled={busy || saving}
              aria-label={t("interviewPrepDeleteLabel", { title: item.title })}
              onClick={async () => {
                const accepted = await confirm({
                  title: t("interviewPrepDeleteTitle"),
                  message: t("interviewPrepDeleteMessage", { title: item.title }),
                  confirmLabel: t("interviewPrepDelete"),
                  destructive: true,
                });
                if (accepted) await run(() => interviewPrepApi.remove(jobId, item.id));
              }}
            >
              <DeleteOutlineIcon fontSize="inherit" />
            </IconButton>
          </span>
        </Tooltip>
      </Stack>
    </Box>
  );
}

export function ApplicationFollowUp({ jobId }: { jobId: number }) {
  const { t } = useI18n();
  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, t("interviewFollowUpLoadFailed")));
    } finally {
      setLoading(false);
    }
  }, [jobId, t]);

  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, t("interviewFollowUpSaveFailed")));
    } finally {
      setBusy(false);
    }
  };

  return (
    <Shell
      title={t("interviewFollowUpTitle")}
      subtitle={t("interviewFollowUpSubtitle")}
      loading={loading}
      error={error}
    >
      <Stack spacing={2}>
        {data && data.openFollowUpTasks > 0 && (
          <Alert severity="info" sx={{ borderRadius: 2 }}>
            {t(data.openFollowUpTasks === 1 ? "interviewFollowUpOpenTask" : "interviewFollowUpOpenTasks", { count: data.openFollowUpTasks })}
          </Alert>
        )}

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

        {data && !data.followUpAt && (
          <Typography variant="body2" color="text.secondary">
            {t("interviewFollowUpEmpty")}
          </Typography>
        )}
      </Stack>
    </Shell>
  );
}

function interviewCategoryLabel(t: (key: any) => string, category: string) {
  const keys: Record<string, string> = {
    "company-research": "interviewCategoryCompanyResearch",
    technical: "interviewCategoryTechnical",
    behavioural: "interviewCategoryBehavioural",
    star: "interviewCategoryStar",
    question: "interviewCategoryQuestions",
    note: "interviewCategoryNotes",
  };
  return keys[category] ? t(keys[category]) : category;
}
