import { Form, Formik } from "formik";
import BearerTypeCard from "../BearerType/BearerTypeCard";
import ChannelCard from "../Channel1-JSON/ChannelCard";
import { useCameraOutput, useGetDispatcherConfig } from "../../../hooks/useCameraOutput";
import type {
  BearerTypeFieldType,
  InitialValuesForm,
  InitialValuesFormErrors,
  OptionalBOF2Constants,
  OptionalBOF2LaneIDs,
} from "../../../types/types";
import { useQueryClient } from "@tanstack/react-query";
import { useUpdateBackOfficeConfig } from "../../../hooks/useBackOfficeConfig";
import { useFormVaidate } from "../../../hooks/useFormValidate";
import { useSightingAmend } from "../../../hooks/useSightingAmend";
import StoreCard from "../Store/StoreCard";

const SettingForms = () => {
  const qc = useQueryClient();
  const { dispatcherQuery, dispatcherMutation, backOfficeDispatcherMutation, bof2LandMutation, laneIdQuery } =
    useCameraOutput();
  const { backOfficeMutation } = useUpdateBackOfficeConfig();
  const { bof2ConstantsQuery } = useGetDispatcherConfig();
  const { validateMutation } = useFormVaidate();
  const { sightingAmendQuery, sightingAmendMutation } = useSightingAmend();

  const format = dispatcherQuery?.data?.propFormat?.value;
  const enabled = dispatcherQuery?.data?.propEnabled?.value;

  const sightingQuality = sightingAmendQuery?.data?.propOverviewQuality?.value;
  const cropSizeFactor = sightingAmendQuery?.data?.propOverviewImageScaleFactor?.value;

  const laneID = laneIdQuery?.data?.id;
  const LID1 = laneIdQuery?.data?.propLaneID1?.value;
  const LID2 = laneIdQuery?.data?.propLaneID2?.value;

  const FFID = bof2ConstantsQuery?.data?.propFeedIdentifier?.value;
  const SCID = bof2ConstantsQuery?.data?.propSourceIdentifier?.value;
  const GPSFormat = bof2ConstantsQuery?.data?.propGpsFormat?.value;
  const timestampSource = bof2ConstantsQuery?.data?.propTimeZoneType?.value;

  const isDispatcherLoading = dispatcherQuery?.isFetching;
  const isBof2ConstantsLoading = bof2ConstantsQuery?.isFetching;

  const initialValues: BearerTypeFieldType & InitialValuesForm & OptionalBOF2Constants & OptionalBOF2LaneIDs = {
    format: format ?? "JSON",
    enabled: enabled === "true",
    backOfficeURL: "",
    username: "",
    password: "",
    connectTimeoutSeconds: Number(5),
    readTimeoutSeconds: Number(15),
    overviewQuality: sightingQuality ?? "HIGH",
    cropSizeFactor: cropSizeFactor ?? "3/4",

    // Bof2 - optional constants
    FFID: FFID ?? "",
    SCID: SCID ?? "",
    timestampSource: timestampSource ?? "",
    GPSFormat: GPSFormat ?? "",

    //BOF2 - optional Lane IDs
    laneId: laneID ?? "",
    LID1: LID1 ?? "",
    LID2: LID2 ?? "",
  };

  const validateValues = (values: InitialValuesForm): InitialValuesFormErrors => {
    const errors: InitialValuesFormErrors = {};

    const read = Number(values.readTimeoutSeconds);
    if (!Number.isFinite(read)) {
      errors.readTimeoutSeconds = "Must be a number";
    } else if (read < 0) {
      errors.readTimeoutSeconds = "Must be ≥ 0";
    }

    const connect = Number(values.connectTimeoutSeconds);
    if (!Number.isFinite(connect)) {
      errors.connectTimeoutSeconds = "Must be a number";
    } else if (connect < 0) {
      errors.connectTimeoutSeconds = "Must be ≥ 0";
    }
    return errors;
  };

  const handleSubmit = async (
    values: BearerTypeFieldType & InitialValuesForm & OptionalBOF2Constants & OptionalBOF2LaneIDs
  ) => {
    const validResponse = await validateMutation.mutateAsync(values);

    const dispatcherData = {
      format: values.format,
      enabled: values.enabled,
    };
    const result = await dispatcherMutation.mutateAsync(dispatcherData);

    if (result?.id) {
      qc.invalidateQueries({ queryKey: ["dispatcher"] });
      qc.invalidateQueries({ queryKey: ["backoffice", values.format] });

      if (validResponse?.reason === "OK") {
        await backOfficeMutation.mutateAsync(values);
        await sightingAmendMutation.mutateAsync(values);

        if (values.format.toLowerCase() === "bof2") {
          const bof2ConstantsData: OptionalBOF2Constants = {
            FFID: values.FFID,
            SCID: values.SCID,
            timestampSource: values.timestampSource,
            GPSFormat: values.GPSFormat,
          };

          const bof2LaneData: OptionalBOF2LaneIDs = {
            laneId: laneIdQuery?.data?.id,
            LID1: values.LID1,
            LID2: values.LID2,
          };
          await bof2LandMutation.mutateAsync(bof2LaneData);
          await backOfficeDispatcherMutation.mutateAsync(bof2ConstantsData);
        }
      } else {
        console.log("error");
        return;
      }
    }
  };

  return (
    <Formik initialValues={initialValues} onSubmit={handleSubmit} validate={validateValues} enableReinitialize>
      {({ isSubmitting, touched }) => (
        <Form>
          <div className="mx-auto grid grid-cols-1 sm:grid-cols-1 lg:grid-cols-2 gap-2 px-2 sm:px-4 lg:px-0 w-full">
            <div>
              <BearerTypeCard />
              <StoreCard />
            </div>

            <ChannelCard
              touched={touched}
              isSubmitting={isSubmitting}
              isDispatcherLoading={isDispatcherLoading}
              isBof2ConstantsLoading={isBof2ConstantsLoading}
            />
          </div>
        </Form>
      )}
    </Formik>
  );
};

export default SettingForms;
