import { request } from './client'
import type {
  Workspace,
  Worktree,
  CredentialMeta,
  CredentialUpsertBody,
  FileStatus,
  CreateWorkspaceBody,
  UpdateWorkspaceBody,
  CreateWorktreeBody,
  CommitBody,
  CommitResp,
  CommitLog,
  DiffResp,
  DiffParams,
} from './types'

const enc = (v: string) => encodeURIComponent(v)

function diffQuery(params?: DiffParams): string {
  if (!params) return ''
  const q = new URLSearchParams()
  if (params.ref) q.set('ref', params.ref)
  if (params.against) q.set('against', params.against)
  if (params.staged) q.set('staged', 'true')
  if (params.paths) q.set('paths', params.paths)
  if (params.context != null) q.set('context', String(params.context))
  const s = q.toString()
  return s ? `?${s}` : ''
}

export const workspacesApi = {
  // ===== Workspace =====
  list: (projectSlug: string) =>
    request<Workspace[]>(`/api/v1/projects/${enc(projectSlug)}/workspaces/`),
  create: (projectSlug: string, body: CreateWorkspaceBody) =>
    request<Workspace>(`/api/v1/projects/${enc(projectSlug)}/workspaces/`, {
      method: 'POST',
      body,
    }),
  get: (wsID: string) => request<Workspace>(`/api/v1/workspaces/${enc(wsID)}`),
  update: (wsID: string, body: UpdateWorkspaceBody) =>
    request<Workspace>(`/api/v1/workspaces/${enc(wsID)}`, { method: 'PATCH', body }),
  delete: (wsID: string) => request<void>(`/api/v1/workspaces/${enc(wsID)}`, { method: 'DELETE' }),
  sync: (wsID: string) =>
    request<Workspace>(`/api/v1/workspaces/${enc(wsID)}/sync`, { method: 'POST' }),

  // ===== Credential =====
  upsertCredential: (wsID: string, body: CredentialUpsertBody) =>
    request<CredentialMeta>(`/api/v1/workspaces/${enc(wsID)}/credential`, {
      method: 'PUT',
      body,
    }),
  getCredential: (wsID: string) =>
    request<CredentialMeta>(`/api/v1/workspaces/${enc(wsID)}/credential`),

  // ===== Worktree =====
  listWorktrees: (wsID: string) => request<Worktree[]>(`/api/v1/workspaces/${enc(wsID)}/worktrees`),
  createWorktree: (wsID: string, body: CreateWorktreeBody) =>
    request<Worktree>(`/api/v1/workspaces/${enc(wsID)}/worktrees`, { method: 'POST', body }),
  deleteWorktree: (wtID: string) =>
    request<void>(`/api/v1/worktrees/${enc(wtID)}`, { method: 'DELETE' }),
  acquire: (wtID: string) =>
    request<Worktree>(`/api/v1/worktrees/${enc(wtID)}/acquire`, { method: 'POST' }),
  release: (wtID: string) =>
    request<Worktree>(`/api/v1/worktrees/${enc(wtID)}/release`, { method: 'POST' }),

  listBranches: (wsID: string): Promise<string[]> =>
    request<{ branches: string[] }>(`/api/v1/workspaces/${enc(wsID)}/branches`).then(
      (r) => r.branches,
    ),

  // ===== Git ops =====
  statusOnMain: (wsID: string) =>
    request<FileStatus[]>(`/api/v1/workspaces/${enc(wsID)}/main/status`),
  commitOnMain: (wsID: string, body: CommitBody) =>
    request<CommitResp>(`/api/v1/workspaces/${enc(wsID)}/main/commit`, { method: 'POST', body }),
  pushOnMain: (wsID: string) =>
    request<void>(`/api/v1/workspaces/${enc(wsID)}/main/push`, { method: 'POST' }),
  logOnMain: (wsID: string, n = 50) =>
    request<CommitLog[]>(`/api/v1/workspaces/${enc(wsID)}/main/log?n=${n}`),
  statusOnWorktree: (wtID: string) =>
    request<FileStatus[]>(`/api/v1/worktrees/${enc(wtID)}/status`),
  commitOnWorktree: (wtID: string, body: CommitBody) =>
    request<CommitResp>(`/api/v1/worktrees/${enc(wtID)}/commit`, { method: 'POST', body }),
  pushOnWorktree: (wtID: string) =>
    request<void>(`/api/v1/worktrees/${enc(wtID)}/push`, { method: 'POST' }),
  logOnWorktree: (wtID: string, n = 50) =>
    request<CommitLog[]>(`/api/v1/worktrees/${enc(wtID)}/log?n=${n}`),

  // ===== Diff =====
  diff: (wsID: string, params?: DiffParams) =>
    request<DiffResp>(`/api/v1/workspaces/${enc(wsID)}/diff${diffQuery(params)}`),
  diffOnWorktree: (wtID: string, params?: DiffParams) =>
    request<DiffResp>(`/api/v1/worktrees/${enc(wtID)}/diff${diffQuery(params)}`),
}
