import { useEffect, useState } from 'react';
import { AppModal } from './AppModal';
import { TrustServerModal } from './TrustServerModal';
import { normalizeHandle, useConnection } from '../../context/ConnectionContext';
import { isTauri, selectWorkspaceFolder } from '../../platform';
import { formatSize } from '../../data/fsTree';
import { formatRelativeTime } from '../../data/format';
import { hostFromIp } from '../../data/serverPins';
import { rememberLabel } from './rememberLabel';

const ICONS = {
  active: 'assets/circle_active.svg',
  inactive: 'assets/circle_inactive.svg',
  add: 'assets/circle_add.svg',
};

/**
 * The organization modal. Opened from the globe, it shows the Login page while
 * logged out and the Projects page once an org session exists.
 */
export function ConnectionsModal({ onClose }) {
  const { loggedIn } = useConnection();
  // Escape-to-close lives in AppModal now, which both pages render through.
  return loggedIn ? <ProjectsPage onClose={onClose} /> : <LoginPage onClose={onClose} />;
}

// --- Login page ------------------------------------------------------------

function LoginPage({ onClose }) {
  const {
    orgConnection,
    startupError,
    login,
    trustPrompt,
    pinMismatch,
    acceptTrust,
    declineTrust,
    forgetServerIdentity,
    dismissPinMismatch,
  } = useConnection();
  const [draft, setDraft] = useState(() => ({
    ip: orgConnection?.ip ?? '',
    username: orgConnection?.username ?? '',
    password: '',
    remember: orgConnection?.remember ?? true,
  }));
  // Seeded from the boot-time resume: this page is what a rejected remember-
  // token falls back to, and arriving with an empty form and no explanation
  // would leave the user guessing why they weren't let straight in.
  const [error, setError] = useState(() => startupError ?? null);
  const [busy, setBusy] = useState(false);

  // A remembered connection no longer has a password to prefill: what is
  // stored is a device-bound token the Rust side redeems. So the box starts
  // empty and just SAYS it is remembered. Typing in it, or changing the
  // username or server, makes it an ordinary password box again — which
  // falls out of the value already being empty, with only the placeholder
  // changing.
  const rememberedLabel =
    (orgConnection?.remember &&
      draft.ip.trim() === orgConnection.ip &&
      draft.username.trim() === orgConnection.username &&
      !draft.password &&
      rememberLabel(orgConnection.rememberExpiresAt)) ||
    null;
  const remembered = Boolean(rememberedLabel);
  const placeholder = rememberedLabel ?? 'Password';

  const submit = async () => {
    if (busy) return;
    setBusy(true);
    setError(null);
    const result = await login(draft);
    setBusy(false);
    // deviceLimitReached, trustRequired, and pinMismatch each open their own
    // modal instead of an inline error (see trustPrompt/pinMismatch below).
    if (!result.ok && !result.deviceLimitReached && !result.trustRequired && !result.pinMismatch) {
      setError(result.error);
    }
    // A workspace is already set for the auto-selected project: skip the
    // Projects page and drop straight into it. Otherwise the modal stays
    // open and flips to the Projects page.
    if (result.ok && result.autoOpened) onClose();
  };

  const onKeyDown = (e) => {
    if (e.key === 'Enter') {
      e.preventDefault();
      submit();
    }
  };

  return (
    <>
      <AppModal title="Log in" icon="assets/globe.svg" onClose={onClose}>
        <p className="projects-subtitle">Log into your organization to get started.</p>
        <div className="login-form" onKeyDown={onKeyDown}>
          <input
            type="text"
            className="connection-field"
            value={draft.ip}
            placeholder="IP address (host:port)"
            autoFocus
            onChange={(e) => setDraft({ ...draft, ip: e.target.value })}
          />
          <input
            type="text"
            className="connection-field"
            value={draft.username}
            placeholder="@username"
            onFocus={() => {
              if (!draft.username) setDraft({ ...draft, username: '@' });
            }}
            onBlur={() => {
              if (draft.username === '@') setDraft({ ...draft, username: '' });
            }}
            onChange={(e) => setDraft({ ...draft, username: normalizeHandle(e.target.value) })}
          />
          <input
            type="password"
            className={`connection-field${remembered ? ' connection-field--remembered' : ''}`}
            value={draft.password}
            placeholder={placeholder}
            onChange={(e) => setDraft({ ...draft, password: e.target.value })}
          />
          <label className="remember-row" title="This device stays signed in; your password is not stored">
            <input
              type="checkbox"
              checked={draft.remember}
              onChange={(e) => setDraft({ ...draft, remember: e.target.checked })}
            />
            Remember me
          </label>
          {error && <p className="connection-card-error connection-card-error--flush">{error}</p>}
          <button
            type="button"
            className="connection-action connection-action--login"
            disabled={busy}
            onClick={submit}
          >
            {busy ? 'Logging in…' : 'Log in'}
          </button>
        </div>
      </AppModal>
      {trustPrompt && (
        <TrustServerModal
          mode="trust"
          host={hostFromIp(trustPrompt.creds.ip)}
          cert={trustPrompt.cert}
          onAccept={acceptTrust}
          onDecline={declineTrust}
        />
      )}
      {pinMismatch && (
        <TrustServerModal
          mode="mismatch"
          host={pinMismatch.host}
          onDecline={dismissPinMismatch}
          onForget={() => forgetServerIdentity(pinMismatch.host)}
        />
      )}
    </>
  );
}

// --- Projects page ---------------------------------------------------------

function ProjectCard({ project, isActive, workspacePath, onSelect, onBrowse, onWorkspaceChange }) {
  const subtext = [
    formatSize(project.sizeBytes),
    `${project.memberCount} member${project.memberCount === 1 ? '' : 's'}`,
    `last commit ${formatRelativeTime(project.lastCommitAt)}`,
  ].join(' · ');

  // Committing on every keystroke used to fire off a full workspace scan for
  // whatever prefix the user had typed so far — e.g. typing "/home/alex/x"
  // scans the real "/home/alex" directory the instant that much is typed.
  // Keep the typed value local and only commit on blur/Enter, while still
  // tracking the prop so an external change (Browse…, or another device)
  // overwrites the draft.
  const [draftPath, setDraftPath] = useState(workspacePath);
  useEffect(() => {
    setDraftPath(workspacePath);
  }, [workspacePath]);
  const commitDraft = () => {
    if (draftPath !== workspacePath) onWorkspaceChange(draftPath);
  };

  return (
    <div className={`connection-card project-card${isActive ? ' connection-card--active' : ''}`}>
      <div className="connection-card-main">
        <button
          type="button"
          className="connection-card-status"
          onClick={onSelect}
          aria-label={isActive ? 'Active project' : 'Select project'}
          title={isActive ? 'Active project' : 'Select project'}
        >
          <img src={isActive ? ICONS.active : ICONS.inactive} alt="" />
        </button>

        <div className="connection-card-fields">
          <button type="button" className="project-card-name" onClick={onSelect}>
            {project.name}
          </button>
          <div className="connection-workspace-row">
            <input
              type="text"
              className="connection-field connection-field--workspace"
              value={draftPath}
              placeholder="Workspace folder (none set)"
              onChange={(e) => setDraftPath(e.target.value)}
              onBlur={commitDraft}
              onKeyDown={(e) => {
                if (e.key === 'Enter') {
                  e.preventDefault();
                  commitDraft();
                }
              }}
            />
            {isTauri && (
              <button
                type="button"
                className="connection-action connection-action--browse"
                onClick={onBrowse}
              >
                Browse…
              </button>
            )}
          </div>
          <p className="project-card-subtext">{subtext}</p>
        </div>
      </div>
    </div>
  );
}

function ProjectsPage({ onClose }) {
  const {
    orgName,
    projects,
    activeProjectId,
    selectProject,
    joinProject,
    logout,
    workspacePaths,
    setWorkspacePath,
  } = useConnection();
  const [joining, setJoining] = useState(false);
  const [code, setCode] = useState('');
  const [joinError, setJoinError] = useState(null);
  const [busy, setBusy] = useState(false);

  const handleBrowse = async (projectId) => {
    const folder = await selectWorkspaceFolder();
    if (folder) setWorkspacePath(folder, projectId);
  };

  const submitCode = async () => {
    const trimmed = code.trim();
    if (!trimmed || busy) return;
    setBusy(true);
    setJoinError(null);
    const result = await joinProject(trimmed);
    setBusy(false);
    if (result.ok) {
      setJoining(false);
      setCode('');
    } else {
      setJoinError(result.error ?? 'Invalid code.');
    }
  };

  return (
    <AppModal title={orgName ?? 'Organization'} icon="assets/globe.svg" onClose={onClose}>
      <p className="projects-subtitle">Which project would you like to work on today?</p>

      <div className="connections-list">
        {projects.length === 0 && (
          <p className="app-modal-placeholder">
            You haven&apos;t been added to any projects. Ask an administrator to invite you to one.
          </p>
        )}

        {projects.map((project) => (
          <ProjectCard
            key={project.id}
            project={project}
            isActive={project.id === activeProjectId}
            workspacePath={workspacePaths[project.id] ?? ''}
            onSelect={() => selectProject(project.id)}
            onBrowse={() => handleBrowse(project.id)}
            onWorkspaceChange={(value) => setWorkspacePath(value, project.id)}
          />
        ))}

        {joining ? (
          <div className="project-join-row">
            <input
              type="text"
              className="connection-field"
              value={code}
              placeholder="Enter a project invite code"
              autoFocus
              onChange={(e) => {
                setCode(e.target.value);
                setJoinError(null);
              }}
              onKeyDown={(e) => {
                if (e.key === 'Enter') {
                  e.preventDefault();
                  submitCode();
                }
                if (e.key === 'Escape') {
                  e.stopPropagation();
                  setJoining(false);
                  setCode('');
                  setJoinError(null);
                }
              }}
            />
            <button
              type="button"
              className="connection-action connection-action--browse"
              disabled={busy}
              onClick={submitCode}
            >
              Join
            </button>
          </div>
        ) : (
          <button
            type="button"
            className="connections-add"
            onClick={() => setJoining(true)}
            aria-label="Join a project"
          >
            <img src={ICONS.add} alt="" />
          </button>
        )}
        {joinError && (
          <p className="connection-card-error connection-card-error--flush">{joinError}</p>
        )}
      </div>

      <button type="button" className="projects-logout" onClick={logout}>
        Log out
      </button>
    </AppModal>
  );
}
