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 { GitHubLabelClient } from "./github-label-client";
import { GitHubPrClient } from "./github-pr-client";
import {
    parsePrIdFromPayload,
    parsePrDetailFromPayload,
    isPrCommentPayload,
    extractPayloadAction,
    parsePrIdFromInput,
} from "../parse-utils";
import { parseRepository, parsePrIdFromRef } from "../../utils";
import { LabelUpdateResult } from "../../label-manager";

/**
 * GitHub Actions 平台适配器。
 */
export class GitHubAdapter implements PlatformAdapter, LabelCapability, PrDetailCapability {
    readonly id = "github" as const;
    private labelClient = new GitHubLabelClient();
    private prClient = new GitHubPrClient();

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

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

        const prId =
            parsePrIdFromRef(env.GITHUB_REF) ??
            parsePrIdFromPayload(payload) ??
            parsePrIdFromInput("PR_NUMBER");

        const eventName = env.GITHUB_EVENT_NAME || "unknown";
        const action =
            extractPayloadAction(payload) ||
            core.getInput("PR_EVENT_TYPE") ||
            "unknown";

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

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

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

    async updatePrLabel(
        ctx: RepoContext,
        label: string,
        cleanupLabels: string[],
        token: string,
    ): Promise<LabelUpdateResult> {
        return this.labelClient.updatePrLabel(ctx, label, cleanupLabels, token);
    }

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