'use client';

import { useCallback, useEffect, useMemo, useState } from 'react';
import ShareScopeSelector from './share-scope-selector.jsx';
import { useProjectAlbum } from './project-album-context.jsx';

// read → Viewer, write → Editor, admin → Admin. The wire values stay
// read/write/admin (the API + ACL domain); these are display labels only.
const PERMISSION_OPTIONS = [
  { value: 'read', label: 'Viewer' },
  { value: 'write', label: 'Editor' },
  { value: 'admin', label: 'Admin' },
];
const PERMISSION_LABEL = Object.fromEntries(PERMISSION_OPTIONS.map((o) => [o.value, o.label]));

function memberLabel(members, userId) {
  const m = members.find((x) => x.user_id === userId);
  if (!m) return { name: userId, sub: 'Unknown member' };
  return { name: m.display_name || m.email || userId, sub: m.display_name ? (m.email || '') : '' };
}

export default function ProjectShareControls({ projectId, projectName }) {
  const { shareData } = useProjectAlbum();
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState('');
  const [busy, setBusy] = useState('');           // tracks the in-flight action key
  const [visibility, setVisibility] = useState('private');
  const [savedVisibility, setSavedVisibility] = useState(null);
  const [pickUser, setPickUser] = useState('');
  const [pickPerm, setPickPerm] = useState('read');

  const load = useCallback(async ({ force = false } = {}) => {
    setLoading(true);
    setError('');
    try {
      const next = await shareData.readProjectShareData(projectId, { force });
      setData(next);
      const vis = next?.status?.shared ? (next.status.visibility || 'org') : 'private';
      setVisibility(vis);
      setSavedVisibility(next?.status?.shared ? vis : null);
    } catch {
      setError('Failed to load sharing settings.');
    } finally {
      setLoading(false);
    }
  }, [projectId, shareData]);

  useEffect(() => { load(); }, [load]);

  const shared = !!data?.status?.shared;
  const cloudReady = !!data?.cloudReady;
  const grants = data?.grants || [];
  const members = data?.members || [];

  // Members not yet granted (and never the current org-principal row).
  const grantedUserIds = useMemo(
    () => new Set(grants.filter((g) => g.principal_type === 'user').map((g) => g.principal_id)),
    [grants],
  );
  const availableMembers = useMemo(
    () => members.filter((m) => !grantedUserIds.has(m.user_id)),
    [members, grantedUserIds],
  );

  const refresh = useCallback(async () => {
    shareData.invalidateProjectShareData(projectId);
    await load({ force: true });
  }, [shareData, projectId, load]);

  async function publishWithVisibility(nextVisibility) {
    setBusy('publish');
    setError('');
    try {
      const res = await fetch('/api/shared/spaces/publish', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ space_type: 'project', project_id: projectId, visibility: nextVisibility }),
      });
      if (!res.ok) {
        const d = await res.json().catch(() => ({}));
        setError(d.error || 'Failed to update sharing.');
        return;
      }
      await refresh();
    } catch {
      setError('Network error.');
    } finally {
      setBusy('');
    }
  }

  async function grant(userId, permission) {
    setBusy(`grant:${userId}`);
    setError('');
    try {
      const res = await fetch(`/api/shared/spaces/${encodeURIComponent(projectId)}/acl`, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ space_type: 'project', principal_type: 'user', principal_id: userId, permission }),
      });
      if (!res.ok) {
        const d = await res.json().catch(() => ({}));
        setError(d.error || 'Failed to grant access.');
        return;
      }
      setPickUser('');
      setPickPerm('read');
      await refresh();
    } catch {
      setError('Network error.');
    } finally {
      setBusy('');
    }
  }

  async function revoke(userId) {
    setBusy(`revoke:${userId}`);
    setError('');
    try {
      const res = await fetch(`/api/shared/spaces/${encodeURIComponent(projectId)}/acl`, {
        method: 'DELETE',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ space_type: 'project', principal_type: 'user', principal_id: userId }),
      });
      if (!res.ok) {
        const d = await res.json().catch(() => ({}));
        setError(d.error || 'Failed to revoke access.');
        return;
      }
      await refresh();
    } catch {
      setError('Network error.');
    } finally {
      setBusy('');
    }
  }

  if (loading) {
    return (
      <div className="share-panel-section">
        <div className="share-panel-skeleton" />
        <div className="share-panel-skeleton" />
        <div className="share-panel-skeleton short" />
      </div>
    );
  }

  if (!cloudReady) {
    return (
      <div className="share-panel-section">
        {error ? <div className="share-panel-error">{error}</div> : null}
        <div className="share-panel-notice">
          <NoticeIcon />
          <div>
            <strong>Org sharing isn’t configured</strong>
            <p>Connect your organization’s shared workspace to grant teammates access to this project. Files stay on this machine — only metadata is shared.</p>
          </div>
        </div>
      </div>
    );
  }

  const userGrants = grants.filter((g) => g.principal_type === 'user');

  return (
    <>
      {error ? <div className="share-panel-error">{error}</div> : null}

      <ShareScopeSelector
        kind="project"
        scope={visibility}
        aclScope={savedVisibility}
        saveStatus={busy === 'publish' ? 'saving' : ''}
        onScopeChange={setVisibility}
        onSave={() => publishWithVisibility(visibility)}
        saveLabel={shared ? 'Update visibility' : 'Share to organization'}
      />

      {!shared ? (
        <section className="share-panel-section">
          <p className="share-panel-empty">
            Share this project to your organization to grant specific members access. Only resource
            metadata (names, folders, types) is shared — file contents never leave this machine.
          </p>
        </section>
      ) : (
        <section className="share-panel-section">
          <p className="share-panel-section-title">People with access</p>

          <div className="share-panel-grant-add">
            <select
              aria-label="Select a member to grant access"
              value={pickUser}
              onChange={(e) => setPickUser(e.target.value)}
              disabled={!availableMembers.length}
            >
              <option value="">{availableMembers.length ? 'Add a member…' : 'No more members to add'}</option>
              {availableMembers.map((m) => (
                <option key={m.user_id} value={m.user_id}>
                  {m.display_name || m.email || m.user_id}
                </option>
              ))}
            </select>
            <select aria-label="Permission level" value={pickPerm} onChange={(e) => setPickPerm(e.target.value)} disabled={!pickUser}>
              {PERMISSION_OPTIONS.map((o) => <option key={o.value} value={o.value}>{o.label}</option>)}
            </select>
            <button
              type="button"
              className="share-panel-primary-button"
              onClick={() => grant(pickUser, pickPerm)}
              disabled={!pickUser || busy === `grant:${pickUser}`}
            >
              {busy === `grant:${pickUser}` ? 'Adding…' : 'Add'}
            </button>
          </div>

          {userGrants.length ? (
            <ul className="share-panel-grant-list">
              {userGrants.map((g) => {
                const who = memberLabel(members, g.principal_id);
                return (
                  <li key={g.id || g.principal_id} className="share-panel-grant-row">
                    <div className="share-panel-grant-who">
                      <span>{who.name}</span>
                      {who.sub ? <small>{who.sub}</small> : null}
                    </div>
                    <div className="share-panel-grant-actions">
                      <select
                        aria-label={`Permission for ${who.name}`}
                        value={g.permission}
                        onChange={(e) => grant(g.principal_id, e.target.value)}
                        disabled={busy === `grant:${g.principal_id}`}
                      >
                        {PERMISSION_OPTIONS.map((o) => <option key={o.value} value={o.value}>{o.label}</option>)}
                      </select>
                      <button
                        type="button"
                        className="share-panel-revoke-button"
                        onClick={() => revoke(g.principal_id)}
                        disabled={busy === `revoke:${g.principal_id}`}
                      >
                        {busy === `revoke:${g.principal_id}` ? 'Removing…' : 'Remove'}
                      </button>
                    </div>
                  </li>
                );
              })}
            </ul>
          ) : (
            <p className="share-panel-empty">
              No individual grants yet.{visibility === 'org' ? ' Everyone in your organization already has read access.' : ' Add a member above to give them access.'}
            </p>
          )}
        </section>
      )}
    </>
  );
}

function NoticeIcon() {
  return (
    <svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
      <circle cx="8" cy="8" r="6.25" />
      <path d="M8 5v3.5" />
      <path d="M8 10.6h.01" />
    </svg>
  );
}
