import { useMutation, useQuery } from "@apollo/client/react";
import { useEffect, useState } from "react";
import { Alert, Button, Card, Checkbox, Divider, Form, Space, Switch, Typography } from "antd";
import ResponsiveTable from "../responsive-table/responsive-table.component";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectBodyshop, selectCurrentUser } from "../../redux/user/user.selectors";
import AlertComponent from "../alert/alert.component";
import {
  QUERY_NOTIFICATION_SETTINGS,
  UPDATE_NOTIFICATION_SETTINGS,
  UPDATE_NOTIFICATIONS_AUTOADD
} from "../../graphql/user.queries.js";
import { notificationScenarios } from "../../utils/jobNotificationScenarios.js";
import LoadingSpinner from "../loading-spinner/loading-spinner.component.jsx";
import PropTypes from "prop-types";
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
import ColumnHeaderCheckbox from "../notification-settings/column-header-checkbox.component.jsx";
import { useIsEmployee } from "../../utils/useIsEmployee.js";

/**
 * Notifications Settings Form
 * @param currentUser
 * @param bodyshop
 * @returns {JSX.Element}
 * @constructor
 */
const NotificationSettingsForm = ({ currentUser, bodyshop }) => {
  const { t } = useTranslation();
  const [form] = Form.useForm();
  const [initialValues, setInitialValues] = useState({});
  const [isDirty, setIsDirty] = useState(false);
  const [autoAddEnabled, setAutoAddEnabled] = useState(false);
  const [initialAutoAdd, setInitialAutoAdd] = useState(false);
  const notification = useNotification();
  const isEmployee = useIsEmployee(bodyshop, currentUser);

  // Fetch notification settings and notifications_autoadd
  const { loading, error, data } = useQuery(QUERY_NOTIFICATION_SETTINGS, {
    fetchPolicy: "network-only",
    nextFetchPolicy: "network-only",
    variables: { email: currentUser.email },
    skip: !currentUser
  });

  const [updateNotificationSettings, { loading: savingSettings }] = useMutation(UPDATE_NOTIFICATION_SETTINGS);
  const [updateNotificationsAutoAdd, { loading: savingAutoAdd }] = useMutation(UPDATE_NOTIFICATIONS_AUTOADD);

  // Populate form with fetched data
  useEffect(() => {
    if (data?.associations?.length > 0) {
      const settings = data.associations[0].notification_settings || {};
      const autoAdd = data.associations[0].notifications_autoadd ?? false;

      // Ensure each scenario has an object with { app, email, fcm }
      const formattedValues = notificationScenarios.reduce((acc, scenario) => {
        acc[scenario] = settings[scenario] ?? { app: false, email: false, fcm: false };
        return acc;
      }, {});

      setInitialValues(formattedValues);
      form.setFieldsValue(formattedValues);
      setAutoAddEnabled(autoAdd);
      setInitialAutoAdd(autoAdd);
      setIsDirty(false); // Reset dirty state when new data loads
    }
  }, [data, form]);

  // Handle toggle of notifications_autoadd
  const handleAutoAddToggle = async (checked) => {
    if (data?.associations?.length > 0) {
      const userId = data.associations[0].id;
      try {
        const result = await updateNotificationsAutoAdd({
          variables: { id: userId, autoadd: checked }
        });
        if (!result?.errors) {
          setAutoAddEnabled(checked);
          setInitialAutoAdd(checked);
          notification.success({ title: t("notifications.labels.auto-add-success") });
          setIsDirty(false); // Reset dirty state if only auto-add was changed
        } else {
          throw new Error("Failed to update auto-add setting");
        }
      } catch {
        setAutoAddEnabled(!checked); // Revert on error
        notification.error({ title: t("notifications.labels.auto-add-failure") });
      }
    }
  };

  // Handle save of notification settings
  const handleSave = async (values) => {
    if (data?.associations?.length > 0) {
      const userId = data.associations[0].id;
      try {
        const result = await updateNotificationSettings({ variables: { id: userId, ns: values } });
        if (!result?.errors) {
          notification.success({ title: t("notifications.labels.notification-settings-success") });
          setInitialValues(values);
          setIsDirty(false);
        } else {
          throw new Error("Failed to update notification settings");
        }
      } catch {
        notification.error({ title: t("notifications.labels.notification-settings-failure") });
      }
    }
  };

  // Mark the form as dirty on any manual change
  const handleFormChange = () => {
    setIsDirty(true);
  };

  // Check if auto-add has changed
  const isAutoAddDirty = autoAddEnabled !== initialAutoAdd;

  // Handle reset of form and auto-add
  const handleReset = () => {
    form.setFieldsValue(initialValues);
    setAutoAddEnabled(initialAutoAdd);
    setIsDirty(false);
  };

  if (error) return <AlertComponent type="error" title={error.message} />;
  if (loading) return <LoadingSpinner />;

  const columns = [
    {
      title: t("notifications.labels.scenario"),
      dataIndex: "scenarioLabel",
      key: "scenario",
      render: (_, record) => t(`notifications.scenarios.${record.key}`),
      width: "80%"
    },
    {
      title: <ColumnHeaderCheckbox channel="app" form={form} onHeaderChange={() => setIsDirty(true)} />,
      dataIndex: "app",
      key: "app",
      align: "center",
      render: (_, record) => (
        <Form.Item name={[record.key, "app"]} valuePropName="checked" noStyle>
          <Checkbox />
        </Form.Item>
      )
    },
    {
      title: <ColumnHeaderCheckbox channel="email" form={form} onHeaderChange={() => setIsDirty(true)} />,
      dataIndex: "email",
      key: "email",
      align: "center",
      render: (_, record) => (
        <Form.Item name={[record.key, "email"]} valuePropName="checked" noStyle>
          <Checkbox />
        </Form.Item>
      )
    }
  ];

  // Currently disabled for prod
  if (!import.meta.env.PROD) {
    columns.push({
      title: <ColumnHeaderCheckbox channel="fcm" form={form} onHeaderChange={() => setIsDirty(true)} />,
      dataIndex: "fcm",
      key: "fcm",
      align: "center",
      render: (_, record) => (
        <Form.Item name={[record.key, "fcm"]} valuePropName="checked" noStyle>
          <Checkbox />
        </Form.Item>
      )
    });
  }

  const dataSource = notificationScenarios.map((scenario) => ({ key: scenario }));

  return (
    <Form
      form={form}
      onFinish={handleSave}
      onValuesChange={handleFormChange}
      initialValues={initialValues}
      autoComplete="off"
      layout="vertical"
    >
      <Card
        title={t("notifications.labels.notificationscenarios")}
        extra={
          <Space>
            <Typography.Text type="secondary">{t("notifications.labels.auto-add")}</Typography.Text>
            <Switch checked={autoAddEnabled} onChange={handleAutoAddToggle} loading={savingAutoAdd} />
            <Button type="default" onClick={handleReset} disabled={!isDirty && !isAutoAddDirty}>
              {t("general.actions.clear")}
            </Button>
            <Button type="primary" htmlType="submit" disabled={!isDirty} loading={savingSettings}>
              {t("notifications.labels.save")}
            </Button>
          </Space>
        }
      >
        {!isEmployee && (
          <div style={{ width: "100%", marginBottom: "10px" }}>
            <Alert title={t("notifications.labels.employee-notification")} type="warning" />
          </div>
        )}
        <ResponsiveTable
          dataSource={dataSource}
          columns={columns}
          mobileColumnKeys={["email", "scenario", "app", "fcm"]}
          pagination={false}
          bordered
          rowKey="key"
        />
        <Divider />
      </Card>
    </Form>
  );
};

NotificationSettingsForm.propTypes = {
  currentUser: PropTypes.shape({
    email: PropTypes.string.isRequired
  }).isRequired,
  bodyshop: PropTypes.object.isRequired
};

const mapStateToProps = createStructuredSelector({
  currentUser: selectCurrentUser,
  bodyshop: selectBodyshop
});

export default connect(mapStateToProps)(NotificationSettingsForm);
