import { Formik, Field, Form } from "formik";
import type { CameraConfig, CameraSettingErrorValues, CameraSettingValues, ZoomInOptions } from "../../types/types";
import { useEffect, useMemo, useState } from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faEye, faEyeSlash } from "@fortawesome/free-regular-svg-icons";
import CardHeader from "../UI/CardHeader";
import { useCameraMode, useCameraZoom } from "../../hooks/useCameraZoom";
import { parseRTSPUrl, reverseZoomMapping, zoomMapping } from "../../utils/utils";

type CameraSettingsProps = {
  initialData: CameraConfig;
  updateCameraConfig: (values: CameraSettingValues) => Promise<void> | void;
  zoomLevel?: number;
  onZoomLevelChange?: (level: number | undefined) => void;
  updateCameraConfigError: null | Error;
};

const CameraSettingFields = ({
  initialData,
  updateCameraConfig,
  zoomLevel,
  onZoomLevelChange,
}: CameraSettingsProps) => {
  const [showPwd, setShowPwd] = useState(false);

  const cameraControllerSide = initialData?.id === "CameraA" ? "CameraControllerA" : "CameraControllerB";
  const { mutation, query } = useCameraZoom({ camera: cameraControllerSide });
  const { cameraModeQuery, cameraModeMutation } = useCameraMode({ camera: cameraControllerSide });
  const zoomOptions = [1, 2, 4];
  const magnification = query?.data?.propMagnification?.value;
  const apiZoom = reverseZoomMapping(magnification);
  const parsed = parseRTSPUrl(initialData?.propURI?.value);
  const cameraMode = cameraModeQuery?.data?.propDayNightMode?.value;

  useEffect(() => {
    if (!query?.data) return;
    onZoomLevelChange?.(apiZoom);
  }, [query?.data, onZoomLevelChange, apiZoom]);

  const initialValues = useMemo<CameraSettingValues>(
    () => ({
      friendlyName: initialData?.id ?? "",
      cameraAddress: initialData?.propURI?.value ?? "",
      userName: parsed?.username ?? "",
      password: parsed?.password ?? "",
      id: initialData?.id,
      mode: cameraMode ?? "day",
      zoom: apiZoom,
    }),

    [initialData?.id, initialData?.propURI?.value, parsed?.username, parsed?.password, cameraMode, apiZoom]
  );

  const validateValues = (values: CameraSettingValues) => {
    const errors: CameraSettingErrorValues = {};
    if (!values.friendlyName) errors.friendlyName = "Required";
    if (!values.cameraAddress) errors.cameraAddress = "Required";
    return errors;
  };

  const handleSubmit = (values: CameraSettingValues) => {
    updateCameraConfig(values);
  };

  const handleRadioButtonChange = async (levelNumber: number) => {
    if (!onZoomLevelChange || !zoomLevel) return;
    const text = zoomMapping(levelNumber);
    onZoomLevelChange(levelNumber);

    const zoomInOptions: ZoomInOptions = {
      camera: cameraControllerSide,
      multiplier: levelNumber,
      multiplierText: text,
    };

    mutation.mutate(zoomInOptions);
  };

  const selectedZoom = zoomLevel ?? 1;
  return (
    <Formik
      initialValues={initialValues}
      onSubmit={handleSubmit}
      validate={validateValues}
      validateOnChange={false}
      enableReinitialize
    >
      {({ errors, touched, values, setFieldValue, isSubmitting }) => (
        <Form className="flex flex-col space-y-6 p-2 overflow-x-hidden">
          <div className="flex flex-col space-y-2 relative">
            <label htmlFor="friendlyName">Name</label>
            {touched.friendlyName && errors.friendlyName && (
              <small className="absolute right-0 top-0 text-red-500">{errors.friendlyName}</small>
            )}
            <Field
              id="friendlyName"
              name="friendlyName"
              type="text"
              className="p-2 border border-gray-400 rounded-lg"
              placeholder="Enter camera name"
            />
          </div>

          <div className="flex flex-col space-y-2 relative">
            <label htmlFor="cameraAddress">Camera Address</label>
            {touched.cameraAddress && errors.cameraAddress && (
              <small className="absolute right-0 top-0 text-red-500">{errors.cameraAddress}</small>
            )}
            <Field
              id="cameraAddress"
              name="cameraAddress"
              type="text"
              className="p-2 border border-gray-400 rounded-lg"
              placeholder="RTSP://..."
            />
          </div>

          <div className="flex flex-col space-y-2 relative">
            <label htmlFor="userName">User Name</label>
            {touched.userName && errors.userName && (
              <small className="absolute right-0 top-0 text-red-500">{errors.userName}</small>
            )}
            <Field
              id="userName"
              name="userName"
              type="text"
              className="p-2 border border-gray-400 rounded-lg"
              placeholder="Enter user name"
              autoComplete="username"
            />
          </div>

          <div className="flex flex-col space-y-2 relative">
            <label htmlFor="password">Password</label>
            {touched.password && errors.password && (
              <small className="absolute right-0 top-0 text-red-500">{errors.password}</small>
            )}
            <div className="flex gap-2 items-center relative mb-4">
              <Field
                id="password"
                name="password"
                type={showPwd ? "text" : "password"}
                className="p-2 border border-gray-400 rounded-lg w-full "
                placeholder="Enter password"
              />
              <FontAwesomeIcon
                type="button"
                className="absolute right-5 end-0"
                onClick={() => setShowPwd((s) => !s)}
                icon={showPwd ? faEyeSlash : faEye}
              />
            </div>
            <div className="my-3">
              <CardHeader title="Zoom settings" />
              <div className="mx-auto grid grid-cols-3 place-items-center">
                {zoomOptions.map((zoom) => (
                  <div key={zoom} className="my-3">
                    <Field
                      type="radio"
                      name="zoom"
                      value={zoom.toString()}
                      checked={selectedZoom === zoom}
                      className="hidden peer"
                      id={`zoom${zoom}`}
                      onChange={() => handleRadioButtonChange(zoom)}
                    />
                    <label
                      htmlFor={`zoom${zoom}`}
                      className="px-6 py-2 rounded-md border border-gray-300 
                   peer-checked:border-2 peer-checked:border-blue-900  
                   peer-checked:text-blue-600 peer-checked:bg-gray-100"
                    >
                      {zoomMapping(zoom)}
                    </label>
                  </div>
                ))}
              </div>
            </div>
            <div>
              <CardHeader title="Mode" />
              <div
                role="radiogroup"
                aria-label="Camera mode"
                className="mx-auto grid grid-cols-2 place-items-center gap-3"
              >
                {["day", "night"].map((el) => (
                  <div key={el} className="my-3">
                    <Field
                      type="radio"
                      name="mode"
                      value={el}
                      checked={values.mode === el}
                      id={`mode-${el}`}
                      className="peer hidden"
                      disabled={cameraModeMutation.isPending}
                      onChange={async () => {
                        setFieldValue("mode", el);
                        await cameraModeMutation.mutateAsync({ camera: cameraControllerSide, mode: el });
                      }}
                    />
                    <label
                      htmlFor={`mode-${el}`}
                      className={`px-8 py-2 rounded-md border border-gray-300
                peer-checked:border-2 peer-checked:border-blue-900
                peer-checked:text-blue-600 peer-checked:bg-gray-100
                ${cameraModeMutation.isPending ? "opacity-60 cursor-not-allowed" : "cursor-pointer"}`}
                    >
                      {el === "day" ? "Day" : "Night"}
                    </label>
                  </div>
                ))}
              </div>
            </div>
            <div className="mt-3">
              {
                <button type="submit" className="bg-green-700 text-white rounded-lg p-2 mx-auto w-full">
                  {isSubmitting ? "Saving" : "Save settings"}
                </button>
              }
            </div>
          </div>
        </Form>
      )}
    </Formik>
  );
};

export default CameraSettingFields;
