import { mkdtemp, readFile, rm } from "fs/promises";
import { tmpdir } from "os";
import { join } from "path";
import { tool } from "@opencode-ai/plugin";
import type { ToolDefinition } from "@opencode-ai/plugin";
import type { ToolDeps } from "./deps";
import { failure, ok, serializeError } from "./response";
import { resolveProviderRuntime } from "./workflow-runtime";
import { WORKFLOW_OUTPUT_DIR_ARGUMENT_DESCRIPTION, resolveWorkflowToolOutputDir } from "./workflow-output";
import { CHALLENGE_AUTOMATION_MODES } from "../challenges/types";

const z = tool.schema;
const browserModeSchema = z.enum(["auto", "extension", "managed"]);
const cookiePolicySchema = z.enum(["off", "auto", "required"]);
const challengeAutomationModeSchema = z.enum(CHALLENGE_AUTOMATION_MODES);

async function captureScreenshotBuffer(deps: ToolDeps, url: string): Promise<Buffer | null> {
  let sessionId: string | null = null;
  let captureDir: string | null = null;
  try {
    const launched = await deps.manager.launch({
      headless: true,
      startUrl: url
    });
    sessionId = launched.sessionId;
    captureDir = await mkdtemp(join(tmpdir(), "odb-product-video-shot-"));
    const capturePath = join(captureDir, "capture.png");
    const screenshot = await deps.manager.screenshot(sessionId, { path: capturePath });
    if (typeof screenshot.path === "string" && screenshot.path.length > 0) {
      return await readFile(screenshot.path);
    }
    if (typeof screenshot.base64 === "string" && screenshot.base64.length > 0) {
      return Buffer.from(screenshot.base64, "base64");
    }
    return null;
  } catch {
    return null;
  } finally {
    if (sessionId) {
      await deps.manager.disconnect(sessionId, true).catch(() => {
        // Best effort cleanup.
      });
    }
    if (captureDir) {
      await rm(captureDir, { recursive: true, force: true }).catch(() => {
        // Best effort cleanup.
      });
    }
  }
}

export function createProductVideoRunTool(deps: ToolDeps): ToolDefinition {
  return tool({
    description: "Collect a product presentation asset pack for video/UGC workflows.",
    args: {
      product_url: z.string().optional().describe("Product URL"),
      product_name: z.string().optional().describe("Product name"),
      provider_hint: z.string().optional().describe("Optional provider hint"),
      include_screenshots: z.boolean().optional().describe("Include screenshots (default true)"),
      include_all_images: z.boolean().optional().describe("Include all discovered images (default true)"),
      include_copy: z.boolean().optional().describe("Include product copy extraction (default true)"),
      output_dir: z.string().optional().describe(WORKFLOW_OUTPUT_DIR_ARGUMENT_DESCRIPTION),
      ttl_hours: z.number().int().positive().optional().describe("Artifact retention TTL in hours"),
      timeoutMs: z.number().int().positive().optional().describe("Workflow timeout in milliseconds"),
      browserMode: browserModeSchema.optional().describe("Browser transport mode: auto|extension|managed"),
      useCookies: z.boolean().optional().describe("Enable/disable provider cookie injection for this run"),
      challengeAutomationMode: challengeAutomationModeSchema.optional().describe("Challenge automation mode: off|browser|browser_with_helper"),
      cookiePolicyOverride: cookiePolicySchema.optional().describe("Override cookie policy: off|auto|required")
    },
    async execute(args) {
      try {
        const runtime = await resolveProviderRuntime(deps);
        const { runProductVideoWorkflow } = await import("../providers");
        const includeScreenshots = args.include_screenshots ?? true;
        const result = await runProductVideoWorkflow(runtime, {
          product_url: args.product_url,
          product_name: args.product_name,
          provider_hint: args.provider_hint,
          include_screenshots: includeScreenshots,
          include_all_images: args.include_all_images,
          include_copy: args.include_copy,
          output_dir: resolveWorkflowToolOutputDir(deps, args.output_dir),
          ttl_hours: args.ttl_hours,
          timeoutMs: args.timeoutMs,
          browserMode: args.browserMode,
          useCookies: args.useCookies,
          challengeAutomationMode: args.challengeAutomationMode,
          cookiePolicyOverride: args.cookiePolicyOverride
        }, {
          captureScreenshot: includeScreenshots
            ? async (url) => captureScreenshotBuffer(deps, url)
            : undefined
        });

        return ok(result);
      } catch (error) {
        return failure(serializeError(error).message, "product_video_run_failed");
      }
    }
  });
}
