import { GET_JOB_NOTES } from "@/graphql/jobs.queries";
import { INSERT_NEW_NOTE } from "@/graphql/notes.queries";
import { selectCurrentUser } from "@/redux/user/user.selectors";
import { useMutation } from "@apollo/client";
import { Formik } from "formik";
import React, { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import {
  Keyboard,
  KeyboardAvoidingView,
  LayoutAnimation,
  Platform,
  ScrollView,
  StyleSheet,
  UIManager,
  View,
} from "react-native";
import {
  Button,
  Chip,
  Divider,
  HelperText,
  Modal,
  Portal,
  Switch,
  Text,
  TextInput,
  useTheme,
} from "react-native-paper";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";

/**
 * NewNoteModal contract
 * Props:
 *  - jobId: uuid string
 *  - visible: boolean - controls modal visibility
 *  - onDismiss: () => void - called when modal closed without save
 *  - onCreated: (note) => void - called after successful creation
 *  - relatedRos: array of job objects to optionally attach note to (excludes current job)
 */

const mapStateToProps = createStructuredSelector({
  currentUser: selectCurrentUser,
});
const mapDispatchToProps = (dispatch) => ({});

const NewNoteModal = ({
  jobId,
  visible,
  onDismiss,
  onCreated,
  relatedRos = [],
  existingNote,
  currentUser,
}) => {
  const theme = useTheme();
  const { t } = useTranslation();
  const insets = useSafeAreaInsets();
  const [keyboardSpace, setKeyboardSpace] = useState(0);

  // Enable LayoutAnimation on Android
  if (
    Platform.OS === "android" &&
    UIManager.setLayoutAnimationEnabledExperimental
  ) {
    try {
      UIManager.setLayoutAnimationEnabledExperimental(true);
    } catch (_) {}
  }

  useEffect(() => {
    const showSub = Keyboard.addListener("keyboardWillShow", (e) => {
      LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
      setKeyboardSpace(e.endCoordinates.height);
    });
    const hideSub = Keyboard.addListener("keyboardWillHide", () => {
      LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
      setKeyboardSpace(0);
    });
    // Fallback for Android (keyboardWillShow not always fired)
    const showSubAndroid = Keyboard.addListener("keyboardDidShow", (e) => {
      if (Platform.OS === "android") {
        setKeyboardSpace(e.endCoordinates.height);
      }
    });
    const hideSubAndroid = Keyboard.addListener("keyboardDidHide", () => {
      if (Platform.OS === "android") setKeyboardSpace(0);
    });
    return () => {
      showSub.remove();
      hideSub.remove();
      showSubAndroid.remove();
      hideSubAndroid.remove();
    };
  }, []);

  const [insertNote, { loading }] = useMutation(INSERT_NEW_NOTE, {
    refetchQueries: [{ query: GET_JOB_NOTES, variables: { id: jobId } }],
    awaitRefetchQueries: true,
  });

  // Filter out current job id
  const filteredRelatedRos = relatedRos.filter((j) => j.id !== jobId);

  const initialValues = {
    critical: false,
    private: false,
    pinned: false,
    type: "general",
    text: "",
    relatedros: {},
  };

  const handleSubmit = async (values, helpers) => {
    try {
      const noteInput = {
        jobid: jobId,
        text: values.text.trim(),
        critical: values.critical,
        private: values.private,
        pinned: values.pinned,
        type: values.type,
        created_by: currentUser?.email,
      };

      // TODO: If backend supports attaching note to multiple related ROs, perform additional mutation(s)
      // here after creating the base note. This may involve an insert into a join table like note_jobs.
      // values.relatedros contains boolean flags keyed by job id.
      const { data } = await insertNote({
        variables: { note: [noteInput] },
      });
      const created = data?.insert_notes?.returning?.[0];
      if (onCreated && created) onCreated(created);
      helpers.resetForm();
    } catch (e) {
      helpers.setStatus({ error: e.message });
    }
  };

  return (
    <KeyboardAvoidingView
      enabled={visible}
      behavior={Platform.OS === "ios" ? "margin" : undefined}
      keyboardVerticalOffset={Platform.select({
        ios: insets.top + 60,
        android: 0,
      })}
      style={(styles.kbWrapper, { height: !visible && 0 })} //Needed to fix flexing on parent component.
    >
      <Portal>
        <Modal
          visible={visible}
          onDismiss={onDismiss}
          contentContainerStyle={[
            { backgroundColor: theme.colors.surface },
            styles.modalContainer,
            {
              marginBottom: keyboardSpace + insets.bottom,
            },
          ]}
        >
          <Formik
            initialValues={initialValues}
            validate={(values) => {
              const errors = {};
              if (!values.text || !values.text.trim()) {
                errors.text = t("general.validation.required");
              }
              return errors;
            }}
            onSubmit={handleSubmit}
          >
            {({
              values,
              errors,
              touched,
              setFieldValue,
              handleSubmit,
              status,
            }) => (
              <ScrollView
                style={styles.formScroll}
                contentContainerStyle={[styles.scrollContent]}
                keyboardShouldPersistTaps="handled"
              >
                <Text variant="titleMedium" style={styles.modalTitle}>
                  {existingNote
                    ? t("objects.notes.labels.editnote")
                    : t("jobdetail.actions.addnote")}
                </Text>
                <Divider style={{ marginBottom: 12 }} />
                <View style={styles.rowWrap}>
                  <SwitchWithLabel
                    label={t("objects.notes.fields.critical")}
                    value={values.critical}
                    onValueChange={(v) => setFieldValue("critical", v)}
                  />
                  <SwitchWithLabel
                    label={t("objects.notes.fields.private")}
                    value={values.private}
                    onValueChange={(v) => setFieldValue("private", v)}
                  />
                  <SwitchWithLabel
                    label={t("objects.notes.fields.pinned")}
                    value={values.pinned}
                    onValueChange={(v) => setFieldValue("pinned", v)}
                  />
                </View>
                <View style={styles.typeChips}>
                  {[
                    "general",
                    "customer",
                    "shop",
                    "office",
                    "parts",
                    "paint",
                    "supplement",
                  ].map((option) => (
                    <Chip
                      key={option}
                      selected={values.type === option}
                      onPress={() => setFieldValue("type", option)}
                      style={styles.chip}
                    >
                      {t(`objects.notes.fields.types.${option}`)}
                    </Chip>
                  ))}
                </View>
                <TextInput
                  label={t("objects.notes.fields.text")}
                  value={values.text}
                  onChangeText={(v) => setFieldValue("text", v)}
                  multiline
                  mode="outlined"
                  placeholder={t("objects.notes.labels.newnoteplaceholder")}
                  style={styles.textArea}
                />
                {touched.text && errors.text && (
                  <HelperText type="error" visible>
                    {errors.text}
                  </HelperText>
                )}
                {status?.error && (
                  <HelperText type="error" visible>
                    {status.error}
                  </HelperText>
                )}
                {!existingNote && filteredRelatedRos.length > 0 && (
                  <View style={styles.relatedRosContainer}>
                    <Text style={styles.relatedRosLabel}>
                      {t("objects.notes.labels.addtorelatedro")}
                    </Text>
                    {filteredRelatedRos.map((j) => (
                      <SwitchWithLabel
                        key={j.id}
                        label={`${j.ro_number || "N/A"}${
                          j.clm_no ? ` | ${j.clm_no}` : ""
                        }${j.status ? ` | ${j.status}` : ""}`}
                        value={values.relatedros?.[j.id] || false}
                        onValueChange={(v) =>
                          setFieldValue(`relatedros.${j.id}`, v)
                        }
                      />
                    ))}
                  </View>
                )}
                <View
                  style={[
                    styles.actions,
                    { paddingBottom: Math.max(insets.bottom, 12) },
                  ]}
                >
                  <Button
                    onPress={onDismiss}
                    mode="text"
                    disabled={loading}
                    icon="close"
                  >
                    {t("general.actions.cancel")}
                  </Button>
                  <Button
                    onPress={handleSubmit}
                    mode="contained"
                    loading={loading}
                    disabled={loading || !values.text.trim()}
                    icon="plus"
                  >
                    {existingNote
                      ? t("general.actions.save")
                      : t("general.actions.add")}
                  </Button>
                </View>
              </ScrollView>
            )}
          </Formik>
        </Modal>
      </Portal>
    </KeyboardAvoidingView>
  );
};

const SwitchWithLabel = ({ label, value, onValueChange }) => (
  <View style={styles.checkboxItem}>
    <Switch value={value} onValueChange={onValueChange} />
    <Text style={styles.checkboxLabel}>{label}</Text>
  </View>
);

const styles = StyleSheet.create({
  modalContainer: {
    marginHorizontal: 24,
    borderRadius: 16,
    //paddingVertical: 12,
    paddingHorizontal: 12,
    maxHeight: "60j%",

    //minHeight: 200,
  },
  kbWrapper: {
    flex: 1,
  },
  modalTitle: {
    paddingHorizontal: 4,
    paddingBottom: 8,
  },
  formScroll: {
    marginTop: 8,
  },
  rowWrap: {
    flexDirection: "row",
    flexWrap: "wrap",
    justifyContent: "space-between",
    marginBottom: 12,
  },
  checkboxItem: {
    flexDirection: "row",
    alignItems: "center",
    marginRight: 12,
    marginVertical: 4,
  },
  checkboxLabel: {
    fontSize: 14,
    marginLeft: 8,
  },
  typeChips: {
    flexDirection: "row",
    flexWrap: "wrap",
    marginBottom: 12,
  },
  chip: {
    margin: 4,
  },
  textArea: {
    minHeight: 160,
    marginBottom: 8,
  },
  relatedRosContainer: {
    marginTop: 16,
  },
  relatedRosLabel: {
    fontWeight: "600",
    marginBottom: 8,
  },
  actions: {
    flexDirection: "row",
    justifyContent: "flex-end",
    marginTop: 16,
    gap: 12,
  },
  scrollContent: {
    // paddingBottom: 24,
  },
});

export default connect(mapStateToProps, mapDispatchToProps)(NewNoteModal);
