import {
  useEffect,
  useState
} from "react";

import {
  useNavigate,
  useOutletContext
} from "react-router-dom";

import {
  getDependents,
  saveDependents
} from "../../../services/publicPortalService";

const createEmptyDependent = () => ({
  full_name: "",
  date_of_birth: "",
  relationship: "",
  gender: "",
  occupation_or_school: ""
});

const relationshipOptions = [
  "Spouse",
  "Son",
  "Daughter",
  "Father",
  "Mother",
  "Brother",
  "Sister",
  "Ward",
  "Other"
];

const Dependents = () => {
  const navigate =
    useNavigate();

  const {
    refreshProgress
  } = useOutletContext();

  const [
    hasDependents,
    setHasDependents
  ] = useState(false);

  const [
    dependents,
    setDependents
  ] = useState([]);

  const [loading, setLoading] =
    useState(true);

  const [saving, setSaving] =
    useState(false);

  const [editable, setEditable] =
    useState(true);

  const [error, setError] =
    useState("");

  const [
    successMessage,
    setSuccessMessage
  ] = useState("");

  const [
    fieldErrors,
    setFieldErrors
  ] = useState({});

  useEffect(() => {
    const loadDependents =
      async () => {
        try {
          setLoading(true);
          setError("");

          const result =
            await getDependents();

          const savedSummary =
            result.data.summary;

          const savedDependents =
            result.data.dependents || [];

          setEditable(
            result.data.editable
          );

          setHasDependents(
            Boolean(
              savedSummary
                ?.has_dependents
            )
          );

          setDependents(
            savedDependents.map(
              (dependent) => ({
                full_name:
                  dependent.full_name ||
                  "",

                date_of_birth:
                  dependent
                    .date_of_birth ||
                  "",

                relationship:
                  dependent
                    .relationship ||
                  "",

                gender:
                  dependent.gender ||
                  "",

                occupation_or_school:
                  dependent
                    .occupation_or_school ||
                  ""
              })
            )
          );
        } catch (requestError) {
          setError(
            requestError.response?.data
              ?.message ||
              requestError.message ||
              "Unable to load dependents."
          );
        } finally {
          setLoading(false);
        }
      };

    loadDependents();
  }, []);

  const clearMessages = () => {
    if (error) {
      setError("");
    }

    if (successMessage) {
      setSuccessMessage("");
    }
  };

  const handleHasDependentsChange = (
    event
  ) => {
    const value =
      event.target.value === "yes";

    setHasDependents(value);

    if (
      value &&
      dependents.length === 0
    ) {
      setDependents([
        createEmptyDependent()
      ]);
    }

    if (!value) {
      setDependents([]);
    }

    setFieldErrors({});
    clearMessages();
  };

  const handleDependentChange = (
    index,
    event
  ) => {
    const {
      name,
      value
    } = event.target;

    setDependents(
      (currentDependents) =>
        currentDependents.map(
          (
            dependent,
            dependentIndex
          ) =>
            dependentIndex === index
              ? {
                  ...dependent,
                  [name]: value
                }
              : dependent
        )
    );

    setFieldErrors(
      (currentErrors) => {
        const nextErrors = {
          ...currentErrors
        };

        delete nextErrors[
          `dependent_${index + 1}`
        ];

        return nextErrors;
      }
    );

    clearMessages();
  };

  const addDependent = () => {
    if (
      dependents.length >= 20
    ) {
      setError(
        "A maximum of 20 dependents may be added."
      );

      return;
    }

    setDependents(
      (currentDependents) => [
        ...currentDependents,
        createEmptyDependent()
      ]
    );

    setHasDependents(true);
    clearMessages();
  };

  const removeDependent = (
    index
  ) => {
    setDependents(
      (currentDependents) =>
        currentDependents.filter(
          (
            dependent,
            dependentIndex
          ) =>
            dependentIndex !== index
        )
    );

    setFieldErrors({});
    clearMessages();
  };

  const submitDependents =
    async ({
      markCompleted
    }) => {
      try {
        setSaving(true);
        setError("");
        setSuccessMessage("");
        setFieldErrors({});

        const result =
          await saveDependents({
            has_dependents:
              hasDependents,

            dependents,

            mark_completed:
              markCompleted
          });

        setSuccessMessage(
          result.message
        );

        await refreshProgress();

        if (markCompleted) {
          navigate(
            "/staff/form/emergency-contact"
          );
        }
      } catch (requestError) {
        const responseData =
          requestError.response?.data;

        setError(
          responseData?.message ||
            requestError.message ||
            "Unable to save dependents."
        );

        setFieldErrors(
          responseData?.errors || {}
        );
      } finally {
        setSaving(false);
      }
    };

  if (loading) {
    return (
      <div className="form-page-card">
        <div className="information-banner">
          Loading dependents...
        </div>
      </div>
    );
  }

  return (
    <div className="form-page-card">
      <div className="form-page-heading">
        <div>
          <span>
            Section C
          </span>

          <h2>
            Details of Dependents
          </h2>

          <p>
            Provide details of your spouse,
            children or other recognised
            dependents.
          </p>
        </div>

        <span className="form-step-badge">
          Step 4 of 8
        </span>
      </div>

      {!editable && (
        <div className="form-alert form-alert--error">
          This submission is no longer
          editable.
        </div>
      )}

      {error && (
        <div
          className="form-alert form-alert--error"
          role="alert"
        >
          {error}
        </div>
      )}

      {successMessage && (
        <div className="form-alert form-alert--success">
          {successMessage}
        </div>
      )}

      <div className="form-group">
        <label htmlFor="has_dependents">
          Do you have any dependents?
          <span className="required-mark">
            *
          </span>
        </label>

        <select
          id="has_dependents"
          value={
            hasDependents
              ? "yes"
              : "no"
          }
          onChange={
            handleHasDependentsChange
          }
          disabled={
            saving ||
            !editable
          }
        >
          <option value="no">
            No
          </option>

          <option value="yes">
            Yes
          </option>
        </select>
      </div>

      {fieldErrors.dependents && (
        <div className="field-error dependents-general-error">
          {fieldErrors.dependents}
        </div>
      )}

      {hasDependents && (
        <div className="dependents-list">
          {dependents.map(
            (
              dependent,
              index
            ) => {
              const rowErrors =
                fieldErrors[
                  `dependent_${index + 1}`
                ] || {};

              return (
                <article
                  className="dependent-card"
                  key={`dependent-${index}`}
                >
                  <div className="dependent-card__header">
                    <div>
                      <span>
                        Dependent
                      </span>

                      <h3>
                        Dependent{" "}
                        {index + 1}
                      </h3>
                    </div>

                    <button
                      type="button"
                      className="danger-text-button"
                      onClick={() =>
                        removeDependent(
                          index
                        )
                      }
                      disabled={
                        saving ||
                        !editable
                      }
                    >
                      Remove
                    </button>
                  </div>

                  <div className="form-grid form-grid--two">
                    <div className="form-group">
                      <label
                        htmlFor={`dependent-full-name-${index}`}
                      >
                        Full Name
                        <span className="required-mark">
                          *
                        </span>
                      </label>

                      <input
                        id={`dependent-full-name-${index}`}
                        name="full_name"
                        type="text"
                        value={
                          dependent
                            .full_name
                        }
                        onChange={(
                          event
                        ) =>
                          handleDependentChange(
                            index,
                            event
                          )
                        }
                        maxLength={150}
                        disabled={
                          saving ||
                          !editable
                        }
                      />

                      {rowErrors.full_name && (
                        <small className="field-error">
                          {
                            rowErrors.full_name
                          }
                        </small>
                      )}
                    </div>

                    <div className="form-group">
                      <label
                        htmlFor={`dependent-relationship-${index}`}
                      >
                        Relationship
                        <span className="required-mark">
                          *
                        </span>
                      </label>

                      <select
                        id={`dependent-relationship-${index}`}
                        name="relationship"
                        value={
                          dependent
                            .relationship
                        }
                        onChange={(
                          event
                        ) =>
                          handleDependentChange(
                            index,
                            event
                          )
                        }
                        disabled={
                          saving ||
                          !editable
                        }
                      >
                        <option value="">
                          Select relationship
                        </option>

                        {relationshipOptions.map(
                          (
                            relationship
                          ) => (
                            <option
                              key={
                                relationship
                              }
                              value={
                                relationship
                              }
                            >
                              {
                                relationship
                              }
                            </option>
                          )
                        )}
                      </select>

                      {rowErrors.relationship && (
                        <small className="field-error">
                          {
                            rowErrors.relationship
                          }
                        </small>
                      )}
                    </div>
                  </div>

                  <div className="form-grid form-grid--two">
                    <div className="form-group">
                      <label
                        htmlFor={`dependent-dob-${index}`}
                      >
                        Date of Birth
                      </label>

                      <input
                        id={`dependent-dob-${index}`}
                        name="date_of_birth"
                        type="date"
                        value={
                          dependent
                            .date_of_birth
                        }
                        onChange={(
                          event
                        ) =>
                          handleDependentChange(
                            index,
                            event
                          )
                        }
                        max={
                          new Date()
                            .toISOString()
                            .split(
                              "T"
                            )[0]
                        }
                        disabled={
                          saving ||
                          !editable
                        }
                      />

                      {rowErrors.date_of_birth && (
                        <small className="field-error">
                          {
                            rowErrors.date_of_birth
                          }
                        </small>
                      )}
                    </div>

                    <div className="form-group">
                      <label
                        htmlFor={`dependent-gender-${index}`}
                      >
                        Gender
                      </label>

                      <select
                        id={`dependent-gender-${index}`}
                        name="gender"
                        value={
                          dependent.gender
                        }
                        onChange={(
                          event
                        ) =>
                          handleDependentChange(
                            index,
                            event
                          )
                        }
                        disabled={
                          saving ||
                          !editable
                        }
                      >
                        <option value="">
                          Select gender
                        </option>

                        <option value="male">
                          Male
                        </option>

                        <option value="female">
                          Female
                        </option>
                      </select>

                      {rowErrors.gender && (
                        <small className="field-error">
                          {
                            rowErrors.gender
                          }
                        </small>
                      )}
                    </div>
                  </div>

                  <div className="form-group">
                    <label
                      htmlFor={`dependent-occupation-${index}`}
                    >
                      Occupation / School
                    </label>

                    <input
                      id={`dependent-occupation-${index}`}
                      name="occupation_or_school"
                      type="text"
                      value={
                        dependent
                          .occupation_or_school
                      }
                      onChange={(
                        event
                      ) =>
                        handleDependentChange(
                          index,
                          event
                        )
                      }
                      maxLength={180}
                      placeholder="Enter occupation or name of school"
                      disabled={
                        saving ||
                        !editable
                      }
                    />
                  </div>
                </article>
              );
            }
          )}

          <button
            type="button"
            className="add-dependent-button"
            onClick={addDependent}
            disabled={
              saving ||
              !editable ||
              dependents.length >= 20
            }
          >
            + Add another dependent
          </button>
        </div>
      )}

      {!hasDependents && (
        <div className="information-banner dependents-empty-message">
          You have selected that you have no
          dependents. You may save and continue
          to the next section.
        </div>
      )}

      <div className="form-action-bar">
        <button
          type="button"
          className="secondary-button"
          onClick={() =>
            navigate(
              "/staff/form/next-of-kin"
            )
          }
          disabled={saving}
        >
          Previous
        </button>

        <button
          type="button"
          className="secondary-button"
          onClick={() =>
            submitDependents({
              markCompleted: false
            })
          }
          disabled={
            saving ||
            !editable
          }
        >
          {saving
            ? "Saving..."
            : "Save draft"}
        </button>

        <button
          type="button"
          className="primary-button"
          onClick={() =>
            submitDependents({
              markCompleted: true
            })
          }
          disabled={
            saving ||
            !editable
          }
        >
          {saving
            ? "Saving..."
            : "Save and continue"}
        </button>
      </div>
    </div>
  );
};

export default Dependents;