import { useCallback, useEffect, useState } from "react";

import {
  checkoutBranch,
  createBranch,
  fetchRepository,
  getRepositoryStatus,
  pullRepository,
  pushRepository,
  type GitStatus,
} from "../api/git_repositories";
import { Icon } from "./icon";
import { MergeDialog } from "./merge-dialog";

interface GitToolbarProps {
  projectId: string;
  repoId: string;
  currentBranch: string;
  branches: string[];
  hasRemote: boolean;
  isMirror: boolean;
  onBranchChange: (branch: string) => void;
  onRefresh: () => void;
}

export const GitToolbar = ({
  projectId,
  repoId,
  currentBranch,
  branches,
  hasRemote,
  isMirror,
  onBranchChange,
  onRefresh,
}: GitToolbarProps) => {
  const [status, setStatus] = useState<GitStatus | null>(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [showNewBranch, setShowNewBranch] = useState(false);
  const [newBranchName, setNewBranchName] = useState("");
  const [newBranchBase, setNewBranchBase] = useState("");
  const [showMergeDialog, setShowMergeDialog] = useState(false);

  const loadStatus = useCallback(async () => {
    try {
      const data = await getRepositoryStatus(projectId, repoId);
      setStatus(data);
      setError(null);
    } catch {
      setError("Failed to load status");
    }
  }, [projectId, repoId]);

  useEffect(() => {
    void loadStatus();
    // Poll status every 5 seconds
    const interval = setInterval(() => void loadStatus(), 5000);
    return () => clearInterval(interval);
  }, [loadStatus]);

  const handleFetch = async () => {
    if (!hasRemote) return;
    setLoading(true);
    try {
      await fetchRepository(projectId, repoId);
      await loadStatus();
    } catch {
      setError("Fetch failed");
    } finally {
      setLoading(false);
    }
  };

  const handlePull = async () => {
    if (!hasRemote) return;
    setLoading(true);
    try {
      await pullRepository(projectId, repoId, currentBranch || undefined);
      await loadStatus();
      onRefresh();
    } catch {
      setError("Pull failed");
    } finally {
      setLoading(false);
    }
  };

  const handlePush = async () => {
    setLoading(true);
    try {
      await pushRepository(projectId, repoId, currentBranch);
      await loadStatus();
    } catch {
      setError("Push failed");
    } finally {
      setLoading(false);
    }
  };

  const handleCheckout = async (branch: string) => {
    setLoading(true);
    try {
      await checkoutBranch(projectId, repoId, branch);
      onBranchChange(branch);
      onRefresh();
    } catch {
      setError("Checkout failed");
    } finally {
      setLoading(false);
    }
  };

  const handleCreateBranch = async () => {
    if (!newBranchName.trim()) return;
    setLoading(true);
    try {
      await createBranch(projectId, repoId, newBranchName, newBranchBase || currentBranch || "HEAD");
      setShowNewBranch(false);
      setNewBranchName("");
      setNewBranchBase("");
      onRefresh();
    } catch {
      setError("Failed to create branch");
    } finally {
      setLoading(false);
    }
  };

  const hasChanges = status && (
    status.modified.length > 0 ||
    status.added.length > 0 ||
    status.deleted.length > 0 ||
    status.untracked.length > 0
  );

  const canSync = hasRemote;

  return (
    <div className="git-toolbar">
      {error && <div className="toolbar-error">{error}</div>}
      {isMirror && (
        <div className="warning-message">
          <Icon name="warning" size="sm" /> This repository is a bare mirror.
          Editing, committing, pulling, and merging are not available.
          Delete and recreate it to enable full workspace features.
        </div>
      )}
      <div className="toolbar-row">
        <div className="toolbar-group">
          <select
            value={currentBranch}
            onChange={(e) => handleCheckout(e.target.value)}
            disabled={loading}
            className="branch-select"
          >
            {branches.map((b) => (
              <option key={b} value={b}>
                {b === currentBranch ? (
                  <>
                    <Icon name="branch" size="sm" /> {b}
                  </>
                ) : (
                  b
                )}
              </option>
            ))}
          </select>
          <button
            className="toolbar-button"
            onClick={() => setShowNewBranch(!showNewBranch)}
            disabled={loading}
            type="button"
          >
            <Icon name="add" size="sm" /> New
          </button>
        </div>

        <div className="toolbar-group">
          <button
            className="toolbar-button"
            onClick={handleFetch}
            disabled={loading || !canSync}
            type="button"
          >
            <Icon name="fetch" size="sm" /> Fetch
          </button>
          <button
            className="toolbar-button"
            onClick={handlePull}
            disabled={loading || !canSync}
            type="button"
          >
            <Icon name="pull" size="sm" /> Pull
            {status?.behind ? <span className="badge">{status.behind}</span> : null}
          </button>
          <button
            className="toolbar-button"
            onClick={handlePush}
            disabled={loading || !canSync || !status?.ahead}
            type="button"
          >
            <Icon name="push" size="sm" /> Push
            {status?.ahead ? <span className="badge">{status.ahead}</span> : null}
          </button>
          <button
            className="toolbar-button"
            onClick={() => setShowMergeDialog(true)}
            disabled={loading}
            type="button"
          >
            <Icon name="merge" size="sm" /> Merge
          </button>
        </div>
      </div>

      {showNewBranch && (
        <div className="toolbar-row new-branch-form">
          <input
            type="text"
            placeholder="Branch name"
            value={newBranchName}
            onChange={(e) => setNewBranchName(e.target.value)}
            className="toolbar-input"
          />
          <select
            value={newBranchBase}
            onChange={(e) => setNewBranchBase(e.target.value)}
            className="toolbar-input"
          >
            <option value="">Base: HEAD</option>
            {branches.map((b) => (
              <option key={b} value={b}>{ b}</option>
            ))}
          </select>
          <button
            className="toolbar-button primary"
            onClick={handleCreateBranch}
            disabled={loading || !newBranchName.trim()}
            type="button"
          >
            <Icon name="add" size="sm" /> Create
          </button>
          <button
            className="toolbar-button"
            onClick={() => setShowNewBranch(false)}
            type="button"
          >
            <Icon name="cancel" size="sm" /> Cancel
          </button>
        </div>
      )}

      {hasChanges && status && (
        <div className="toolbar-row status-summary">
          {status.modified.length > 0 && <span className="status-badge modified"><Icon name="edit" size="sm" /> {status.modified.length} modified</span>}
          {status.added.length > 0 && <span className="status-badge added"><Icon name="add" size="sm" /> {status.added.length} added</span>}
          {status.deleted.length > 0 && <span className="status-badge deleted"><Icon name="delete" size="sm" /> {status.deleted.length} deleted</span>}
          {status.untracked.length > 0 && <span className="status-badge untracked"><Icon name="warning" size="sm" /> {status.untracked.length} untracked</span>}
        </div>
      )}

      <MergeDialog
        projectId={projectId}
        repoId={repoId}
        branches={branches}
        currentBranch={currentBranch}
        isOpen={showMergeDialog}
        onClose={() => setShowMergeDialog(false)}
        onMerge={() => {
          void loadStatus();
          onRefresh();
        }}
      />
    </div>
  );
};
