import React, { useMemo, useState } from "react";

import {
  Box,
  Card,
  CardContent,
  IconButton,
  Menu,
  MenuItem,
  Paper,
  Typography,
} from "@mui/material";
import { alpha, useTheme } from "@mui/material/styles";
import MoreHorizIcon from "@mui/icons-material/MoreHoriz";

import { api } from "../api";
import ViewStateNotice from "./ViewStateNotice";
import { JobApplication } from "../types";
import { useI18n } from "../i18n/I18nProvider";
import { useViewResource } from "../hooks/useViewResource";
import { PIPELINE_STATUSES, PipelineStatus, normalizeStatus, statusLabel, statusTone } from "../pipeline";

const STATUSES = PIPELINE_STATUSES;
type Status = PipelineStatus;

const TONE_PALETTE: Record<string, (theme: any) => string> = {
  error: (theme) => theme.palette.error.main,
  warning: (theme) => theme.palette.warning.main,
  success: (theme) => theme.palette.success.main,
  info: (theme) => alpha(theme.palette.primary.main, 0.95),
  primary: (theme) => theme.palette.primary.main,
  default: (theme) => theme.palette.primary.main,
};

function toneColor(theme: any, status: Status | "Other"): string {
  return TONE_PALETTE[statusTone(status)](theme);
}

export default function KanbanBoard() {
  const theme = useTheme();
  const { t } = useI18n();
  const [dragJobId, setDragJobId] = useState<number | null>(null);
  const [menuAnchor, setMenuAnchor] = useState<null | HTMLElement>(null);
  const [menuJobId, setMenuJobId] = useState<number | null>(null);

  const jobsResource = useViewResource(
    async () => {
      const response = await api.get<JobApplication[]>("/jobapplications/board");
      return response.data;
    },
    {
      initialData: [],
      errorMessage: "Unable to load the board right now.",
      deps: [],
    },
  );

  const jobs = jobsResource.data;

  const groups = useMemo(() => {
    const map = new Map<string, JobApplication[]>();
    STATUSES.forEach((s) => map.set(s, []));
    map.set("Other", []);
    for (const j of jobs) {
      const key = normalizeStatus(j.status);
      map.get(key)!.push(j);
    }
    map.forEach((arr, k) => {
      arr.sort((a, b) => +new Date(b.dateApplied) - +new Date(a.dateApplied));
      map.set(k, arr);
    });
    return map;
  }, [jobs]);

  const onDropTo = async (status: Status) => {
    if (!dragJobId) return;
    setDragJobId(null);
    await api.patch(`/jobapplications/${dragJobId}/status`, { status });
    jobsResource.setData((prev) => prev.map((j) => (j.id === dragJobId ? { ...j, status } : j)));
  };

  const setStatus = async (id: number, status: Status) => {
    await api.patch(`/jobapplications/${id}/status`, { status });
    jobsResource.setData((prev) => prev.map((j) => (j.id === id ? { ...j, status } : j)));
  };

  const currentMenuStatus = menuJobId == null ? null : normalizeStatus(jobs.find((j) => j.id === menuJobId)?.status ?? "");

  return (
    <Box sx={{ mt: 2 }}>
      <Typography variant="body2" sx={{ color: "text.secondary", mb: 1 }}>
        {t("kanbanHint")}
      </Typography>

      <ViewStateNotice
        loading={jobsResource.loading}
        error={jobsResource.error}
        title="Unable to load the kanban board"
        description="The board could not reach the API."
        onRetry={jobsResource.reload}
      />

      {!jobsResource.loading && !jobsResource.error ? (
        <Box sx={{ display: "grid", gridTemplateColumns: { xs: "1fr", md: "repeat(3, 1fr)", xl: "repeat(6, 1fr)" }, gap: 2, alignItems: "start" }}>
          {STATUSES.map((status) => {
            const c = toneColor(theme, status);
            const list = groups.get(status) ?? [];
            return (
              <Paper
                key={status}
                onDragOver={(e) => e.preventDefault()}
                onDrop={() => void onDropTo(status)}
                sx={{
                  p: 1.5,
                  borderRadius: 3,
                  minHeight: 220,
                  border: "1px solid",
                  borderColor: "divider",
                  background: theme.palette.mode === "dark" ? alpha(theme.palette.common.white, 0.02) : alpha(theme.palette.text.primary, 0.015),
                }}
              >
                <Box sx={{ display: "flex", justifyContent: "space-between", alignItems: "center", mb: 1.25, px: 0.25 }}>
                  <Box sx={{ display: "flex", alignItems: "center", gap: 1 }}>
                    <Box sx={{ width: 9, height: 9, borderRadius: "50%", backgroundColor: c, flexShrink: 0 }} />
                    <Typography variant="subtitle1" sx={{ fontWeight: 800 }}>
                      {statusLabel(t, status)}
                    </Typography>
                  </Box>
                  <Typography variant="body2" sx={{ color: "text.secondary", fontWeight: 700 }}>
                    {list.length}
                  </Typography>
                </Box>

                <Box sx={{ display: "flex", flexDirection: "column", gap: 1 }}>
                  {list.map((j) => (
                    <Card
                      key={j.id}
                      draggable
                      onDragStart={() => setDragJobId(j.id)}
                      onDragEnd={() => setDragJobId(null)}
                      sx={{
                        cursor: "grab",
                        borderRadius: 2.5,
                        borderLeft: `4px solid ${c}`,
                        boxShadow: theme.palette.mode === "dark" ? "none" : "0 1px 3px rgba(15,23,42,0.06)",
                      }}
                    >
                      <CardContent sx={{ p: 1.25, "&:last-child": { pb: 1.25 } }}>
                        <Box sx={{ display: "flex", justifyContent: "space-between", gap: 1 }}>
                          <Typography sx={{ fontWeight: 800, lineHeight: 1.25 }}>
                            {j.jobTitle}
                          </Typography>
                          <IconButton
                            size="small"
                            onClick={(e) => {
                              e.stopPropagation();
                              setMenuJobId(j.id);
                              setMenuAnchor(e.currentTarget);
                            }}
                          >
                            <MoreHorizIcon fontSize="small" />
                          </IconButton>
                        </Box>
                        <Typography variant="body2" sx={{ color: "text.secondary" }}>
                          {[j.company?.name, j.location].filter(Boolean).join(" · ")}
                        </Typography>
                        <Typography variant="body2" sx={{ color: "text.secondary", mt: 0.75 }}>
                          {j.daysSince}d
                        </Typography>
                      </CardContent>
                    </Card>
                  ))}
                  {list.length === 0 && (
                    <Typography variant="body2" sx={{ color: "text.secondary", py: 1 }}>
                      {t("kanbanDropHere")}
                    </Typography>
                  )}
                </Box>
              </Paper>
            );
          })}
        </Box>
      ) : null}

      <Menu anchorEl={menuAnchor} open={Boolean(menuAnchor)} onClose={() => { setMenuAnchor(null); setMenuJobId(null); }}>
        {(["Applied", "Waiting", "Interview", "Offer", "Rejected", "Ghosted"] as const)
          .filter((s) => s !== currentMenuStatus)
          .map((s) => (
            <MenuItem key={s} onClick={() => { if (menuJobId) void setStatus(menuJobId, s); setMenuAnchor(null); setMenuJobId(null); }}>
              {t("jobTableSetStatus", { status: statusLabel(t, s) })}
            </MenuItem>
          ))}
      </Menu>
    </Box>
  );
}
