package wang.yaojia.webterm.viewmodels

import wang.yaojia.webterm.api.models.CreateWorktreeResult
import wang.yaojia.webterm.api.models.GitLogResult
import wang.yaojia.webterm.api.models.GitWriteOutcome
import wang.yaojia.webterm.api.models.PrStatus
import wang.yaojia.webterm.api.models.ProjectDetail
import wang.yaojia.webterm.api.models.ProjectInfo
import wang.yaojia.webterm.api.models.PruneWorktreesResult
import wang.yaojia.webterm.api.models.RemoveWorktreeResult
import wang.yaojia.webterm.api.models.UiPrefs

/**
 * A configurable [ProjectsGateway] double for the W5 presenter tests (WorktreeViewModel,
 * ProjectDetailViewModel PR/log). Records the guarded-write call args and returns canned outcomes;
 * PR/log return canned values or throw to exercise failure-isolation. The list-page methods
 * (projects/prefs) are unused here and throw if called.
 */
class FakeWorktreeGateway(
    private val detail: ProjectDetail? = null,
    private val prResult: PrStatus? = null,
    private val prThrows: Boolean = false,
    private val logResult: GitLogResult? = null,
    private val logThrows: Boolean = false,
    private val createOutcome: GitWriteOutcome<CreateWorktreeResult> = GitWriteOutcome.Ok(CreateWorktreeResult()),
    private val removeOutcome: GitWriteOutcome<RemoveWorktreeResult> = GitWriteOutcome.Ok(RemoveWorktreeResult()),
    private val pruneOutcome: GitWriteOutcome<PruneWorktreesResult> = GitWriteOutcome.Ok(PruneWorktreesResult()),
) : ProjectsGateway {
    val createCalls = mutableListOf<Triple<String, String, String?>>()
    val removeCalls = mutableListOf<Triple<String, String, Boolean>>()
    val pruneCalls = mutableListOf<String>()
    var detailCalls = 0
        private set

    override suspend fun projects(): List<ProjectInfo> = throw NotImplementedError()
    override suspend fun prefs(): UiPrefs = throw NotImplementedError()
    override suspend fun putPrefs(prefs: UiPrefs): UiPrefs = throw NotImplementedError()

    override suspend fun projectDetail(path: String): ProjectDetail {
        detailCalls++
        return detail ?: throw NotImplementedError("no detail configured")
    }

    override suspend fun projectPr(path: String): PrStatus {
        if (prThrows) throw RuntimeException("pr unavailable")
        return prResult ?: throw NotImplementedError("no pr configured")
    }

    override suspend fun projectLog(path: String, n: Int?): GitLogResult {
        if (logThrows) throw RuntimeException("log unavailable")
        return logResult ?: throw NotImplementedError("no log configured")
    }

    override suspend fun createWorktree(path: String, branch: String, base: String?): GitWriteOutcome<CreateWorktreeResult> {
        createCalls += Triple(path, branch, base)
        return createOutcome
    }

    override suspend fun removeWorktree(path: String, worktreePath: String, force: Boolean): GitWriteOutcome<RemoveWorktreeResult> {
        removeCalls += Triple(path, worktreePath, force)
        return removeOutcome
    }

    override suspend fun pruneWorktrees(path: String): GitWriteOutcome<PruneWorktreesResult> {
        pruneCalls += path
        return pruneOutcome
    }
}
