import { useContext, useEffect, useRef, useState } from 'react';
import * as React from 'react';
import DJClientContext from '../../providers/djclient';
import { ErrorMessage, Field, Form, Formik } from 'formik';
import { FormikSelect } from '../AddEditNodePage/FormikSelect';
import EditIcon from '../../icons/EditIcon';
import { displayMessageAfterSubmit } from '../../../utils/form';
import LoadingIcon from '../../icons/LoadingIcon';

export default function ManageDimensionLinksDialog({
  column,
  node,
  dimensions,
  fkLinks,
  referenceLink,
  onSubmit,
}) {
  const djClient = useContext(DJClientContext).DataJunctionAPI;
  const [isOpen, setIsOpen] = useState(false);
  const [activeTab, setActiveTab] = useState('fk');
  const ref = useRef(null);
  const [dimensionColumns, setDimensionColumns] = useState([]);
  const [selectedDimension, setSelectedDimension] = useState(
    referenceLink?.dimension || '',
  );

  useEffect(() => {
    const handleClickOutside = event => {
      if (ref.current && !ref.current.contains(event.target)) {
        setIsOpen(false);
      }
    };
    document.addEventListener('click', handleClickOutside, true);
    return () => {
      document.removeEventListener('click', handleClickOutside, true);
    };
  }, []);

  // Fetch columns for the selected dimension
  useEffect(() => {
    const fetchDimensionColumns = async () => {
      if (selectedDimension) {
        try {
          const dimensionNode = await djClient.node(selectedDimension);
          const columns = dimensionNode.columns.map(col => ({
            value: col.name,
            label: col.display_name || col.name,
          }));
          setDimensionColumns(columns);
        } catch (error) {
          console.error('Failed to fetch dimension columns:', error);
        }
      }
    };
    fetchDimensionColumns();
  }, [selectedDimension, djClient]);

  const handleFKSubmit = async (values, { setSubmitting, setStatus }) => {
    try {
      // Add FK links that are not already present
      const existingDims = new Set(fkLinks);
      const newDims = new Set(values.fkDimensions);

      // Links to add
      const toAdd = Array.from(newDims).filter(dim => !existingDims.has(dim));
      // Links to remove
      const toRemove = Array.from(existingDims).filter(
        dim => !newDims.has(dim),
      );

      const addPromises = toAdd.map(dim =>
        djClient.linkDimension(node.name, column.name, dim),
      );
      const removePromises = toRemove.map(dim =>
        djClient.unlinkDimension(node.name, column.name, dim),
      );

      const results = await Promise.all([...addPromises, ...removePromises]);
      const failures = results.filter(
        r => !(r.status === 200 || r.status === 201),
      );
      if (failures.length > 0) {
        const message =
          failures[0].json?.message ||
          failures[0].json?.detail ||
          'Failed to update FK links';
        setStatus({ failure: message });
        return;
      }

      setStatus({ success: 'FK links updated successfully!' });
      setTimeout(() => {
        onSubmit();
      }, 500);
    } catch (error) {
      setStatus({ failure: error.message });
    } finally {
      setSubmitting(false);
    }
  };

  const handleReferenceSubmit = async (
    values,
    { setSubmitting, setStatus },
  ) => {
    try {
      const response = await djClient.addReferenceDimensionLink(
        node.name,
        column.name,
        values.dimensionNode,
        values.dimensionColumn,
        values.role || null,
      );

      if (response.status === 200 || response.status === 201) {
        setStatus({ success: 'Reference link updated successfully!' });
        setTimeout(() => {
          onSubmit();
        }, 500);
      } else {
        setStatus({ failure: response.json?.message || 'Failed to add link' });
      }
    } catch (error) {
      setStatus({ failure: error.message });
    } finally {
      setSubmitting(false);
    }
  };

  const handleRemoveReference = async () => {
    if (
      !window.confirm('Are you sure you want to remove this reference link?')
    ) {
      return;
    }

    try {
      const response = await djClient.removeReferenceDimensionLink(
        node.name,
        column.name,
      );

      if (response.status === 200 || response.status === 201) {
        alert('Reference dimension link removed successfully!');
        window.location.reload();
      } else {
        alert(response.json?.message || 'Failed to remove link');
      }
    } catch (error) {
      alert(error.message);
    }
  };

  return (
    <>
      <button
        className="edit_button dimension-link-edit"
        aria-label="ManageDimensionLinksToggle"
        tabIndex="0"
        onClick={() => setIsOpen(!isOpen)}
        title="Manage dimension links for this column"
        style={{
          marginLeft: '0.35rem',
          padding: '0',
          opacity: 0.5,
          transition: 'opacity 0.2s ease',
          background: 'transparent',
          border: 'none',
          cursor: 'pointer',
          fontSize: '12px',
          color: '#999',
          display: 'inline-flex',
          alignItems: 'center',
        }}
      >
        <EditIcon />
      </button>
      {isOpen && (
        <>
          {/* Backdrop overlay */}
          <div
            style={{
              position: 'fixed',
              top: 0,
              left: 0,
              right: 0,
              bottom: 0,
              backgroundColor: 'rgba(0, 0, 0, 0.5)',
              zIndex: 1000,
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'center',
              padding: '2rem',
            }}
            onClick={() => setIsOpen(false)}
          >
            {/* Modal */}
            <div
              role="dialog"
              aria-label="ManageDimensionLinksDialog"
              ref={ref}
              onClick={e => e.stopPropagation()}
              style={{
                backgroundColor: 'white',
                borderRadius: '8px',
                boxShadow: '0 4px 20px rgba(0, 0, 0, 0.15)',
                width: '550px',
                maxWidth: '100%',
                maxHeight: '100%',
                overflow: 'visible',
                padding: '1.5rem',
                textTransform: 'none',
                fontWeight: 'normal',
                position: 'relative',
                zIndex: 1000,
              }}
            >
              <div
                style={{ maxHeight: 'calc(85vh - 4rem)', overflowY: 'auto' }}
              >
                <div style={{ display: 'flex', marginBottom: '1rem' }}>
                  <h3
                    style={{
                      margin: '0 1em 0 0',
                      fontSize: '1.25rem',
                      fontWeight: '600',
                    }}
                  >
                    Manage Dimension Links
                  </h3>
                  <span
                    style={{
                      display: 'flex',
                      alignItems: 'center',
                      gap: '0.5rem',
                    }}
                  >
                    <span
                      style={{
                        fontSize: '1rem',
                        fontWeight: '500',
                        color: '#333',
                      }}
                    >
                      {column.name}
                    </span>
                    <span
                      className="rounded-pill badge bg-secondary-soft"
                      style={{ fontSize: '0.75rem', fontWeight: 'normal' }}
                    >
                      {column.type}
                    </span>
                  </span>
                </div>

                {/* Tab Navigation */}
                <div
                  style={{
                    display: 'flex',
                    borderBottom: '2px solid #e0e0e0',
                    marginBottom: '1rem',
                  }}
                >
                  <button
                    type="button"
                    onClick={() => setActiveTab('fk')}
                    style={{
                      flex: 1,
                      padding: '0.5rem 1rem',
                      border: 'none',
                      background: 'transparent',
                      borderBottom:
                        activeTab === 'fk' ? '3px solid #007bff' : 'none',
                      color: activeTab === 'fk' ? '#007bff' : '#6c757d',
                      fontWeight: activeTab === 'fk' ? 'bold' : 'normal',
                      cursor: 'pointer',
                    }}
                  >
                    FK Links
                  </button>
                  <button
                    type="button"
                    onClick={() => setActiveTab('reference')}
                    style={{
                      flex: 1,
                      padding: '0.5rem 1rem',
                      border: 'none',
                      background: 'transparent',
                      borderBottom:
                        activeTab === 'reference'
                          ? '3px solid #007bff'
                          : 'none',
                      color: activeTab === 'reference' ? '#007bff' : '#6c757d',
                      fontWeight: activeTab === 'reference' ? 'bold' : 'normal',
                      cursor: 'pointer',
                    }}
                  >
                    Reference Links
                  </button>
                </div>

                {/* FK Links Tab */}
                {activeTab === 'fk' && (
                  <div>
                    <p
                      style={{
                        fontSize: '0.875rem',
                        color: '#6c757d',
                        marginBottom: '1rem',
                      }}
                    >
                      FK Links automatically join via the dimension's primary
                      key. Select one or more dimensions to link to this column.
                    </p>
                    <Formik
                      initialValues={{
                        fkDimensions: fkLinks,
                      }}
                      onSubmit={handleFKSubmit}
                    >
                      {function Render({ isSubmitting, status }) {
                        return (
                          <Form>
                            {displayMessageAfterSubmit(status)}
                            <div style={{ marginBottom: '1rem' }}>
                              <label htmlFor="fkDimensions">
                                Select Dimensions
                              </label>
                              <FormikSelect
                                selectOptions={dimensions}
                                formikFieldName="fkDimensions"
                                placeholder="Select dimensions"
                                isMulti={true}
                                defaultValue={fkLinks.map(dim => ({
                                  value: dim,
                                  label: dim,
                                }))}
                                menuPosition="fixed"
                              />
                            </div>
                            <button
                              className="add_node"
                              type="submit"
                              disabled={isSubmitting}
                              style={{ marginLeft: '0' }}
                            >
                              {isSubmitting ? <LoadingIcon /> : 'Save'}
                            </button>
                          </Form>
                        );
                      }}
                    </Formik>
                  </div>
                )}

                {/* Reference Links Tab */}
                {activeTab === 'reference' && (
                  <div>
                    <p
                      style={{
                        fontSize: '0.875rem',
                        color: '#6c757d',
                        marginBottom: '1rem',
                      }}
                    >
                      Reference Links explicitly map this column to a specific
                      dimension attribute. Use when the relationship is not
                      through a primary key.
                    </p>
                    <Formik
                      initialValues={{
                        dimensionNode: referenceLink?.dimension || '',
                        dimensionColumn: referenceLink?.dimension_column || '',
                        role: referenceLink?.role || '',
                      }}
                      onSubmit={handleReferenceSubmit}
                      validate={values => {
                        const errors = {};
                        if (!values.dimensionNode) {
                          errors.dimensionNode = 'Required';
                        }
                        if (!values.dimensionColumn) {
                          errors.dimensionColumn = 'Required';
                        }
                        return errors;
                      }}
                    >
                      {function Render({
                        isSubmitting,
                        status,
                        setFieldValue,
                      }) {
                        return (
                          <Form>
                            {displayMessageAfterSubmit(status)}
                            <div style={{ marginBottom: '1rem' }}>
                              <ErrorMessage
                                name="dimensionNode"
                                component="span"
                              />
                              <label htmlFor="dimensionNode">
                                Dimension Node *
                              </label>
                              <FormikSelect
                                selectOptions={dimensions}
                                formikFieldName="dimensionNode"
                                placeholder="Select dimension"
                                defaultValue={
                                  referenceLink
                                    ? {
                                        value: referenceLink.dimension,
                                        label: referenceLink.dimension,
                                      }
                                    : null
                                }
                                onChange={option => {
                                  setFieldValue(
                                    'dimensionNode',
                                    option?.value || '',
                                  );
                                  setSelectedDimension(option?.value || '');
                                  setFieldValue('dimensionColumn', '');
                                }}
                              />
                            </div>

                            <div style={{ marginBottom: '1rem' }}>
                              <ErrorMessage
                                name="dimensionColumn"
                                component="span"
                              />
                              <label htmlFor="dimensionColumn">
                                Dimension Column *
                              </label>
                              {dimensionColumns.length > 0 ? (
                                <FormikSelect
                                  selectOptions={dimensionColumns}
                                  formikFieldName="dimensionColumn"
                                  placeholder="Select column"
                                  defaultValue={
                                    referenceLink
                                      ? {
                                          value: referenceLink.dimension_column,
                                          label: referenceLink.dimension_column,
                                        }
                                      : null
                                  }
                                />
                              ) : (
                                <Field
                                  type="text"
                                  name="dimensionColumn"
                                  id="dimensionColumn"
                                  placeholder="Enter dimension column name"
                                  style={{
                                    width: '100%',
                                    padding: '0.5rem',
                                  }}
                                />
                              )}
                            </div>

                            <div style={{ marginBottom: '1rem' }}>
                              <label htmlFor="role">Role (Optional)</label>
                              <Field
                                type="text"
                                name="role"
                                id="role"
                                placeholder="e.g., birth_date, registration_date"
                                style={{
                                  width: '100%',
                                  padding: '0.5rem',
                                }}
                              />
                              <small
                                style={{
                                  color: '#6c757d',
                                  fontSize: '0.75rem',
                                }}
                              >
                                Optional role if linking the same dimension
                                multiple times
                              </small>
                            </div>

                            <div
                              style={{
                                display: 'flex',
                                gap: '0.5rem',
                                marginTop: '1rem',
                              }}
                            >
                              <button
                                className="add_node"
                                type="submit"
                                disabled={isSubmitting}
                              >
                                {isSubmitting ? (
                                  <LoadingIcon />
                                ) : referenceLink ? (
                                  'Update Link'
                                ) : (
                                  'Add Link'
                                )}
                              </button>
                              {referenceLink && (
                                <button
                                  type="button"
                                  onClick={handleRemoveReference}
                                  style={{
                                    padding: '0.5rem 1rem',
                                    background: '#dc3545',
                                    color: 'white',
                                    border: 'none',
                                    borderRadius: '4px',
                                    cursor: 'pointer',
                                    textTransform: 'none',
                                  }}
                                >
                                  Remove Link
                                </button>
                              )}
                            </div>
                          </Form>
                        );
                      }}
                    </Formik>
                  </div>
                )}
              </div>
            </div>
          </div>
        </>
      )}
    </>
  );
}
