import * as core from "@actions/core";
import { PlatformAdapter, LabelCapability, PrDetailCapability, PlatformError } from "../adapter";
import { RepoContext, OutputEntry, PrDetail } from "../types";
import { normalizeEvent } from "../event-normalizer";
import { writeOutputFile } from "../output";
import { GitCodePrClient } from "./gitcode-pr-client";
import {
    parseIntOrNull,
    parsePrIdFromPayload,
    parsePrDetailFromPayload,
    isPrCommentPayload,
    extractPayloadAction,
    parsePrIdFromInput,
} from "../parse-utils";
import { parseRepository, parsePrIdFromRef } from "../../utils";
import { updatePrLabel as gitcodeUpdatePrLabel, LabelUpdateResult } from "../../label-manager";

/**
 * GitCode 平台适配器。
 */
export class GitCodeAdapter implements PlatformAdapter, LabelCapability, PrDetailCapability {
    readonly id = "gitcode" as const;
    private prClient = new GitCodePrClient();

    detect(env: NodeJS.ProcessEnv): boolean {
        return Boolean(env.ATOMGIT_REPOSITORY);
    }

    resolveContext(env: NodeJS.ProcessEnv, payload?: unknown): RepoContext {
        const repository = env.ATOMGIT_REPOSITORY;
        if (!repository) {
            throw new PlatformError("环境变量 ATOMGIT_REPOSITORY 未设置");
        }
        const repoInfo = parseRepository(repository);
        if (!repoInfo) {
            throw new PlatformError(`ATOMGIT_REPOSITORY 格式无效: ${repository}`);
        }

        const prId =
            parsePrIdFromRef(env.ATOMGIT_REF) ??
            parseIntOrNull(env.MERGE_ID) ??
            parsePrIdFromPayload(payload) ??
            parsePrIdFromInput("PR_NUMBER");

        // 事件名缺失时按 PR 上下文推断(prId 可解析即视为 PR 触发)
        const eventName =
            env.ATOMGIT_EVENT_NAME || (prId != null ? "pull_request" : "unknown");
        const action =
            env.ATOMGIT_EVENT_ACTION ??
            extractPayloadAction(payload) ??
            env.MERGE_REQUEST_ACTION ??
            core.getInput("PR_EVENT_TYPE") ??
            "unknown";

        const prEventType = normalizeEvent(
            this.id,
            eventName,
            action,
            isPrCommentPayload(payload),
        );

        core.debug(
            `[context] eventName=${eventName} action=${action} prId=${prId} `
            + `payload=${payload ? "present" : "null"} prEventType=${prEventType}`,
        );

        return {
            platform: this.id,
            orgName: repoInfo.orgName,
            repoName: repoInfo.repoName,
            prId: prId ?? undefined,
            commitSha: env.ATOMGIT_SHA || undefined,
            prDetail: parsePrDetailFromPayload(payload) ?? undefined,
            prEventType,
            triggerAccount: env.ATOMGIT_ACTOR || undefined,
            rawEvent: { eventName, action },
        };
    }

    writeOutputs(entries: OutputEntry[], env: NodeJS.ProcessEnv): void {
        writeOutputFile(env.ATOMGIT_OUTPUT, entries);
    }

    async updatePrLabel(
        ctx: RepoContext,
        label: string,
        cleanupLabels: string[],
        token: string,
    ): Promise<LabelUpdateResult> {
        return gitcodeUpdatePrLabel(
            ctx.orgName,
            ctx.repoName,
            ctx.prId!,
            label,
            cleanupLabels,
            token,
        );
    }

    async fetchPrDetail(ctx: RepoContext, token: string): Promise<PrDetail | null> {
        return this.prClient.fetchPrDetail(ctx, token);
    }
}