import { useRef, useState } from 'react';
import { AppModal } from './AppModal';
import { ChangePasswordModal } from './ChangePasswordModal';
import { TimezoneSelect } from '../TimezoneSelect';
import { UserAvatar } from '../UserAvatar';
import { useConnection } from '../../context/ConnectionContext';
import { nearestTimezone } from '../../data/timezones';

const AVATAR_SIZE = 128;

/** Downscale the chosen image to a small square data URL before uploading. */
function fileToAvatarDataUrl(file) {
  return new Promise((resolve, reject) => {
    const url = URL.createObjectURL(file);
    const img = new Image();
    img.onload = () => {
      const canvas = document.createElement('canvas');
      canvas.width = AVATAR_SIZE;
      canvas.height = AVATAR_SIZE;
      const ctx = canvas.getContext('2d');
      // Center-crop to a square before scaling.
      const side = Math.min(img.width, img.height);
      const sx = (img.width - side) / 2;
      const sy = (img.height - side) / 2;
      ctx.drawImage(img, sx, sy, side, side, 0, 0, AVATAR_SIZE, AVATAR_SIZE);
      URL.revokeObjectURL(url);
      resolve(canvas.toDataURL('image/png'));
    };
    img.onerror = () => {
      URL.revokeObjectURL(url);
      reject(new Error('Could not read that image.'));
    };
    img.src = url;
  });
}

function systemTimezone() {
  try {
    return Intl.DateTimeFormat().resolvedOptions().timeZone;
  } catch {
    return 'UTC';
  }
}

export function AccountModal({ onClose }) {
  const {
    loggedIn,
    orgName,
    projectName,
    account,
    updateAccount,
    updateDeviceName,
    uploadAvatar,
  } = useConnection();
  const [draft, setDraft] = useState(() =>
    account
      ? {
          displayName: account.displayName,
          timezone: account.timezone ?? nearestTimezone(systemTimezone()),
          status: account.status,
          deviceName: account.deviceName,
        }
      : null
  );
  // Freshly picked image (data URL) not yet uploaded; null = keep current.
  const [pendingAvatar, setPendingAvatar] = useState(null);
  const [changingPassword, setChangingPassword] = useState(false);
  const [passwordChanged, setPasswordChanged] = useState(false);
  const [saving, setSaving] = useState(false);
  const [saved, setSaved] = useState(false);
  const [error, setError] = useState(null);
  const fileInputRef = useRef(null);

  if (!loggedIn) {
    return (
      <AppModal title="Account" icon="assets/account.svg" onClose={onClose}>
        <p className="app-modal-placeholder">
          Accounts are organization-specific, and you aren&apos;t logged into an organization
          currently. Click the globe to log in, then come back here to set up your account.
        </p>
      </AppModal>
    );
  }

  const setField = (patch) => {
    setDraft((prev) => ({ ...prev, ...patch }));
    setSaved(false);
    setError(null);
  };

  const handlePickAvatar = async (e) => {
    const file = e.target.files?.[0];
    e.target.value = '';
    if (!file) return;
    try {
      setPendingAvatar(await fileToAvatarDataUrl(file));
      setSaved(false);
      setError(null);
    } catch (err) {
      setError(err.message);
    }
  };

  const handleSave = async () => {
    if (saving) return;
    setSaving(true);
    setError(null);
    try {
      // Device rename first — it's the only call that can be rejected
      // (name already taken), and we stop there so nothing else half-saves.
      if (draft.deviceName !== account.deviceName) {
        const result = await updateDeviceName(draft.deviceName);
        if (!result.ok) {
          setError(result.error);
          return;
        }
      }
      const result = await updateAccount({
        displayName: draft.displayName,
        timezone: draft.timezone,
        status: draft.status,
      });
      if (!result.ok) {
        setError(result.error);
        return;
      }
      if (pendingAvatar) {
        const avatarResult = await uploadAvatar(pendingAvatar);
        if (!avatarResult.ok) {
          setError(avatarResult.error);
          return;
        }
        setPendingAvatar(null);
      }
      setSaved(true);
    } finally {
      setSaving(false);
    }
  };

  return (
    <AppModal title="Account" icon="assets/account.svg" onClose={onClose}>
      <div className="settings-section">
        <h3 className="settings-section-title">
          {orgName}
          {projectName ? ` / ${projectName}` : ''} — {account.username}
        </h3>

        <div className="account-avatar-row">
          <UserAvatar
            user={{ avatarUrl: pendingAvatar ?? account.avatarUrl }}
            size={64}
            className="account-avatar-preview"
          />
          <div className="account-avatar-actions">
            <button
              type="button"
              className="confirm-btn confirm-btn--cancel"
              onClick={() => fileInputRef.current?.click()}
            >
              Change Picture…
            </button>
            <button
              type="button"
              className="confirm-btn confirm-btn--cancel"
              onClick={() => setChangingPassword(true)}
            >
              Change Password…
            </button>
            <input
              ref={fileInputRef}
              type="file"
              accept="image/*"
              hidden
              onChange={handlePickAvatar}
            />
          </div>
        </div>

        <label className="settings-row account-field-row">
          <span className="settings-row-label">Username</span>
          <input type="text" className="account-input" value={account.username} readOnly />
        </label>
        <p className="account-field-hint">
          Usernames are set on the server when your account is created and can&apos;t be changed
          here.
        </p>

        <label className="settings-row account-field-row">
          <span className="settings-row-label">Display Name</span>
          <input
            type="text"
            className="account-input"
            value={draft.displayName}
            placeholder={account.username}
            maxLength={16}
            onChange={(e) => setField({ displayName: e.target.value })}
          />
        </label>

        <label className="settings-row account-field-row">
          <span className="settings-row-label">Device Name</span>
          <input
            type="text"
            className="account-input"
            value={draft.deviceName}
            placeholder="e.g. macbook-air"
            onChange={(e) => setField({ deviceName: e.target.value })}
          />
        </label>
        <p className="account-field-hint">
          What this machine is called on this server. Each of your devices is its own workspace —
          a file checked out here can&apos;t be edited from your other devices.
        </p>

        <label className="settings-row account-field-row">
          <span className="settings-row-label">Timezone</span>
          <TimezoneSelect
            className="account-input"
            value={draft.timezone}
            onChange={(timezone) => setField({ timezone })}
          />
        </label>

        <label className="settings-row account-field-row">
          <span className="settings-row-label">Status</span>
          <input
            type="text"
            className="account-input"
            value={draft.status}
            placeholder="What are you working on?"
            onChange={(e) => setField({ status: e.target.value })}
          />
        </label>

        <div className="account-actions">
          {error && <span className="account-error">{error}</span>}
          {saved && !error && <span className="account-saved-note">Saved</span>}
          {passwordChanged && !error && <span className="account-saved-note">Password changed</span>}
          <button
            type="button"
            className="confirm-btn confirm-btn--cancel"
            disabled={saving}
            onClick={handleSave}
          >
            {saving ? 'Saving…' : 'Save Changes'}
          </button>
        </div>
      </div>
      {changingPassword && (
        <ChangePasswordModal
          onClose={(changed) => {
            setChangingPassword(false);
            setPasswordChanged(changed === true);
          }}
        />
      )}
    </AppModal>
  );
}
