import { z } from 'zod';
import { Effect } from 'effect';

/**
 * OpenCode Plugin Types
 *
 * Minimal type definitions needed for the plugin.
 * Based on @opencode-ai/plugin package types.
 */

type Part = {
    type: 'text' | 'image' | 'file' | 'tool_use' | 'tool_result';
    text?: string;
    [key: string]: unknown;
};
type UserMessage = {
    id: string;
    sessionID: string;
    role: 'user';
    [key: string]: unknown;
};
type Message = {
    id: string;
    sessionID: string;
    role: 'user' | 'assistant';
    [key: string]: unknown;
};
type Model = {
    providerID: string;
    modelID: string;
    [key: string]: unknown;
};
type Project = {
    id: string;
    path: string;
    [key: string]: unknown;
};
type PluginInput = {
    client: unknown;
    project: Project;
    directory: string;
    worktree: string;
    serverUrl: URL;
    $: unknown;
};

type ToolContext = {
    sessionID: string;
    messageID: string;
    agent: string;
    directory: string;
    worktree: string;
    abort: AbortSignal;
    metadata(input: {
        title?: string;
        metadata?: Record<string, unknown>;
    }): void;
    ask(input: {
        permission: string;
        patterns: string[];
        always: string[];
        metadata: Record<string, unknown>;
    }): Effect.Effect<void>;
};
type ToolDefinition = {
    description: string;
    args: z.ZodRawShape;
    execute(args: unknown, context: ToolContext): Promise<string>;
};
type SessionCompactedEvent = {
    type: 'session.compacted';
    properties: {
        sessionID: string;
    };
};
type SessionIdleEvent = {
    type: 'session.idle';
    properties: {
        sessionID: string;
    };
};
type OtherEvent = {
    type: string;
    properties: Record<string, unknown>;
};
type BusEvent = SessionCompactedEvent | SessionIdleEvent | OtherEvent;
interface Hooks {
    event?: (input: {
        event: BusEvent;
    }) => Promise<void>;
    config?: (input: unknown) => Promise<void>;
    tool?: {
        [key: string]: ToolDefinition;
    };
    auth?: unknown;
    /**
     * Called when a new message is received
     */
    'chat.message'?: (input: {
        sessionID: string;
        agent?: string;
        model?: {
            providerID: string;
            modelID: string;
        };
        messageID?: string;
        variant?: string;
    }, output: {
        message: UserMessage;
        parts: Part[];
    }) => Promise<void>;
    /**
     * Modify parameters sent to LLM
     */
    'chat.params'?: (input: {
        sessionID: string;
        agent: string;
        model: Model;
        provider: unknown;
        message: UserMessage;
    }, output: {
        temperature: number;
        topP: number;
        topK: number;
        options: Record<string, unknown>;
    }) => Promise<void>;
    'chat.headers'?: (input: {
        sessionID: string;
        agent: string;
        model: Model;
        provider: unknown;
        message: UserMessage;
    }, output: {
        headers: Record<string, string>;
    }) => Promise<void>;
    'permission.ask'?: (input: unknown, output: {
        status: 'ask' | 'deny' | 'allow';
    }) => Promise<void>;
    'command.execute.before'?: (input: {
        command: string;
        sessionID: string;
        arguments: string;
    }, output: {
        parts: Part[];
    }) => Promise<void>;
    'tool.execute.before'?: (input: {
        tool: string;
        sessionID: string;
        callID: string;
    }, output: {
        args: Record<string, unknown>;
    }) => Promise<void>;
    'shell.env'?: (input: {
        cwd: string;
        sessionID?: string;
        callID?: string;
    }, output: {
        env: Record<string, string>;
    }) => Promise<void>;
    'tool.execute.after'?: (input: {
        tool: string;
        sessionID: string;
        callID: string;
        args: unknown;
    }, output: {
        title: string;
        output: string;
        metadata: unknown;
    }) => Promise<void>;
    'experimental.chat.messages.transform'?: (input: Record<string, never>, output: {
        messages: {
            info: Message;
            parts: Part[];
        }[];
    }) => Promise<void>;
    'experimental.chat.system.transform'?: (input: {
        sessionID?: string;
        model: Model;
    }, output: {
        system: string[];
    }) => Promise<void>;
    /**
     * Called before session compaction starts. Allows plugins to customize
     * the compaction prompt.
     */
    'experimental.session.compacting'?: (input: {
        sessionID: string;
    }, output: {
        context: string[];
        prompt?: string;
    }) => Promise<void>;
    'experimental.text.complete'?: (input: {
        sessionID: string;
        messageID: string;
        partID: string;
    }, output: {
        text: string;
    }) => Promise<void>;
    /**
     * Modify tool definitions (description and parameters) sent to LLM
     */
    'tool.definition'?: (input: {
        toolID: string;
    }, output: {
        description: string;
        parameters: unknown;
    }) => Promise<void>;
}
type Plugin = (input: PluginInput) => Promise<Hooks>;
type PluginModule = {
    id?: string;
    server: Plugin;
    tui?: never;
};

/**
 * OpenCode Workflows Plugin
 *
 * Integrates workflows-core state management with OpenCode hooks to provide
 * phase-aware development guidance and file edit restrictions.
 *
 * Hooks implemented:
 * 1. chat.message - Add synthetic part with phase instructions after each user message
 * 2. tool.execute.before - Block editing of certain files based on phase
 * 3. experimental.session.compacting - Inject workflow state into compaction context
 *
 * Logs are sent via OpenCode SDK's client.app.log() API
 */

/**
 * Main plugin export
 */
declare const WorkflowsPlugin: Plugin;
declare const _default: {
    id: string;
    server: Plugin;
};

export { type BusEvent, type Hooks, type Message, type Model, type OtherEvent, type Part, type Plugin, type PluginInput, type PluginModule, type Project, type SessionCompactedEvent, type SessionIdleEvent, type ToolContext, type ToolDefinition, type UserMessage, WorkflowsPlugin, _default as default };
