import { useMutation, useQuery } from "@apollo/client";
import { useEffect, useState } from "react";
import { Button, Card, Checkbox, Form, Space, Table } from "antd";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectCurrentUser } from "../../redux/user/user.selectors";
import AlertComponent from "../alert/alert.component";
import { QUERY_NOTIFICATION_SETTINGS, UPDATE_NOTIFICATION_SETTINGS } 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";

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

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

  const [updateNotificationSettings, { loading: saving }] = useMutation(UPDATE_NOTIFICATION_SETTINGS);

  // Populate form with fetched data.
  useEffect(() => {
    if (data?.associations?.length > 0) {
      const settings = data.associations[0].notification_settings || {};
      // 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);
      setIsDirty(false); // Reset dirty state when new data loads.
    }
  }, [data, form]);

  const handleSave = async (values) => {
    if (data?.associations?.length > 0) {
      const userId = data.associations[0].id;
      // Save the updated notification settings.
      const result = await updateNotificationSettings({ variables: { id: userId, ns: values } });
      if (!result?.errors) {
        notification.success({ message: t("notifications.labels.notification-settings-success") });
        setInitialValues(values);
        setIsDirty(false);
      } else {
        notification.error({ message: t("notifications.labels.notification-settings-failure") });
      }
    }
  };

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

  const handleReset = () => {
    form.setFieldsValue(initialValues);
    setIsDirty(false);
  };

  if (error) return <AlertComponent type="error" message={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: "90%"
    },
    {
      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>
      )
    }
    // TODO: Disabled for now until FCM is implemented.
    // {
    //   title: <ColumnHeaderCheckbox channel="fcm" form={form} disabled onHeaderChange={() => setIsDirty(true)} />,
    //   dataIndex: "fcm",
    //   key: "fcm",
    //   align: "center",
    //   render: (_, record) => (
    //     <Form.Item name={[record.key, "fcm"]} valuePropName="checked" noStyle>
    //       <Checkbox disabled />
    //     </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>
            <Button type="default" onClick={handleReset} disabled={!isDirty}>
              {t("general.actions.clear")}
            </Button>

            <Button type="primary" htmlType="submit" disabled={!isDirty} loading={saving}>
              {t("notifications.labels.save")}
            </Button>
          </Space>
        }
      >
        <Table dataSource={dataSource} columns={columns} pagination={false} bordered rowKey="key" />
      </Card>
    </Form>
  );
};

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

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

export default connect(mapStateToProps)(NotificationSettingsForm);
