import { useMutation } from "@tanstack/react-query";
import { addWeeks, format } from "date-fns";
import { useEffect, useState } from "react";

import { createAllocation, deleteAllocation, updateAllocation } from "../../api/allocations";
import { formatHoursPerDay } from "../../planner/allocationTimeline";
import { Modal } from "../ui/Modal";
import { toastFromError, useToast } from "../ui/Toast";
import type { Allocation, Person, Project } from "../../types";

interface AddProjectMemberModalProps {
  open: boolean;
  project: Project | null;
  people: Person[];
  allocation: Allocation | null;
  assignedPersonIds: number[];
  onClose: () => void;
  onSaved: () => void;
}

export function AddProjectMemberModal({
  open,
  project,
  people,
  allocation,
  assignedPersonIds,
  onClose,
  onSaved,
}: AddProjectMemberModalProps) {
  const { push } = useToast();
  const [personId, setPersonId] = useState<number | "">("");
  const [startDate, setStartDate] = useState("");
  const [endDate, setEndDate] = useState("");
  const [allocationPct, setAllocationPct] = useState(50);

  useEffect(() => {
    if (!open || !project) return;
    if (allocation) {
      setPersonId(allocation.person_id);
      setStartDate(allocation.start_date);
      setEndDate(allocation.end_date);
      setAllocationPct(allocation.allocation_pct);
      return;
    }
    const available = people.find((person) => !assignedPersonIds.includes(person.id));
    setPersonId(available?.id ?? "");
    setStartDate(format(new Date(), "yyyy-MM-dd"));
    setEndDate(format(addWeeks(new Date(), 1), "yyyy-MM-dd"));
    setAllocationPct(50);
  }, [open, project, allocation, people, assignedPersonIds]);

  const createMutation = useMutation({
    mutationFn: createAllocation,
    onSuccess: () => {
      push("Developer added to project", "success");
      onSaved();
      onClose();
    },
    onError: (error) => push(toastFromError(error, "Could not add developer"), "error"),
  });

  const updateMutation = useMutation({
    mutationFn: ({ id, input }: { id: number; input: { start_date: string; end_date: string; allocation_pct: number } }) =>
      updateAllocation(id, input),
    onSuccess: () => {
      push("Allocation updated", "success");
      onSaved();
      onClose();
    },
    onError: (error) => push(toastFromError(error, "Could not update allocation"), "error"),
  });

  const deleteMutation = useMutation({
    mutationFn: deleteAllocation,
    onSuccess: () => {
      push("Developer removed from project", "success");
      onSaved();
      onClose();
    },
    onError: (error) => push(toastFromError(error, "Could not remove developer"), "error"),
  });

  const isSaving = createMutation.isPending || updateMutation.isPending || deleteMutation.isPending;

  const availablePeople = allocation
    ? people.filter((person) => person.id === allocation.person_id)
    : people.filter((person) => !assignedPersonIds.includes(person.id));

  const handleSave = () => {
    if (!project || personId === "") return;
    if (allocation) {
      updateMutation.mutate({
        id: allocation.id,
        input: { start_date: startDate, end_date: endDate, allocation_pct: allocationPct },
      });
      return;
    }
    createMutation.mutate({
      person_id: Number(personId),
      project_id: project.id,
      start_date: startDate,
      end_date: endDate,
      allocation_pct: allocationPct,
    });
  };

  return (
    <Modal
      open={open && project !== null}
      onClose={onClose}
      size="md"
      title={allocation ? "Edit assignment" : `Add person — ${project?.name ?? ""}`}
      footer={
        <>
          {allocation ? (
            <button
              className="ghost-button danger"
              disabled={isSaving}
              onClick={() => {
                if (window.confirm("Remove this person from the project?")) {
                  deleteMutation.mutate(allocation.id);
                }
              }}
              type="button"
            >
              Remove
            </button>
          ) : null}
          <span style={{ flex: 1 }} />
          <button className="secondary-button" onClick={onClose} type="button">
            Cancel
          </button>
          <button
            className="primary-button"
            disabled={isSaving || personId === "" || !startDate || !endDate}
            onClick={handleSave}
            type="button"
          >
            Save
          </button>
        </>
      }
    >
      {!project ? null : (
        <div className="form-grid">
          <label className="span-2">
            Person
            <select
              disabled={!!allocation}
              onChange={(event) => setPersonId(event.target.value ? Number(event.target.value) : "")}
              value={personId}
            >
              <option value="">Select developer</option>
              {availablePeople.map((person) => (
                <option key={person.id} value={person.id}>
                  {person.name} — {person.role.name}
                </option>
              ))}
            </select>
          </label>
          <label>
            Start date
            <input onChange={(event) => setStartDate(event.target.value)} type="date" value={startDate} />
          </label>
          <label>
            End date
            <input onChange={(event) => setEndDate(event.target.value)} type="date" value={endDate} />
          </label>
          <label className="span-2">
            Allocation
            <div className="row gap">
              <input
                max={100}
                min={5}
                onChange={(event) => setAllocationPct(Number(event.target.value))}
                step={5}
                type="range"
                value={allocationPct}
              />
              <span className="badge">{allocationPct}%</span>
              {personId !== "" ? (
                <span className="muted-text">
                  {formatHoursPerDay(
                    allocationPct,
                    people.find((person) => person.id === Number(personId))?.weekly_capacity_hrs ?? 40,
                  )}
                </span>
              ) : null}
            </div>
          </label>
        </div>
      )}
    </Modal>
  );
}
