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

import {
  Alert, Box, Chip, Divider, LinearProgress, Paper, Skeleton, Stack, ToggleButton,
  ToggleButtonGroup, Typography,
} from "@mui/material";

import { getApiErrorMessage } from "../api";
import {
  CareerMatch, JobAnalysis, Timeline, applicationIntelligenceApi,
} from "../applicationWorkspace";
import { useI18n } from "../i18n/I18nProvider";

// Phase 5.3 — Application Intelligence sections for the workspace.
//
// Everything here renders a deterministic, read-only backend answer. No component triggers an AI
// generation stays in the dedicated document/preparation tools, so nothing on this page can
// silently spend a token or change the user's data.
// docs/architecture/application-workspace.md.

// One loader for all three sections: same fetch/loading/empty/error shape, so the sections stay
// consistent and each one is just its own rendering.
function useIntelligence<T>(load: () => Promise<T>, deps: React.DependencyList) {
  const { t } = useI18n();
  const [data, setData] = useState<T | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [loading, setLoading] = useState(true);

  // eslint-disable-next-line react-hooks/exhaustive-deps
  const run = useCallback(load, deps);

  useEffect(() => {
    let cancelled = false;
    setLoading(true);
    run()
      .then((result) => {
        if (cancelled) return;
        setData(result);
        setError(null);
      })
      .catch((err) => {
        if (!cancelled) setError(getApiErrorMessage(err, t("intelligenceLoadFailed")));
      })
      .finally(() => {
        if (!cancelled) setLoading(false);
      });
    return () => {
      cancelled = true;
    };
  }, [run, t]);

  return { data, error, loading };
}

function SectionShell({ title, subtitle, loading, error, empty, emptyText, children }: {
  title: string;
  subtitle?: string;
  loading: boolean;
  error: string | null;
  empty?: boolean;
  emptyText?: string;
  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={40} />)}</Stack>
      ) : error ? (
        <Alert severity="error">{error}</Alert>
      ) : empty ? (
        <Typography variant="body2" color="text.secondary">{emptyText}</Typography>
      ) : (
        children
      )}
    </Paper>
  );
}

function Chips({ label, values, color }: { label: string; values: string[]; color?: "success" | "warning" | "default" }) {
  if (values.length === 0) return null;
  return (
    <Box>
      <Typography variant="caption" color="text.secondary" sx={{ fontWeight: 700 }}>{label}</Typography>
      <Stack direction="row" flexWrap="wrap" gap={0.5} sx={{ mt: 0.5 }}>
        {values.map((v) => (
          <Chip key={v} size="small" label={v} variant="outlined"
            color={color === "default" ? undefined : color} />
        ))}
      </Stack>
    </Box>
  );
}

function Bullets({ label, values }: { label: string; values: string[] }) {
  if (values.length === 0) return null;
  return (
    <Box>
      <Typography variant="caption" color="text.secondary" sx={{ fontWeight: 700 }}>{label}</Typography>
      <Stack component="ul" spacing={0.5} sx={{ mt: 0.5, pl: 2.5, mb: 0 }}>
        {values.map((v, i) => (
          <Typography key={i} component="li" variant="body2">{v}</Typography>
        ))}
      </Stack>
    </Box>
  );
}

// ---------- Timeline ----------

export function ApplicationTimeline({ jobId }: { jobId: number }) {
  const { language, t } = useI18n();
  const [category, setCategory] = useState<string>("");
  const { data, error, loading } = useIntelligence<Timeline>(
    () => applicationIntelligenceApi.timeline(jobId, category || undefined),
    [jobId, category],
  );

  const hasEvents = (data?.totalEvents ?? 0) > 0;

  return (
    <Stack spacing={2}>
      {hasEvents && (data?.milestones.length ?? 0) > 0 && (
        <Paper sx={{ p: 2, borderRadius: 3 }}>
          <Typography variant="subtitle2" sx={{ fontWeight: 800, mb: 1 }}>{t("intelligenceMilestones")}</Typography>
          <Stack spacing={0.75}>
            {(data?.milestones ?? []).map((m) => (
              <Stack key={m.id} direction="row" spacing={1} justifyContent="space-between" alignItems="baseline">
                <Typography variant="body2" sx={{ fontWeight: 600 }}>{m.summary}</Typography>
                <Typography variant="caption" color="text.secondary">
                  {new Date(m.at).toLocaleDateString(language === "nb" ? "nb-NO" : "en")}
                </Typography>
              </Stack>
            ))}
          </Stack>
        </Paper>
      )}

      <SectionShell
        title={t("intelligenceTimeline")}
        subtitle={t("intelligenceTimelineSubtitle")}
        loading={loading}
        error={error}
        empty={!hasEvents}
        emptyText={t("intelligenceTimelineEmpty")}
      >
        {/* SectionShell takes children as a prop, so this JSX is built before it decides whether to
            render it — every access has to tolerate a null `data`. */}
        <Stack spacing={2}>
          {(data?.categories.length ?? 0) > 1 && (
            <ToggleButtonGroup
              size="small"
              exclusive
              value={category}
              onChange={(_e, next) => setCategory(next ?? "")}
              aria-label={t("intelligenceTimelineFilter")}
              sx={{ flexWrap: "wrap" }}
            >
              <ToggleButton value="" aria-label={t("intelligenceAllEvents")}>{t("intelligenceAll")}</ToggleButton>
              {(data?.categories ?? []).map((c) => (
                <ToggleButton key={c} value={c} aria-label={timelineCategoryLabel(t, c)}>
                  {timelineCategoryLabel(t, c)}
                </ToggleButton>
              ))}
            </ToggleButtonGroup>
          )}

          {(data?.days.length ?? 0) === 0 ? (
            <Typography variant="body2" color="text.secondary">{t("intelligenceNoCategoryEvents")}</Typography>
          ) : (
            (data?.days ?? []).map((day) => (
              <Box key={day.date}>
                <Typography variant="caption" sx={{ fontWeight: 800, textTransform: "uppercase", letterSpacing: ".06em", color: "text.secondary" }}>
                  {day.label}
                </Typography>
                <Stack spacing={1} sx={{ mt: 0.75, pl: 1.5, borderLeft: "2px solid", borderColor: "divider" }}>
                  {day.events.map((e) => (
                    <Box key={e.id} sx={{ pl: 1.5 }}>
                      <Stack direction="row" spacing={0.75} alignItems="center" flexWrap="wrap">
                        <Typography variant="body2" sx={{ fontWeight: e.isMilestone ? 700 : 500 }}>
                          {e.summary}
                        </Typography>
                        {e.isMilestone && <Chip size="small" label={t("intelligenceMilestone")} color="primary" variant="outlined" />}
                      </Stack>
                      {e.detail && (
                        <Typography variant="caption" color="text.secondary">{e.detail}</Typography>
                      )}
                    </Box>
                  ))}
                </Stack>
              </Box>
            ))
          )}
        </Stack>
      </SectionShell>
    </Stack>
  );
}

// ---------- Analysis ----------

export function ApplicationAnalysis({ jobId }: { jobId: number }) {
  const { t } = useI18n();
  const { data, error, loading } = useIntelligence<JobAnalysis>(
    () => applicationIntelligenceApi.analysis(jobId),
    [jobId],
  );

  const facts: [string, string | null][] = data
    ? [
        [t("intelligenceRole"), data.role],
        [t("company"), data.company],
        [t("location"), data.location],
        [t("intelligenceEmploymentType"), data.employmentType],
        [t("intelligenceSeniority"), data.seniority],
        [t("jobDetailsSalary"), data.salary],
      ]
    : [];

  return (
    <SectionShell
      title={t("workspaceAnalysis")}
      subtitle={t("intelligenceAnalysisSubtitle")}
      loading={loading}
      error={error}
    >
      <Stack spacing={2}>
        {data && !data.hasJobDescription && (
          <Alert severity="info" sx={{ borderRadius: 2 }}>
            {t("intelligenceNoAdvert")}
          </Alert>
        )}

        <Typography variant="body2">{data?.summary}</Typography>

        <Box sx={{ display: "grid", gridTemplateColumns: { xs: "1fr", sm: "160px 1fr" }, rowGap: 0.75, columnGap: 2 }}>
          {facts.map(([k, v]) => (
            <React.Fragment key={k}>
              <Typography variant="body2" color="text.secondary">{k}</Typography>
              <Typography variant="body2">{v ?? "—"}</Typography>
            </React.Fragment>
          ))}
        </Box>

        <Chips label={t("intelligenceTechnologies")} values={data?.technologies ?? []} />
        <Chips label={t("intelligenceSkills")} values={data?.skills ?? []} />
        <Bullets label={t("intelligenceRequirements")} values={data?.importantRequirements ?? []} />
        <Bullets label={t("intelligenceResponsibilities")} values={data?.responsibilities ?? []} />
        <Chips label={t("intelligenceInterviewTopics")} values={data?.interviewTopics ?? []} />
        <Bullets label={t("intelligenceNotStated")} values={data?.missingInformation ?? []} />
      </Stack>
    </SectionShell>
  );
}

// ---------- Match ----------

export function ApplicationMatch({ jobId }: { jobId: number }) {
  const { t } = useI18n();
  const { data, error, loading } = useIntelligence<CareerMatch>(
    () => applicationIntelligenceApi.match(jobId),
    [jobId],
  );

  return (
    <SectionShell
      title={t("workspaceCvMatch")}
      subtitle={data?.selectedCvName
        ? t("workspaceComparingCv", { name: data.selectedCvName })
        : t("workspaceSelectCvMatch")}
      loading={loading}
      error={error}
    >
      <Stack spacing={2}>
        {data && !data.hasSelectedCv ? (
          <Alert severity="info" sx={{ borderRadius: 2 }}>
            {t("workspaceSelectCvFirst")}
          </Alert>
        ) : data && !data.hasCareerProfile ? (
          <Alert severity="info" sx={{ borderRadius: 2 }}>
            {t("intelligenceCvProfileEmpty")}
          </Alert>
        ) : (
          <>
            <Box>
              <Stack direction="row" justifyContent="space-between" alignItems="baseline">
                <Typography variant="h4" sx={{ fontWeight: 900 }}>{data?.score}%</Typography>
                <Chip size="small" label={matchBandLabel(t, data?.band)} variant="outlined" />
              </Stack>
              <LinearProgress
                variant="determinate"
                value={data?.score ?? 0}
                aria-label={t("intelligenceMatchScore")}
                sx={{ mt: 1, height: 8, borderRadius: 4 }}
              />
            </Box>

            {data && !data.hasEnoughSignal && (
              <Alert severity="warning" sx={{ borderRadius: 2 }}>
                {t("intelligenceAdvertTooShort")}
              </Alert>
            )}

            {data?.languageMismatch && (
              <Alert severity={data.usedTranslatedJobDescription ? "info" : "warning"} sx={{ borderRadius: 2 }}>
                {t(data.usedTranslatedJobDescription
                  ? "intelligenceMatchUsedTranslation"
                  : "intelligenceMatchLanguageMismatch")}
              </Alert>
            )}

            <Chips label={t("intelligenceMatched")} values={data?.matchedSkills ?? []} color="success" />
            <Chips label={t("intelligenceMissing")} values={data?.missingSkills ?? []} color="warning" />

            {(data?.relevantExperience.length ?? 0) > 0 && (
              <Box>
                <Typography variant="caption" color="text.secondary" sx={{ fontWeight: 700 }}>
                  {t("intelligenceRelevantExperience")}
                </Typography>
                <Stack spacing={1} sx={{ mt: 0.5 }}>
                  {(data?.relevantExperience ?? []).map((e, i) => (
                    <Box key={i}>
                      <Typography variant="body2" sx={{ fontWeight: 600 }}>{e.title}</Typography>
                      {e.subtitle && <Typography variant="caption" color="text.secondary">{e.subtitle}</Typography>}
                      <Stack direction="row" flexWrap="wrap" gap={0.5} sx={{ mt: 0.5 }}>
                        {e.matched.map((k) => <Chip key={k} size="small" label={k} variant="outlined" />)}
                      </Stack>
                    </Box>
                  ))}
                </Stack>
              </Box>
            )}

            {(data?.relevantProjects.length ?? 0) > 0 && (
              <Box>
                <Typography variant="caption" color="text.secondary" sx={{ fontWeight: 700 }}>
                  {t("intelligenceRelevantProjects")}
                </Typography>
                <Stack spacing={1} sx={{ mt: 0.5 }}>
                  {(data?.relevantProjects ?? []).map((p, i) => (
                    <Box key={i}>
                      <Typography variant="body2" sx={{ fontWeight: 600 }}>{p.title}</Typography>
                      {p.subtitle && <Typography variant="caption" color="text.secondary">{p.subtitle}</Typography>}
                      <Stack direction="row" flexWrap="wrap" gap={0.5} sx={{ mt: 0.5 }}>
                        {p.matched.map((k) => <Chip key={k} size="small" label={k} variant="outlined" />)}
                      </Stack>
                    </Box>
                  ))}
                </Stack>
              </Box>
            )}
          </>
        )}

        <Bullets label={t("intelligenceSuggestions")} values={data?.suggestions ?? []} />
      </Stack>
    </SectionShell>
  );
}

function timelineCategoryLabel(t: (key: any) => string, category: string): string {
  const keys: Record<string, any> = {
    lifecycle: "intelligenceCategoryLifecycle",
    stage: "intelligenceCategoryStage",
    "follow-up": "intelligenceCategoryFollowUp",
    communication: "intelligenceCategoryCommunication",
    ai: "intelligenceCategoryAi",
  };
  return keys[category] ? t(keys[category]) : category;
}

function matchBandLabel(t: (key: any) => string, band?: string): string {
  if (!band) return t("matchScoreBand_Unknown");
  return ["Strong", "Partial", "Low", "Unknown"].includes(band)
    ? t(`matchScoreBand_${band}`)
    : band;
}
