import { useEffect, useMemo, useState } from 'react';

interface ServerProfile {
  id: string;
  physicalNodeId?: string;
  name: string;
  purpose?: 'personal-fifth-domain' | 'enterprise-lighthouse';
  connected: boolean;
  verified: boolean;
}

interface ServerSession {
  authenticated: boolean;
  nodeId: string;
  username?: string;
}

interface ServerRepository {
  name: string;
  fullName: string;
  private: boolean;
  defaultBranch: string;
}

interface Props {
  open: boolean;
  apiBase: string;
  currentRemote?: string | null;
  initialMode?: 'local' | 'server';
  onClose: () => void;
  onApplied: (result: { mode: 'local' | 'server'; repository?: ServerRepository }) => void;
}

type ServerBridge = {
  list: () => Promise<ServerProfile[]>;
  connect: (nodeId: string) => Promise<ServerProfile>;
  session: (nodeId?: string) => Promise<ServerSession>;
  login: (input: { nodeId: string; username: string; password: string }) => Promise<ServerSession>;
  logout: () => Promise<ServerSession>;
  repositories: () => Promise<ServerRepository[]>;
  createRepository: (input: { name: string; description?: string }) => Promise<ServerRepository>;
  gitRemote: (fullName: string) => Promise<string>;
};

function bridge(): ServerBridge | null {
  return (window as any).hololake?.server || null;
}

export function StorageLocationSheet({ open, apiBase, currentRemote, initialMode, onClose, onApplied }: Props) {
  const [mode, setMode] = useState<'local' | 'server'>(currentRemote ? 'server' : 'local');
  const [servers, setServers] = useState<ServerProfile[]>([]);
  const [selectedNode, setSelectedNode] = useState('');
  const [session, setSession] = useState<ServerSession>({ authenticated: false, nodeId: selectedNode });
  const [repositories, setRepositories] = useState<ServerRepository[]>([]);
  const [selectedRepository, setSelectedRepository] = useState('');
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');
  const [creating, setCreating] = useState(false);
  const [newRepository, setNewRepository] = useState('heartbeat-core-knowledge');
  const [busy, setBusy] = useState(false);
  const [message, setMessage] = useState('');

  const selectedServer = useMemo(
    () => servers.find(server => server.id === selectedNode) || null,
    [servers, selectedNode],
  );

  async function loadRepositories() {
    const server = bridge();
    if (!server) return;
    const next = await server.repositories();
    setRepositories(next);
    setSelectedRepository(previous => previous || next[0]?.fullName || '');
  }

  useEffect(() => {
    if (!open) return;
    setMode(initialMode || (currentRemote ? 'server' : 'local'));
    setMessage('');
    const server = bridge();
    if (!server) {
      setMessage('服务器托管只在 HoloLake 桌面 App 中提供');
      return;
    }
    server.list()
      .then(async profiles => {
        setServers(profiles);
        const personal = profiles.find(profile => profile.purpose === 'personal-fifth-domain');
        const nodeId = selectedNode || personal?.id || '';
        setSelectedNode(nodeId);
        const currentSession = await server.session(nodeId);
        setSession(currentSession);
        if (currentSession.authenticated) {
          setUsername(currentSession.username || '');
          await loadRepositories();
        }
      })
      .catch(error => setMessage(error instanceof Error ? error.message : String(error)));
  }, [open, currentRemote, initialMode]);

  async function selectServer(nodeId: string) {
    const server = bridge();
    setSelectedNode(nodeId);
    setRepositories([]);
    setSelectedRepository('');
    setPassword('');
    setMessage('');
    if (!server) return;
    try {
      const nextSession = await server.session(nodeId);
      setSession(nextSession);
      if (nextSession.authenticated) {
        setUsername(nextSession.username || '');
        await loadRepositories();
      } else {
        setUsername('');
      }
    } catch (error) {
      setMessage(error instanceof Error ? error.message : String(error));
    }
  }

  async function connectServer() {
    const server = bridge();
    if (!server) return;
    setBusy(true);
    setMessage('');
    try {
      const profile = await server.connect(selectedNode);
      setServers(previous => previous.map(item => item.id === profile.id ? profile : item));
      setMessage('服务器连接已验证');
    } catch (error) {
      setMessage(error instanceof Error ? error.message : String(error));
    } finally {
      setBusy(false);
    }
  }

  async function login() {
    const server = bridge();
    if (!server) return;
    setBusy(true);
    setMessage('');
    try {
      const nextSession = await server.login({ nodeId: selectedNode, username, password });
      setPassword('');
      setSession(nextSession);
      await loadRepositories();
      setMessage(`已登录 ${nextSession.username}`);
    } catch (error) {
      setMessage(error instanceof Error ? error.message : String(error));
    } finally {
      setBusy(false);
    }
  }

  async function createRepository() {
    const server = bridge();
    if (!server || !newRepository.trim()) return;
    setBusy(true);
    setMessage('');
    try {
      const created = await server.createRepository({
        name: newRepository.trim(),
        description: 'HoloLake 频道知识库',
      });
      setRepositories(previous => [...previous, created].sort((a, b) => a.name.localeCompare(b.name)));
      setSelectedRepository(created.fullName);
      setCreating(false);
      setMessage(`已建立私有仓库 ${created.fullName}`);
    } catch (error) {
      setMessage(error instanceof Error ? error.message : String(error));
    } finally {
      setBusy(false);
    }
  }

  async function logout() {
    const server = bridge();
    if (!server) return;
    setBusy(true);
    setMessage('');
    try {
      const nextSession = await server.logout();
      setSession(nextSession);
      setRepositories([]);
      setSelectedRepository('');
      setUsername('');
      setMode('local');
      onApplied({ mode: 'local' });
      setMessage('已退出服务器账号，并解除当前知识库的远端连接');
    } catch (error) {
      setMessage(error instanceof Error ? error.message : String(error));
    } finally {
      setBusy(false);
    }
  }

  async function apply() {
    if (mode === 'local') {
      setBusy(true);
      setMessage('');
      try {
        if (currentRemote) {
          const response = await fetch(`${apiBase}/api/forgejo/remote`, { method: 'DELETE' });
          const data = await response.json();
          if (!data.ok) throw new Error(data.error || '解除服务器托管失败');
        }
        onApplied({ mode: 'local' });
        onClose();
      } catch (error) {
        setMessage(error instanceof Error ? error.message : String(error));
      } finally {
        setBusy(false);
      }
      return;
    }
    const server = bridge();
    const repository = repositories.find(item => item.fullName === selectedRepository);
    if (!server || !repository) {
      setMessage(session.authenticated ? '请选择目标仓库' : '请先登录服务器');
      return;
    }
    setBusy(true);
    setMessage('');
    try {
      const remote = await server.gitRemote(repository.fullName);
      const response = await fetch(`${apiBase}/api/forgejo/remote`, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ url: remote }),
      });
      const data = await response.json();
      if (!data.ok) throw new Error(data.error || '连接仓库失败');
      onApplied({ mode: 'server', repository });
      onClose();
    } catch (error) {
      setMessage(error instanceof Error ? error.message : String(error));
    } finally {
      setBusy(false);
    }
  }

  if (!open) return null;

  return (
    <div className="storage-sheet-backdrop" role="presentation" onMouseDown={event => {
      if (event.target === event.currentTarget) onClose();
    }}>
      <section className="storage-sheet" role="dialog" aria-modal="true" aria-labelledby="storage-sheet-title">
        <header className="storage-sheet-header">
          <h2 id="storage-sheet-title">知识库保存位置</h2>
          <button className="icon-button" onClick={onClose} aria-label="关闭保存位置设置">×</button>
        </header>

        <div className="storage-mode-list">
          <label className={`storage-mode-row ${mode === 'local' ? 'selected' : ''}`}>
            <input type="radio" checked={mode === 'local'} onChange={() => setMode('local')} />
            <span><strong>仅保存在本机</strong><small>使用本地 Git 保留历史，不上传服务器</small></span>
          </label>
          <label className={`storage-mode-row ${mode === 'server' ? 'selected' : ''}`}>
            <input type="radio" checked={mode === 'server'} onChange={() => setMode('server')} />
            <span><strong>托管到我的服务器</strong><small>本机保留工作副本，提交到已授权的代码频道</small></span>
          </label>
        </div>

        {mode === 'server' && (
          <div className="storage-server-area">
            <p className="sheet-label">已选择的服务器</p>
            <div className="server-profile-picker">
              <label className="sheet-label" htmlFor="hololake-server-profile">服务器身份</label>
              <select id="hololake-server-profile" value={selectedNode} onChange={event => selectServer(event.target.value)}>
                {servers.map(server => (
                  <option key={server.id} value={server.id}>{server.name}</option>
                ))}
              </select>
            </div>
            <div className="server-profile-row">
              <div className="server-profile-mark" aria-hidden="true"><span /></div>
              <div><strong>{selectedServer?.name || '我的第五域服务器'}</strong><small>{selectedNode}{selectedServer?.physicalNodeId && selectedServer.physicalNodeId !== selectedNode ? ` · ${selectedServer.physicalNodeId}` : ''}</small></div>
              <span className="verified-state">{selectedServer?.connected ? '已连接' : '已验证'}</span>
              {!selectedServer?.connected && <button className="text-button" onClick={connectServer} disabled={busy}>连接</button>}
            </div>

            {!session.authenticated ? (
              <div className="server-login-form">
                <p className="sheet-label">登录服务器代码频道</p>
                <div className="login-fields">
                  <input value={username} onChange={event => setUsername(event.target.value)} placeholder="账号" autoComplete="username" />
                  <input type="password" value={password} onChange={event => setPassword(event.target.value)} placeholder="密码" autoComplete="current-password" onKeyDown={event => {
                    if (event.key === 'Enter') login();
                  }} />
                  <button className="secondary-button" onClick={login} disabled={busy || !username || !password}>登录</button>
                </div>
                <small>密码只用于换取 HoloLake 应用令牌，不写入知识库或 Git 地址。</small>
              </div>
            ) : (
              <div className="repository-picker">
                <div className="repository-picker-heading">
                  <p className="sheet-label">目标仓库</p>
                  <span>已登录 {session.username} <button className="inline-logout" onClick={logout} disabled={busy}>退出账号</button></span>
                </div>
                <div className="repository-picker-row">
                  <select value={selectedRepository} onChange={event => setSelectedRepository(event.target.value)}>
                    <option value="">选择私有仓库</option>
                    {repositories.map(repository => (
                      <option key={repository.fullName} value={repository.fullName}>{repository.fullName}</option>
                    ))}
                  </select>
                  <button className="text-button" onClick={() => setCreating(!creating)}>新建仓库</button>
                </div>
                {creating && (
                  <div className="new-repository-row">
                    <input value={newRepository} onChange={event => setNewRepository(event.target.value)} placeholder="仓库名称" />
                    <button className="secondary-button" onClick={createRepository} disabled={busy}>建立私有仓库</button>
                  </div>
                )}
              </div>
            )}

            <p className="storage-privacy-note">首次上传前会显示文件数量、目标仓库和分支，需要确认后才会推送。</p>
          </div>
        )}

        {message && <div className="sheet-message" role="status">{message}</div>}

        <footer className="storage-sheet-footer">
          <span className="storage-boundary-copy">账号与仓库按服务器隔离</span>
          <span />
          <button className="secondary-button" onClick={onClose}>取消</button>
          <button className="primary-button" onClick={apply} disabled={busy || (mode === 'server' && !session.authenticated)}>
            {busy ? '正在处理…' : '连接并继续'}
          </button>
        </footer>
      </section>
    </div>
  );
}
