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 * as worktree from '../lib/worktree.js'
import type { PrResult, PrOptions } from './types.js'

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

    // Block if on main/develop
    const branchType = branch.detectBranchType(currentBranch)
    if (branchType === 'main' || branchType === 'develop') {
      return {
        success: false,
        provider: 'unknown',
        title: '',
        source: currentBranch,
        target: '',
        draft: opts.draft,
        error: `Cannot create PR from ${branchType} branch`,
      }
    }

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

    // Push unpushed commits
    const aheadBehind = await git.getAheadBehind(currentBranch, `origin/${currentBranch}`, cwd)
    if (aheadBehind.ahead > 0) {
      const pushResult = await git.push(currentBranch, cwd, false, false)
      if (pushResult.exitCode !== 0) {
        return {
          success: false,
          provider: cfg.git.provider,
          title: '',
          source: currentBranch,
          target: branch.getTargetBranch(branchType, cfg),
          draft: opts.draft,
          error: `Failed to push commits: ${pushResult.stderr || pushResult.stdout}`,
        }
      }
    }

    // Check for existing PR
    const existingPR = await provider.findPR(currentBranch, cfg.git.provider, cwd)
    if (existingPR) {
      return {
        success: true,
        provider: cfg.git.provider,
        prNumber: existingPR.number,
        prUrl: existingPR.url,
        title: existingPR.title,
        source: currentBranch,
        target: existingPR.target,
        draft: opts.draft,
      }
    }

    // Generate title from git log
    const logs = await git.getLog(1, '%s', cwd)
    let title = logs[0] || 'PR from ' + currentBranch

    // Add prefix based on branch type
    if (branchType === 'release' && !title.startsWith('Release ')) {
      const versionMatch = currentBranch.match(/release\/(.+)/)
      title = versionMatch ? `Release ${versionMatch[1]}` : title
    } else if (branchType === 'hotfix' && !title.startsWith('Hotfix:')) {
      title = `Hotfix: ${title}`
    }

    // Generate body from recent commits
    const recentLogs = await git.getLog(5, '%h %s', cwd)
    const body = recentLogs.join('\n')

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

    // Create PR via provider
    const prOptions = {
      title,
      body,
      source: currentBranch,
      target: targetBranch,
      draft: opts.draft,
      provider: cfg.git.provider,
      ...(cfg.git.provider === 'azuredevops' ? { azure: provider.parseAzureDevOpsUrl(cfg.repository.remoteUrl) as any } : {}),
    }

    const createResult = await provider.createPR(prOptions, cwd)
    if (!createResult.success) {
      return {
        success: false,
        provider: cfg.git.provider,
        title,
        source: currentBranch,
        target: targetBranch,
        draft: opts.draft,
        error: createResult.error,
      }
    }

    return {
      success: true,
      provider: cfg.git.provider,
      prNumber: createResult.pr!.number,
      prUrl: createResult.pr!.url,
      title: createResult.pr!.title,
      source: currentBranch,
      target: targetBranch,
      draft: opts.draft,
      buildPassed: true,
    }
  } catch (err) {
    const message = err instanceof Error ? err.message : String(err)
    return {
      success: false,
      provider: 'unknown',
      title: '',
      source: '',
      target: '',
      draft: opts.draft,
      error: message,
    }
  }
}
