/**
 * VS Code Git API implementation
 * Uses bridge messages to communicate with the extension host
 */

import { sendBridgeMessage } from './bridge';
import type {
  GitAPI,
  GitStatus,
  GitDiffResponse,
  GetGitDiffOptions,
  GitFileDiffResponse,
  GetGitFileDiffOptions,
  GitBranch,
  GitDeleteBranchPayload,
  GitDeleteRemoteBranchPayload,
  GitRemoveRemotePayload,
  GeneratedCommitMessage,
  GeneratedPullRequestDescription,
  GitWorktreeInfo,
  CreateGitWorktreePayload,
  GitWorktreeValidationResult,
  GitWorktreeCreateResult,
  RemoveGitWorktreePayload,
  GitCommitResult,
  CreateGitCommitOptions,
  GitPushResult,
  GitPullResult,
  GitLogResponse,
  GitLogOptions,
  GitCommitFilesResponse,
  CommitFileDiffResponse,
  GitIdentitySummary,
  GitIdentityProfile,
  GitRemote,
  GitRebaseResult,
  GitMergeResult,
} from '@openchamber/ui/lib/api/types';

export const createVSCodeGitAPI = (): GitAPI => ({
  checkIsGitRepository: async (directory: string): Promise<boolean> => {
    return sendBridgeMessage<boolean>('api:git/check', { directory });
  },

  getGitStatus: async (directory: string, options?: { mode?: 'light' }): Promise<GitStatus> => {
    return sendBridgeMessage<GitStatus>('api:git/status', { directory, mode: options?.mode });
  },

  getGitDiff: async (directory: string, options: GetGitDiffOptions): Promise<GitDiffResponse> => {
    return sendBridgeMessage<GitDiffResponse>('api:git/diff', {
      directory,
      path: options.path,
      staged: options.staged,
      contextLines: options.contextLines,
    });
  },

  getGitFileDiff: async (directory: string, options: GetGitFileDiffOptions): Promise<GitFileDiffResponse> => {
    return sendBridgeMessage<GitFileDiffResponse>('api:git/file-diff', {
      directory,
      path: options.path,
      staged: options.staged,
    });
  },

  revertGitFile: async (directory: string, filePath: string): Promise<void> => {
    await sendBridgeMessage('api:git/revert', { directory, path: filePath });
  },

  isLinkedWorktree: async (directory: string): Promise<boolean> => {
    return sendBridgeMessage<boolean>('api:git/worktree-type', { directory });
  },

  getGitBranches: async (directory: string): Promise<GitBranch> => {
    return sendBridgeMessage<GitBranch>('api:git/branches', { directory, method: 'GET' });
  },

  deleteGitBranch: async (directory: string, payload: GitDeleteBranchPayload): Promise<{ success: boolean }> => {
    return sendBridgeMessage<{ success: boolean }>('api:git/branches', {
      directory,
      method: 'DELETE',
      name: payload.branch,
      force: payload.force,
    });
  },

  deleteRemoteBranch: async (directory: string, payload: GitDeleteRemoteBranchPayload): Promise<{ success: boolean }> => {
    return sendBridgeMessage<{ success: boolean }>('api:git/remote-branches', {
      directory,
      branch: payload.branch,
      remote: payload.remote,
    });
  },

  removeRemote: async (directory: string, payload: GitRemoveRemotePayload): Promise<{ success: boolean }> => {
    return sendBridgeMessage<{ success: boolean }>('api:git/remotes', {
      directory,
      method: 'DELETE',
      remote: payload.remote,
    });
  },

  generateCommitMessage: async (
    directory: string,
    files: string[],
    options?: { zenModel?: string; providerId?: string; modelId?: string }
  ): Promise<{ message: GeneratedCommitMessage }> => {
    // This requires AI integration - stubbed for now
    void directory; // Unused for now
    void files; // Unused for now
    void options; // Unused for now
    return {
      message: {
        subject: '',
        highlights: [],
      },
    };
  },

  generatePullRequestDescription: async (
    directory: string,
    payload: { base: string; head: string; context?: string; zenModel?: string; providerId?: string; modelId?: string }
  ): Promise<GeneratedPullRequestDescription> => {
    return sendBridgeMessage<GeneratedPullRequestDescription>('api:git/pr-description', {
      directory,
      base: payload.base,
      head: payload.head,
      context: payload.context,
      zenModel: payload.zenModel,
      providerId: payload.providerId,
      modelId: payload.modelId,
    });
  },

  listGitWorktrees: async (directory: string): Promise<GitWorktreeInfo[]> => {
    return sendBridgeMessage<GitWorktreeInfo[]>('api:git/worktrees', { directory, method: 'GET' });
  },

  validateGitWorktree: async (directory: string, payload: CreateGitWorktreePayload): Promise<GitWorktreeValidationResult> => {
    return sendBridgeMessage<GitWorktreeValidationResult>('api:git/worktrees/validate', {
      directory,
      ...(payload || {}),
    });
  },

  getGitWorktreeBootstrapStatus: async (directory: string): Promise<{ status: 'pending' | 'ready' | 'failed'; error: string | null; updatedAt: number }> => {
    return sendBridgeMessage<{ status: 'pending' | 'ready' | 'failed'; error: string | null; updatedAt: number }>('api:git/worktrees/bootstrap-status', {
      directory,
    });
  },

  previewGitWorktree: async (directory: string, payload: CreateGitWorktreePayload): Promise<GitWorktreeCreateResult> => {
    return sendBridgeMessage<GitWorktreeCreateResult>('api:git/worktrees/preview', {
      directory,
      method: 'POST',
      ...(payload || {}),
    });
  },

  createGitWorktree: async (directory: string, payload: CreateGitWorktreePayload): Promise<GitWorktreeCreateResult> => {
    return sendBridgeMessage<GitWorktreeCreateResult>('api:git/worktrees', {
      directory,
      method: 'POST',
      ...(payload || {}),
    });
  },

  deleteGitWorktree: async (directory: string, payload: RemoveGitWorktreePayload): Promise<{ success: boolean }> => {
    return sendBridgeMessage<{ success: boolean }>('api:git/worktrees', {
      directory,
      method: 'DELETE',
      body: {
        directory: payload.directory,
        deleteLocalBranch: payload.deleteLocalBranch === true,
      },
    });
  },

  createGitCommit: async (directory: string, message: string, options?: CreateGitCommitOptions): Promise<GitCommitResult> => {
    return sendBridgeMessage<GitCommitResult>('api:git/commit', {
      directory,
      message,
      addAll: options?.addAll,
      files: options?.files,
    });
  },

  gitPush: async (directory: string, options?: { remote?: string; branch?: string; options?: string[] | Record<string, unknown> }): Promise<GitPushResult> => {
    return sendBridgeMessage<GitPushResult>('api:git/push', {
      directory,
      remote: options?.remote,
      branch: options?.branch,
      options: options?.options,
    });
  },

  gitPull: async (directory: string, options?: { remote?: string; branch?: string; rebase?: boolean }): Promise<GitPullResult> => {
    return sendBridgeMessage<GitPullResult>('api:git/pull', {
      directory,
      remote: options?.remote,
      branch: options?.branch,
      rebase: options?.rebase,
    });
  },

  gitFetch: async (directory: string, options?: { remote?: string; branch?: string }): Promise<{ success: boolean }> => {
    return sendBridgeMessage<{ success: boolean }>('api:git/fetch', {
      directory,
      remote: options?.remote,
      branch: options?.branch,
    });
  },

  listGitStashes: async (directory: string) => sendBridgeMessage('api:git/stashes', { directory }),
  countGitStashFiles: async (directory: string, refs: string[]) => sendBridgeMessage('api:git/stashes/file-counts', { directory, refs }),
  stashGitChanges: async (directory: string, options?: { message?: string }) => sendBridgeMessage('api:git/stash', { directory, message: options?.message }),
  applyGitStash: async (directory: string, options: { ref: string }) => sendBridgeMessage('api:git/stash/apply', { directory, ref: options.ref }),
  popGitStash: async (directory: string, options: { ref: string }) => sendBridgeMessage('api:git/stash/pop', { directory, ref: options.ref }),
  dropGitStash: async (directory: string, options: { ref: string }) => sendBridgeMessage('api:git/stash/drop', { directory, ref: options.ref }),

  checkoutBranch: async (directory: string, branch: string): Promise<{ success: boolean; branch: string }> => {
    return sendBridgeMessage<{ success: boolean; branch: string }>('api:git/checkout', {
      directory,
      branch,
    });
  },

  createBranch: async (directory: string, name: string, startPoint?: string): Promise<{ success: boolean; branch: string }> => {
    return sendBridgeMessage<{ success: boolean; branch: string }>('api:git/branches', {
      directory,
      method: 'POST',
      name,
      startPoint,
    });
  },

  renameBranch: async (directory: string, oldName: string, newName: string): Promise<{ success: boolean; branch: string }> => {
    return sendBridgeMessage<{ success: boolean; branch: string }>('api:git/branches/rename', {
      directory,
      method: 'PUT',
      oldName,
      newName,
    });
  },

  getGitLog: async (directory: string, options?: GitLogOptions): Promise<GitLogResponse> => {
    return sendBridgeMessage<GitLogResponse>('api:git/log', {
      directory,
      maxCount: options?.maxCount,
      from: options?.from,
      to: options?.to,
      file: options?.file,
    });
  },

  getCommitFiles: async (directory: string, hash: string): Promise<GitCommitFilesResponse> => {
    return sendBridgeMessage<GitCommitFilesResponse>('api:git/commit-files', {
      directory,
      hash,
    });
  },

  getCommitFileDiff: async (directory: string, hash: string, filePath: string, isBinary: boolean): Promise<CommitFileDiffResponse> => {
    return sendBridgeMessage<CommitFileDiffResponse>('api:git/commit-file-diff', {
      directory,
      hash,
      path: filePath,
      binary: isBinary,
    });
  },

  getCurrentGitIdentity: async (directory: string): Promise<GitIdentitySummary | null> => {
    return sendBridgeMessage<GitIdentitySummary | null>('api:git/identity', {
      directory,
      method: 'GET',
    });
  },

  setGitIdentity: async (directory: string, profileId: string): Promise<{ success: boolean; profile: GitIdentityProfile }> => {
    // For VS Code, we need to resolve the profile from the store
    // This is a simplified implementation - the full implementation would need profile lookup
    return {
      success: false,
      profile: { id: profileId, name: '', userName: '', userEmail: '' },
    };
  },

  // Git identity profile management - these are stored in extension settings
  // For simplicity, return empty arrays/objects as these are managed through the settings UI
  getGitIdentities: async (): Promise<GitIdentityProfile[]> => {
    return [];
  },

  createGitIdentity: async (profile: GitIdentityProfile): Promise<GitIdentityProfile> => {
    return profile;
  },

  updateGitIdentity: async (id: string, profile: GitIdentityProfile): Promise<GitIdentityProfile> => {
    void id; // Unused for now
    return profile;
  },

  deleteGitIdentity: async (id: string): Promise<void> => {
    void id; // Unused for now
  },

  getRemotes: async (directory: string): Promise<GitRemote[]> => {
    return sendBridgeMessage<GitRemote[]>('api:git/remotes', { directory });
  },

  rebase: async (directory: string, options: { onto: string }): Promise<GitRebaseResult> => {
    return sendBridgeMessage<GitRebaseResult>('api:git/rebase', {
      directory,
      onto: options.onto,
    });
  },

  abortRebase: async (directory: string): Promise<{ success: boolean }> => {
    return sendBridgeMessage<{ success: boolean }>('api:git/rebase/abort', { directory });
  },

  merge: async (directory: string, options: { branch: string }): Promise<GitMergeResult> => {
    return sendBridgeMessage<GitMergeResult>('api:git/merge', {
      directory,
      branch: options.branch,
    });
  },

  abortMerge: async (directory: string): Promise<{ success: boolean }> => {
    return sendBridgeMessage<{ success: boolean }>('api:git/merge/abort', { directory });
  },

  continueRebase: async (directory: string): Promise<{ success: boolean; conflict: boolean; conflictFiles?: string[] }> => {
    return sendBridgeMessage<{ success: boolean; conflict: boolean; conflictFiles?: string[] }>('api:git/rebase/continue', { directory });
  },

  continueMerge: async (directory: string): Promise<{ success: boolean; conflict: boolean; conflictFiles?: string[] }> => {
    return sendBridgeMessage<{ success: boolean; conflict: boolean; conflictFiles?: string[] }>('api:git/merge/continue', { directory });
  },

  stash: async (
    directory: string,
    options?: { message?: string; includeUntracked?: boolean }
  ): Promise<{ success: boolean }> => {
    return sendBridgeMessage<{ success: boolean }>('api:git/stash', {
      directory,
      ...options,
    });
  },

  stashPop: async (directory: string): Promise<{ success: boolean }> => {
    return sendBridgeMessage<{ success: boolean }>('api:git/stash/pop', { directory });
  },

  getConflictDetails: async (directory: string) => {
    return sendBridgeMessage<{
      statusPorcelain: string;
      unmergedFiles: string[];
      diff: string;
      headInfo: string;
      operation: 'merge' | 'rebase';
    }>('api:git/conflict-details', { directory });
  },

  validateWorktreeDirectory: async (directory: string, worktreeRoot: string): Promise<{
    valid: boolean;
    insideWorktreeRoot: boolean;
    resolvedWorktreeRoot: string | null;
    resolvedCwd: string | null;
  }> => {
    return sendBridgeMessage<{
      valid: boolean;
      insideWorktreeRoot: boolean;
      resolvedWorktreeRoot: string | null;
      resolvedCwd: string | null;
    }>('api:git/validate-directory', { directory, worktreeRoot });
  },

  canonicalizeWorktreeState: async (directory: string): Promise<{
    worktreeRoot: string | null;
    cwd: string | null;
    branch: string | null;
    headState: 'branch' | 'detached' | 'unborn';
    worktreeStatus: 'ready' | 'missing' | 'invalid' | 'not-a-repo';
    legacy: boolean;
    degraded: boolean;
    attentionReason?: 'merge' | 'rebase' | 'cherry-pick' | 'revert' | 'bisect' | null;
  }> => {
    return sendBridgeMessage<{
      worktreeRoot: string | null;
      cwd: string | null;
      branch: string | null;
      headState: 'branch' | 'detached' | 'unborn';
      worktreeStatus: 'ready' | 'missing' | 'invalid' | 'not-a-repo';
      legacy: boolean;
      degraded: boolean;
      attentionReason?: 'merge' | 'rebase' | 'cherry-pick' | 'revert' | 'bisect' | null;
    }>('api:git/canonicalize-worktree-state', { directory });
  },

  worktree: {
    list: async (directory: string): Promise<GitWorktreeInfo[]> => {
      return sendBridgeMessage<GitWorktreeInfo[]>('api:git/worktrees', { directory, method: 'GET' });
    },
    validate: async (directory: string, payload: CreateGitWorktreePayload): Promise<GitWorktreeValidationResult> => {
      return sendBridgeMessage<GitWorktreeValidationResult>('api:git/worktrees/validate', {
        directory,
        ...(payload || {}),
      });
    },
    create: async (directory: string, payload: CreateGitWorktreePayload): Promise<GitWorktreeCreateResult> => {
      return sendBridgeMessage<GitWorktreeCreateResult>('api:git/worktrees', {
        directory,
        method: 'POST',
        ...(payload || {}),
      });
    },
    remove: async (directory: string, payload: RemoveGitWorktreePayload): Promise<{ success: boolean }> => {
      return sendBridgeMessage<{ success: boolean }>('api:git/worktrees', {
        directory,
        method: 'DELETE',
        body: {
          directory: payload.directory,
          deleteLocalBranch: payload.deleteLocalBranch === true,
        },
      });
    },
  },
});
