import { useState } from "react";
import { motion, AnimatePresence } from "framer-motion";
import Box from "@mui/material/Box";
import Typography from "@mui/material/Typography";
import {
  Modal,
  ConfirmDialog,
  Field,
  TextField,
  Select,
  DateField,
  CheckboxField,
  Button,
  Card,
} from "../ui";
import useReducedMotion from "../hooks/useReducedMotion";
import {
  ResolvedCell,
  PlanCategory,
  planCategoryLabel,
  cellProjectLabel,
} from "../lib/queries/plan";
import { formatDate } from "../utils/formatters";

interface Project {
  id: number;
  name: string;
  project_number?: string;
}

export type PlanCellModalMode =
  | { kind: "closed" }
  | { kind: "create"; userId: number; date: string }
  | {
      kind: "edit-range";
      entryId: number;
      userId: number;
      date: string;
      range: {
        date_from: string;
        date_to: string;
        project_id: number | null;
        category: string;
        note: string;
      };
    }
  | {
      kind: "edit-override";
      overrideId: number;
      userId: number;
      date: string;
      cell: ResolvedCell;
    }
  | {
      kind: "day-in-range";
      entryId: number;
      userId: number;
      date: string;
      range: {
        date_from: string;
        date_to: string;
        project_id: number | null;
        category: string;
        note: string;
      };
    }
  | { kind: "view"; userId: number; date: string; cell: ResolvedCell };

interface Props {
  open: boolean;
  mode: PlanCellModalMode;
  projects: Project[];
  categories: PlanCategory[];
  onClose: () => void;
  onSaveEntry: (body: any) => Promise<void>;
  onUpdateEntry: (id: number, body: any) => Promise<void>;
  onDeleteEntry: (id: number) => Promise<void>;
  onSaveOverride: (body: any) => Promise<void>;
  onUpdateOverride: (id: number, body: any) => Promise<void>;
  onDeleteOverride: (id: number) => Promise<void>;
  onCreateOverrideFromRange: (
    entryId: number,
    userId: number,
    date: string,
  ) => Promise<void>;
  onSwitchToEditRange: (entryId: number, userId: number, date: string) => void;
}

const TrashIcon = (
  <svg
    width="14"
    height="14"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    strokeWidth="2"
    strokeLinecap="round"
    strokeLinejoin="round"
    aria-hidden
  >
    <polyline points="3 6 5 6 21 6" />
    <path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6" />
    <path d="M10 11v6" />
    <path d="M14 11v6" />
    <path d="M9 6V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2" />
  </svg>
);

export default function PlanCellModal(props: Props) {
  const { open, mode, onClose } = props;
  if (!open || mode.kind === "closed") return null;
  if (mode.kind === "view") return <ViewModal {...props} />;
  if (mode.kind === "day-in-range")
    return <DayInRangeModal {...props} mode={mode} />;
  return <EditForm {...props} />;
}

function EditForm(props: Props) {
  const {
    mode,
    onClose,
    onSaveEntry,
    onUpdateEntry,
    onDeleteEntry,
    onSaveOverride,
    onUpdateOverride,
    onDeleteOverride,
    projects,
  } = props;
  const [submitting, setSubmitting] = useState(false);
  const [confirmDelete, setConfirmDelete] = useState(false);

  // Narrow mode to the kinds EditForm actually handles. The call site in
  // PlanCellModal only passes "create" | "edit-range" | "edit-override" but
  // the parameter type is the full union, so we narrow explicitly here.
  if (
    mode.kind !== "create" &&
    mode.kind !== "edit-range" &&
    mode.kind !== "edit-override"
  ) {
    return null;
  }

  const isOverride = mode.kind === "edit-override";
  const activeCategories = props.categories.filter((c) => c.is_active);

  const initial = (() => {
    if (mode.kind === "create") {
      return {
        date_from: mode.date,
        date_to: mode.date,
        is_range: false,
        project_id: null as number | null,
        // Default to "work" when it's active, otherwise the first active
        // category, so a new entry never starts on a retired key.
        category: activeCategories.some((c) => c.key === "work")
          ? "work"
          : (activeCategories[0]?.key ?? "work"),
        note: "",
      };
    }
    if (mode.kind === "edit-range") {
      return {
        date_from: mode.range.date_from,
        date_to: mode.range.date_to,
        is_range: mode.range.date_from !== mode.range.date_to,
        project_id: mode.range.project_id,
        category: mode.range.category,
        note: mode.range.note,
      };
    }
    // mode.kind === "edit-override" (narrowed above)
    return {
      date_from: mode.date,
      date_to: mode.date,
      is_range: false,
      project_id: mode.cell.project_id,
      category: mode.cell.category,
      note: mode.cell.note,
    };
  })();

  const [dateFrom, setDateFrom] = useState(initial.date_from);
  const [dateTo, setDateTo] = useState(initial.date_to);
  const [isRange, setIsRange] = useState(initial.is_range);
  const [projectId, setProjectId] = useState<number | null>(initial.project_id);
  const [category, setCategory] = useState(initial.category);
  const [note, setNote] = useState(initial.note);

  const title =
    mode.kind === "create"
      ? "Nový záznam plánu"
      : mode.kind === "edit-range"
        ? "Upravit rozsah"
        : "Upravit přepsání dne";

  const handleSubmit = async () => {
    setSubmitting(true);
    try {
      if (mode.kind === "create") {
        const userId = mode.userId;
        await onSaveEntry({
          user_id: userId,
          date_from: dateFrom,
          date_to: isRange ? dateTo : dateFrom,
          project_id: projectId,
          category,
          note,
        });
      } else if (mode.kind === "edit-range") {
        await onUpdateEntry(mode.entryId, {
          date_from: dateFrom,
          date_to: isRange ? dateTo : dateFrom,
          project_id: projectId,
          category,
          note,
        });
      } else {
        await onUpdateOverride(mode.overrideId, {
          project_id: projectId,
          category,
          note,
        });
      }
      onClose();
    } finally {
      setSubmitting(false);
    }
  };

  const handleDelete = async () => {
    setSubmitting(true);
    try {
      if (mode.kind === "edit-range") {
        await onDeleteEntry(mode.entryId);
      } else if (mode.kind === "edit-override") {
        await onDeleteOverride(mode.overrideId);
      }
      onClose();
    } finally {
      setSubmitting(false);
    }
  };

  // If the row's current category was retired/hidden, still show it (marked)
  // so the select reflects reality instead of silently snapping to the first
  // active option. The server only re-checks the category if it changes, so
  // keeping it saves fine.
  const showRetiredCategory =
    category && !activeCategories.some((c) => c.key === category);

  return (
    <>
      <Modal
        isOpen
        title={title}
        onClose={onClose}
        onSubmit={handleSubmit}
        submitText={mode.kind === "create" ? "Vytvořit" : "Uložit"}
        loading={submitting}
      >
        {mode.kind !== "create" && (
          <Box sx={{ mb: 2 }}>
            <Button
              variant="outlined"
              color="error"
              startIcon={TrashIcon}
              onClick={() => setConfirmDelete(true)}
              disabled={submitting}
            >
              Smazat
            </Button>
          </Box>
        )}
        <Field label="Datum od">
          <DateField
            value={dateFrom}
            onChange={setDateFrom}
            disabled={isOverride}
          />
        </Field>
        {!isOverride && (
          <Field label="Rozsah dnů">
            <CheckboxField
              label="Více dní"
              checked={isRange}
              onChange={setIsRange}
            />
          </Field>
        )}
        {!isOverride && isRange && (
          <Field label="Datum do">
            <DateField value={dateTo} onChange={setDateTo} />
          </Field>
        )}
        <Field label="Projekt">
          <Select
            value={projectId === null ? "" : String(projectId)}
            onChange={(val) => setProjectId(val ? Number(val) : null)}
            options={[
              { value: "", label: "— bez projektu —" },
              ...projects.map((p) => ({
                value: String(p.id),
                label: p.name,
              })),
            ]}
          />
        </Field>
        <Field label="Kategorie">
          <Select
            value={category}
            onChange={(val) => setCategory(val)}
            options={[
              ...(showRetiredCategory
                ? [
                    {
                      value: category,
                      label: `${planCategoryLabel(
                        category,
                        Object.fromEntries(
                          props.categories.map((x) => [x.key, x]),
                        ),
                      )} (skrytá)`,
                    },
                  ]
                : []),
              ...activeCategories.map((c) => ({
                value: c.key,
                label: c.label,
              })),
            ]}
          />
        </Field>
        <Field label="Text poznámky (volitelný)">
          <TextField
            multiline
            minRows={3}
            value={note}
            onChange={(e) => setNote(e.target.value)}
            inputProps={{ maxLength: 500 }}
          />
        </Field>
      </Modal>

      <ConfirmDialog
        isOpen={confirmDelete}
        title="Smazat záznam plánu?"
        message="Tato akce je nevratná (záznam bude soft-delete)."
        confirmText="Smazat"
        confirmVariant="danger"
        loading={submitting}
        onClose={() => setConfirmDelete(false)}
        onConfirm={handleDelete}
      />
    </>
  );
}

function DayInRangeModal(
  props: Props & { mode: Extract<PlanCellModalMode, { kind: "day-in-range" }> },
) {
  const { mode, onClose, onCreateOverrideFromRange, onSwitchToEditRange } =
    props;
  const reducedMotion = useReducedMotion();

  // Two clear paths: edit the whole range (default, safe) or carve out
  // a one-day override (deviates from the plan). Close = no action.
  const choices = [
    {
      key: "edit-range",
      title: "Upravit celý rozsah",
      desc: `Změní projekt, kategorii nebo poznámku pro všechny dny v rozsahu ${mode.range.date_from} – ${mode.range.date_to}.`,
      tone: "primary" as const,
      onClick: () => onSwitchToEditRange(mode.entryId, mode.userId, mode.date),
      cta: "Upravit rozsah",
    },
    {
      key: "override-day",
      title: "Upravit pouze tento den",
      desc: `Vytvoří přepsání pro ${mode.range.date_from === mode.date ? "tento" : mode.date}; zbytek rozsahu zůstane beze změny.`,
      tone: "secondary" as const,
      onClick: async () => {
        await onCreateOverrideFromRange(mode.entryId, mode.userId, mode.date);
        onClose();
      },
      cta: "Vytvořit přepsání",
    },
  ];

  return (
    <Modal
      isOpen
      title="Den je součástí rozsahu"
      onClose={onClose}
      onSubmit={onClose}
      submitText="Zavřít — ponechat rozsah beze změny"
      maxWidth="md"
    >
      <Typography variant="body2" sx={{ mb: 2 }}>
        Den <strong>{mode.date}</strong> je součástí rozsahu{" "}
        <strong>
          {mode.range.date_from} – {mode.range.date_to}
        </strong>
        . Vyberte, co chcete udělat:
      </Typography>
      <Box sx={{ display: "flex", flexDirection: "column", gap: 1.5 }}>
        <AnimatePresence>
          {choices.map((c, i) => (
            <motion.div
              key={c.key}
              initial={reducedMotion ? false : { opacity: 0, y: 8 }}
              animate={{ opacity: 1, y: 0 }}
              exit={reducedMotion ? undefined : { opacity: 0, y: -4 }}
              transition={{
                duration: reducedMotion ? 0 : 0.22,
                delay: reducedMotion ? 0 : 0.04 + i * 0.05,
                ease: [0.16, 1, 0.3, 1],
              }}
            >
              <Card
                variant="outlined"
                sx={{
                  borderColor:
                    c.tone === "primary" ? "primary.main" : "divider",
                }}
              >
                <Box
                  sx={{
                    display: "flex",
                    alignItems: "center",
                    justifyContent: "space-between",
                    gap: 2,
                    flexWrap: "wrap",
                  }}
                >
                  <Box sx={{ flex: 1, minWidth: 200 }}>
                    <Typography sx={{ fontWeight: 600 }}>{c.title}</Typography>
                    <Typography variant="body2" color="text.secondary">
                      {c.desc}
                    </Typography>
                  </Box>
                  <Button
                    variant={c.tone === "primary" ? "contained" : "outlined"}
                    color={c.tone === "primary" ? "primary" : "inherit"}
                    onClick={c.onClick}
                  >
                    {c.cta}
                  </Button>
                </Box>
              </Card>
            </motion.div>
          ))}
        </AnimatePresence>
      </Box>
    </Modal>
  );
}

function ViewModal(props: Props) {
  const { mode, onClose, projects, categories } = props;
  if (mode.kind !== "view") return null;
  const c = mode.cell;
  // Prefer the server-embedded project label; fall back to the projects-list
  // lookup only for cells that predate the embed (stale cache).
  const fallback = c.project_id
    ? (projects.find((p) => p.id === c.project_id) ?? null)
    : null;
  const projectLabel =
    cellProjectLabel(c) ??
    (fallback
      ? fallback.project_number
        ? `${fallback.project_number} — ${fallback.name}`
        : fallback.name
      : null);
  return (
    <Modal
      isOpen
      title="Detail plánu"
      onClose={onClose}
      onSubmit={onClose}
      submitText="Zavřít"
      hideCancel
    >
      <Typography sx={{ mb: 1 }}>
        <strong>Datum:</strong> {formatDate(c.shift_date)}
      </Typography>
      <Typography sx={{ mb: 1 }}>
        <strong>Kategorie:</strong>{" "}
        {planCategoryLabel(
          c.category,
          Object.fromEntries(categories.map((x) => [x.key, x])),
        )}
      </Typography>
      <Typography sx={{ mb: 1 }}>
        <strong>Projekt:</strong> {projectLabel || "—"}
      </Typography>
      <Typography sx={{ mb: 1 }}>
        <strong>Text:</strong> {c.note || "—"}
      </Typography>
      {c.rangeFrom && c.rangeTo && (
        <Typography sx={{ mb: 1 }}>
          <strong>Patří do rozsahu:</strong> {formatDate(c.rangeFrom)} –{" "}
          {formatDate(c.rangeTo)}
        </Typography>
      )}
    </Modal>
  );
}
