import { useState } from "react";
import { motion, AnimatePresence } from "framer-motion";
import FormModal from "./FormModal";
import FormField from "./FormField";
import AdminDatePicker from "./AdminDatePicker";
import ConfirmModal from "./ConfirmModal";
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;
}

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);
    }
  };

  return (
    <>
      <FormModal
        isOpen
        title={title}
        onClose={onClose}
        onSubmit={handleSubmit}
        submitLabel={mode.kind === "create" ? "Vytvořit" : "Uložit"}
        loading={submitting}
        footerLeft={
          mode.kind !== "create" ? (
            <button
              type="button"
              className="admin-btn admin-btn-secondary"
              onClick={() => setConfirmDelete(true)}
              disabled={submitting}
            >
              <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>
              Smazat
            </button>
          ) : null
        }
      >
        <FormField label="Datum od">
          <AdminDatePicker
            value={dateFrom}
            onChange={setDateFrom}
            disabled={isOverride}
          />
        </FormField>
        {!isOverride && (
          <FormField label="Rozsah dnů">
            <label className="admin-form-checkbox">
              <input
                type="checkbox"
                checked={isRange}
                onChange={(e) => setIsRange(e.target.checked)}
              />
              <span>Více dní</span>
            </label>
          </FormField>
        )}
        {!isOverride && isRange && (
          <FormField label="Datum do">
            <AdminDatePicker value={dateTo} onChange={setDateTo} />
          </FormField>
        )}
        <FormField label="Projekt">
          <select
            className="admin-form-select"
            value={projectId ?? ""}
            onChange={(e) =>
              setProjectId(e.target.value ? Number(e.target.value) : null)
            }
          >
            <option value="">— bez projektu —</option>
            {projects.map((p) => (
              <option key={p.id} value={p.id}>
                {p.name}
              </option>
            ))}
          </select>
        </FormField>
        <FormField label="Kategorie">
          <select
            className="admin-form-select"
            value={category}
            onChange={(e) => setCategory(e.target.value)}
          >
            {/* 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. */}
            {category && !activeCategories.some((c) => c.key === category) && (
              <option value={category}>
                {planCategoryLabel(
                  category,
                  Object.fromEntries(props.categories.map((x) => [x.key, x])),
                )}{" "}
                (skrytá)
              </option>
            )}
            {activeCategories.map((c) => (
              <option key={c.key} value={c.key}>
                {c.label}
              </option>
            ))}
          </select>
        </FormField>
        <FormField label="Text poznámky (volitelný)">
          <textarea
            className="admin-form-textarea"
            value={note}
            onChange={(e) => setNote(e.target.value)}
            maxLength={500}
            rows={3}
          />
        </FormField>
      </FormModal>

      <ConfirmModal
        isOpen={confirmDelete}
        title="Smazat záznam plánu?"
        message="Tato akce je nevratná (záznam bude soft-delete)."
        confirmText="Smazat"
        type="danger"
        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 (
    <FormModal
      isOpen
      title="Den je součástí rozsahu"
      onClose={onClose}
      hideFooter
      size="md"
    >
      <p className="plan-modal-intro">
        Den <strong>{mode.date}</strong> je součástí rozsahu{" "}
        <strong>
          {mode.range.date_from} – {mode.range.date_to}
        </strong>
        . Vyberte, co chcete udělat:
      </p>
      <ul className="plan-choices">
        <AnimatePresence>
          {choices.map((c, i) => (
            <motion.li
              key={c.key}
              className={`plan-choice plan-choice-${c.tone}`}
              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],
              }}
            >
              <div className="plan-choice-body">
                <div className="plan-choice-title">{c.title}</div>
                <div className="plan-choice-desc">{c.desc}</div>
              </div>
              <button
                type="button"
                className={
                  c.tone === "primary"
                    ? "admin-btn admin-btn-primary"
                    : "admin-btn admin-btn-secondary"
                }
                onClick={c.onClick}
              >
                {c.cta}
              </button>
            </motion.li>
          ))}
        </AnimatePresence>
      </ul>
      <div className="plan-modal-actions plan-modal-actions--solo">
        <button
          type="button"
          className="admin-btn admin-btn-secondary"
          onClick={onClose}
        >
          Zavřít — ponechat rozsah beze změny
        </button>
      </div>
    </FormModal>
  );
}

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 (
    <FormModal isOpen title="Detail plánu" onClose={onClose} hideFooter>
      <p>
        <strong>Datum:</strong> {formatDate(c.shift_date)}
      </p>
      <p>
        <strong>Kategorie:</strong>{" "}
        {planCategoryLabel(
          c.category,
          Object.fromEntries(categories.map((x) => [x.key, x])),
        )}
      </p>
      <p>
        <strong>Projekt:</strong> {projectLabel || "—"}
      </p>
      <p>
        <strong>Text:</strong> {c.note || "—"}
      </p>
      {c.rangeFrom && c.rangeTo && (
        <p>
          <strong>Patří do rozsahu:</strong> {formatDate(c.rangeFrom)} –{" "}
          {formatDate(c.rangeTo)}
        </p>
      )}
    </FormModal>
  );
}
