import * as git from '../lib/git.js'
import * as branch from '../lib/branch.js'
import * as config from '../lib/config.js'
import * as provider from '../lib/provider.js'
import type { MergeResult, MergeOptions } from './types.js'

export async function execute(
  opts: MergeOptions,
  cwd?: string,
): Promise<MergeResult> {
  try {
    // Get current branch
    const currentBranch = await git.getCurrentBranch(cwd)

    // Detect type
    const branchType = branch.detectBranchType(currentBranch)

    // Block if main/develop/other
    if (branchType === 'main' || branchType === 'develop' || branchType === 'other') {
      return {
        success: false,
        strategy: 'merge',
        target: '',
        branchDeleted: false,
        error: `Cannot merge from ${branchType} branch`,
      }
    }

    // Read config
    const cfg = await config.readConfigForPlatform()

    // Determine default strategy based on branch type
    let strategy: 'squash' | 'merge' = 'squash'
    if (branchType === 'release' || branchType === 'hotfix') {
      strategy = 'merge'
    }

    // Override if explicitly requested
    if (opts.merge) strategy = 'merge'
    if (opts.squash) strategy = 'squash'

    // Determine target branch
    const targetBranch = branch.getTargetBranch(branchType, cfg)

    // Find PR
    const pr = await provider.findPR(currentBranch, cfg.git.provider, cwd)
    if (!pr) {
      return {
        success: false,
        strategy,
        target: targetBranch,
        branchDeleted: false,
        error: `No PR found for branch ${currentBranch}`,
      }
    }

    // Merge PR via provider
    const mergeResult = await provider.mergePR(pr.number, cfg.git.provider, strategy, cwd)
    if (!mergeResult.success) {
      return {
        success: false,
        prNumber: pr.number,
        strategy,
        target: targetBranch,
        branchDeleted: false,
        error: mergeResult.error,
      }
    }

    // Fetch to verify
    await git.fetchAll(cwd)

    // Check if branch was deleted by provider
    const stillExists = await git.branchExists(currentBranch, true, cwd)

    return {
      success: true,
      prNumber: pr.number,
      strategy,
      target: targetBranch,
      branchDeleted: !stillExists,
    }
  } catch (err) {
    const message = err instanceof Error ? err.message : String(err)
    return {
      success: false,
      strategy: 'merge',
      target: '',
      branchDeleted: false,
      error: message,
    }
  }
}
