import { useEffect, useMemo, useState } from 'react';
import { useSelector } from 'react-redux';
import { Button, CircularProgress } from '@mui/material';

import Dialog from '../Dialog';
import {
  fetchSubscribable,
  selectSubscribable,
  selectTreeLoadingStates,
  subscribeProfile,
  unsubscribeProfile
} from './store';
import { useHostTreeDispatch } from './store/dispatchType';

interface Props {
  open: boolean;
  subscribedIds: Set<string>;
  onClose: () => void;
  onChanged: () => void; // parent should refetch profile list after any change
}

export const EditSubscriptionsDialog = ({
  open,
  subscribedIds,
  onClose,
  onChanged
}: Props) => {
  const dispatch = useHostTreeDispatch();
  const { items, loading, loaded } = useSelector(selectSubscribable);
  const { subscribeProfile: subBusy, unsubscribeProfile: unsubBusy } = useSelector(
    selectTreeLoadingStates
  );
  const [busyId, setBusyId] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    if (!open) return;
    if (!loaded) dispatch(fetchSubscribable());
  }, [dispatch, open, loaded]);

  // Track subscribed state separately so optimistic toggles reflect
  // immediately even before the parent re-pulls the profile list.
  const [localSubscribed, setLocalSubscribed] = useState<Set<string>>(new Set());
  useEffect(() => {
    setLocalSubscribed(new Set(subscribedIds));
  }, [subscribedIds]);

  const rows = useMemo(
    () =>
      items.map(p => ({
        id: String(p.id),
        profile: p,
        subscribed: localSubscribed.has(String(p.id))
      })),
    [items, localSubscribed]
  );

  const toggleSubscription = async (row: { id: string; subscribed: boolean }) => {
    setBusyId(row.id);
    setError(null);
    const thunk = row.subscribed ? unsubscribeProfile : subscribeProfile;
    const action = await dispatch(thunk(row.id));
    setBusyId(null);
    const matcher = row.subscribed ? unsubscribeProfile.fulfilled : subscribeProfile.fulfilled;
    if (matcher.match(action)) {
      setLocalSubscribed(prev => {
        const next = new Set(prev);
        if (row.subscribed) next.delete(row.id);
        else next.add(row.id);
        return next;
      });
      onChanged();
    } else {
      setError((action.error?.message as string) ?? 'Failed to update subscription');
    }
  };

  return (
    <Dialog
      open={open}
      onClose={onClose}
      title="Subscription list"
      size="md"
      fullWidth
      actionButtons={
        <Button onClick={onClose} variant="outlined" color="inherit">
          Close
        </Button>
      }
    >
      {loading && (
        <div style={{ display: 'flex', justifyContent: 'center', padding: 24 }}>
          <CircularProgress size={24} />
        </div>
      )}
      {error && <div className="alert alert-error">{error}</div>}
      {!loading && rows.length === 0 && (
        <div className="alert alert-info">No shared trees available to subscribe to.</div>
      )}
      {!loading && rows.length > 0 && (
        <ul style={{ listStyle: 'none', padding: 0, margin: 0 }}>
          {rows.map(row => {
            const busy = busyId === row.id && (subBusy || unsubBusy);
            return (
              <li
                key={row.id}
                style={{
                  display: 'flex',
                  justifyContent: 'space-between',
                  alignItems: 'center',
                  padding: '8px 4px',
                  borderBottom: '1px solid #eee'
                }}
              >
                <div>
                  <strong>{row.profile.name}</strong>
                </div>
                <Button
                  size="small"
                  variant={row.subscribed ? 'outlined' : 'contained'}
                  color={row.subscribed ? 'inherit' : 'primary'}
                  disabled={busy}
                  onClick={() => toggleSubscription(row)}
                >
                  {row.subscribed ? 'Unsubscribe' : 'Subscribe'}
                </Button>
              </li>
            );
          })}
        </ul>
      )}
    </Dialog>
  );
};
