import { useState } from 'react';
import { useNavigate } from 'react-router';
import { useTranslation } from 'react-i18next';
import type { FetchBaseQueryError } from '@reduxjs/toolkit/query';
import {
  Card,
  TextField,
  Button,
  Callout,
  Badge,
  Dialog,
  IconButton,
} from '@olly/modern-sk';
import { Icon } from '../../components/common/Icon';
import { useAppDispatch } from '../../hooks/useAppDispatch';
import { useConnectionStatus } from '../../hooks/useConnectionStatus';
import { setTokens, setUser } from '../../store/slices/auth';
import {
  useLoginMutation,
  useRegisterMutation,
} from '../../api/endpoints/auth';
import { REGISTRATION_ENABLED } from '../../config/env';
import {
  listInstances,
  getActiveInstanceId,
  setActiveInstanceId,
  removeInstance,
  clearInstanceAuth,
  upsertInstance,
  type Instance,
} from '../../config/instances';

type Mode = 'login' | 'register';

const HEALTH_VARIANTS = {
  connected: 'lime',
  connecting: 'neutral',
  disconnected: 'ember',
  error: 'ember',
} as const;

const HEALTH_KEY = {
  connected: 'conn.connected',
  connecting: 'conn.connecting',
  disconnected: 'conn.disconnected',
  error: 'conn.error',
} as const;

/** Map an RTKQ login failure to a user-facing i18n key. */
function resolveLoginError(err: unknown): string {
  const e = err as FetchBaseQueryError | undefined;
  if (e && 'status' in e) {
    if (e.status === 'FETCH_ERROR') return 'connect.errors.unreachable';
    if (e.status === 401) return 'connect.errors.badCredentials';
  }
  return 'connect.errors.generic';
}

/** Map an RTKQ register failure to a user-facing i18n key. */
function resolveRegisterError(err: unknown): string {
  const e = err as FetchBaseQueryError | undefined;
  if (e && 'status' in e) {
    if (e.status === 'FETCH_ERROR') return 'connect.errors.unreachable';
    if (e.status === 409) return 'connect.errors.usernameTaken';
    if (e.status === 422) return 'connect.errors.passwordTooShort';
    if (e.status === 403) return 'connect.errors.registrationDisabled';
  }
  return 'connect.errors.registerFailed';
}

function InstanceRow({
  inst,
  selected,
  onSelect,
  onLogout,
  onRemove,
}: {
  inst: Instance;
  selected: boolean;
  onSelect: () => void;
  onLogout: () => void;
  onRemove: () => void;
}) {
  const { t } = useTranslation();
  const status = useConnectionStatus(inst.baseUrl);
  const [dialogOpen, setDialogOpen] = useState(false);

  return (
    <div
      style={{
        display: 'flex',
        alignItems: 'center',
        gap: '0.625rem',
        padding: '0.375rem 0',
      }}
    >
      <Badge variant={HEALTH_VARIANTS[status]} dot>
        {t(HEALTH_KEY[status])}
      </Badge>
      <div style={{ minWidth: 0, flex: 1 }}>
        <div
          style={{
            fontSize: '0.875rem',
            fontWeight: 600,
            color: 'var(--color-text-1)',
            overflow: 'hidden',
            textOverflow: 'ellipsis',
            whiteSpace: 'nowrap',
          }}
        >
          {inst.name}
        </div>
        <div
          style={{
            fontSize: '0.75rem',
            color: 'var(--color-text-3)',
            overflow: 'hidden',
            textOverflow: 'ellipsis',
            whiteSpace: 'nowrap',
          }}
        >
          {inst.baseUrl}
        </div>
      </div>
      {selected ? (
        <Badge variant="outline">{t('connect.domains.selected')}</Badge>
      ) : (
        <Button variant="ghost" size="sm" onClick={onSelect}>
          {t('connect.domains.use')}
        </Button>
      )}
      <Dialog
        open={dialogOpen}
        onOpenChange={setDialogOpen}
        title={t('connect.removeDialog.title')}
        description={t('connect.removeDialog.description', {
          name: inst.name,
        })}
        trigger={
          <button
            type="button"
            className="iconbtn sm"
            title={t('connect.domains.forgetTitle')}
          >
            <Icon name="trash" />
          </button>
        }
        footer={
          <div
            style={{
              display: 'flex',
              justifyContent: 'flex-end',
              gap: '0.5rem',
            }}
          >
            <Button
              variant="ghost"
              size="sm"
              onClick={() => setDialogOpen(false)}
            >
              {t('connect.removeDialog.cancel')}
            </Button>
            <Button
              variant="ghost"
              size="sm"
              onClick={() => {
                setDialogOpen(false);
                onLogout();
              }}
            >
              {t('connect.removeDialog.logout')}
            </Button>
            <Button
              variant="ember"
              size="sm"
              onClick={() => {
                setDialogOpen(false);
                onRemove();
              }}
            >
              {t('connect.removeDialog.removeAndLogout')}
            </Button>
          </div>
        }
      />
    </div>
  );
}

export function ConnectPage() {
  const { t } = useTranslation();
  const dispatch = useAppDispatch();
  const navigate = useNavigate();

  const [rev, setRev] = useState(0);
  const instances = listInstances();

  const [selectedId, setSelectedId] = useState<string | null>(() =>
    getActiveInstanceId(),
  );
  const selectedInstance = instances.find((i) => i.id === selectedId) ?? null;
  const [instanceAddShown, setInstanceAddShown] = useState(false);

  const [addUrl, setAddUrl] = useState('');

  const [mode, setMode] = useState<Mode>('login');
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');
  const [error, setError] = useState<string | null>(null);

  const [login, { isLoading: isLoggingIn }] = useLoginMutation();
  const [register, { isLoading: isRegistering }] = useRegisterMutation();
  const isLoading = isLoggingIn || isRegistering;

  const switchMode = (next: Mode) => {
    setMode(next);
    setError(null);
  };

  // Switching the active instance and reloading lets the app pick the saved
  // session for that instance back up (if any); if it has none, ProtectedRoute
  // bounces back here and `selectedId` defaults to it, surfacing the login card.
  const selectInstance = (id: string) => {
    setActiveInstanceId(id);
    window.location.assign('/');
  };

  const handleAdd = (e: React.FormEvent) => {
    e.preventDefault();
    const url = addUrl.trim();
    if (!url || url === 'https://') return;
    const inst = upsertInstance(url);
    setActiveInstanceId(inst.id);
    setAddUrl('https://');
    setSelectedId(inst.id);
    setRev((r) => r + 1);
  };

  const handleLogout = (id: string) => {
    clearInstanceAuth(id);
    setRev((r) => r + 1);
  };

  const handleRemove = (id: string) => {
    removeInstance(id);
    if (selectedId === id) setSelectedId(getActiveInstanceId());
    setRev((r) => r + 1);
  };

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!selectedInstance) return;
    setError(null);

    try {
      const action =
        mode === 'register'
          ? register({ username, password })
          : login({ username, password });
      const { user, tokens } = await action.unwrap();
      dispatch(setTokens(tokens));
      dispatch(setUser(user));
      void navigate('/');
    } catch (err) {
      setError(
        mode === 'register'
          ? resolveRegisterError(err)
          : resolveLoginError(err),
      );
    }
  };

  const labelStyle: React.CSSProperties = {
    display: 'block',
    fontSize: '0.8125rem',
    fontWeight: 500,
    marginBottom: '0.375rem',
    color: 'var(--color-text-2)',
  };

  return (
    <div
      key={rev}
      style={{
        minHeight: '100vh',
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center',
        padding: '2rem',
      }}
    >
      <div
        style={{
          width: '100%',
          maxWidth: '26rem',
          display: 'flex',
          flexDirection: 'column',
          gap: '1.25rem',
        }}
      >
        <h1
          style={{
            textAlign: 'center',
            color: 'var(--color-accent)',
            fontSize: '1.75rem',
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center',
            gap: '0.5rem',
          }}
        >
          <Icon name="vinyl-record" fill /> MCMA
        </h1>

        <Card>
          <div
            style={{
              padding: '1.25rem 1.5rem',
              display: 'flex',
              flexDirection: 'column',
              gap: '0.5rem',
            }}
          >
            {instances.length > 0 && (
              <>
                <span className="msk-label" style={{ marginBottom: '0.25rem' }}>
                  {t('connect.domains.title')}
                </span>
                {instances.map((inst) => (
                  <InstanceRow
                    key={inst.id}
                    inst={inst}
                    selected={inst.id === selectedId}
                    onSelect={() => selectInstance(inst.id)}
                    onLogout={() => handleLogout(inst.id)}
                    onRemove={() => handleRemove(inst.id)}
                  />
                ))}
              </>
            )}
            <form
              onSubmit={handleAdd}
              style={{
                display: 'flex',
                gap: '0.5rem',
                marginTop: instances.length > 0 ? '0.5rem' : 0,
              }}
            >
              {instanceAddShown ? (
                <>
                  <TextField
                    value={addUrl}
                    onChange={(e) => setAddUrl(e.target.value)}
                    placeholder={t('connect.domains.addPlaceholder')}
                    style={{ flex: 1 }}
                  />
                  <IconButton type="submit" variant="primary">
                    <Icon name="plus" />
                  </IconButton>
                </>
              ) : (
                <Button
                  onClick={() => setInstanceAddShown(true)}
                  style={{ width: '100%' }}
                  variant="ghost"
                >
                  <Icon name="plus" /> {t('connect.domains.addButton')}
                </Button>
              )}
            </form>
          </div>
        </Card>

        {selectedInstance && (
          <Card>
            <form
              onSubmit={handleSubmit}
              style={{
                display: 'flex',
                flexDirection: 'column',
                gap: '1rem',
                padding: '1.5rem',
              }}
            >
              <span className="msk-label">
                {mode === 'register'
                  ? t('connect.login.registerTitle', {
                      name: selectedInstance.name,
                    })
                  : t('connect.login.title', { name: selectedInstance.name })}
              </span>
              <div>
                <label style={labelStyle}>{t('connect.login.username')}</label>
                <TextField
                  value={username}
                  onChange={(e) => setUsername(e.target.value)}
                  placeholder="username"
                  autoComplete="username"
                  required
                />
              </div>
              <div>
                <label style={labelStyle}>{t('connect.login.password')}</label>
                <TextField
                  type="password"
                  value={password}
                  onChange={(e) => setPassword(e.target.value)}
                  placeholder="password"
                  autoComplete={
                    mode === 'register' ? 'new-password' : 'current-password'
                  }
                  required
                />
                {mode === 'register' && (
                  <span
                    style={{
                      display: 'block',
                      fontSize: '0.75rem',
                      color: 'var(--color-text-3)',
                      marginTop: '0.375rem',
                    }}
                  >
                    {t('connect.login.passwordHint')}
                  </span>
                )}
              </div>
              {error && <Callout variant="danger">{t(error)}</Callout>}
              <Button
                type="submit"
                variant="primary"
                disabled={isLoading}
                style={{ marginTop: '0.5rem' }}
              >
                {isLoading
                  ? mode === 'register'
                    ? t('connect.login.registering')
                    : t('connect.login.submitting')
                  : mode === 'register'
                    ? t('connect.login.registerSubmit')
                    : t('connect.login.submit')}
              </Button>

              {REGISTRATION_ENABLED && (
                <div
                  style={{
                    textAlign: 'center',
                    fontSize: '0.8125rem',
                    color: 'var(--color-text-3)',
                  }}
                >
                  {mode === 'register' ? (
                    <>
                      {t('connect.login.haveAccount')}{' '}
                      <Button
                        type="button"
                        variant="ghost"
                        size="sm"
                        onClick={() => switchMode('login')}
                      >
                        {t('connect.login.signInLink')}
                      </Button>
                    </>
                  ) : (
                    <>
                      {t('connect.login.noAccount')}{' '}
                      <Button
                        type="button"
                        variant="ghost"
                        size="sm"
                        onClick={() => switchMode('register')}
                      >
                        {t('connect.login.registerLink')}
                      </Button>
                    </>
                  )}
                </div>
              )}
            </form>
          </Card>
        )}
      </div>
    </div>
  );
}
