import { v } from 'convex/values';

import { internal } from '../../../_generated/api';
import { jsonRecordValidator } from '../../../lib/validators/json';
import type { ActionDefinition } from '../../helpers/nodes/action/types';
import type { WebsiteActionParams } from './helpers/types';

// Common field validators
const statusValidator = v.optional(
  v.union(
    v.literal('idle'),
    v.literal('scanning'),
    v.literal('active'),
    v.literal('error'),
  ),
);

export const websiteAction: ActionDefinition<WebsiteActionParams> = {
  type: 'website',
  title: 'Website Operation',
  description:
    'Execute website-specific operations (create, update, get_by_domain). organizationId is automatically read from workflow context variables.',

  parametersValidator: v.union(
    // create: Create a new website
    v.object({
      operation: v.literal('create'),
      domain: v.string(),
      title: v.optional(v.string()),
      description: v.optional(v.string()),
      scanInterval: v.optional(v.string()),
      lastScannedAt: v.optional(v.number()),
      status: statusValidator,
      metadata: v.optional(jsonRecordValidator),
    }),
    // update: Update an existing website
    v.object({
      operation: v.literal('update'),
      websiteId: v.id('websites'),
      domain: v.optional(v.string()),
      title: v.optional(v.string()),
      description: v.optional(v.string()),
      scanInterval: v.optional(v.string()),
      lastScannedAt: v.optional(v.number()),
      status: statusValidator,
      metadata: v.optional(jsonRecordValidator),
    }),
    // get_by_domain: Get a website by domain
    v.object({
      operation: v.literal('get_by_domain'),
      domain: v.string(),
    }),
  ),

  async execute(ctx, params, variables) {
    // Read organizationId from workflow context variables with proper type validation
    const organizationId = variables.organizationId;
    if (typeof organizationId !== 'string' || !organizationId) {
      throw new Error(
        'website action requires a non-empty string organizationId in workflow context',
      );
    }

    switch (params.operation) {
      case 'create': {
        const _websiteId = await ctx.runMutation(
          internal.websites.internal_mutations.provisionWebsite,
          {
            organizationId,
            domain: params.domain, // Required by validator
            title: params.title,
            description: params.description,
            scanInterval: params.scanInterval || '6h',
            status: params.status || 'active',
            metadata: params.metadata,
          },
        );

        // Fetch and return the full created entity
        // Note: execute_action_node wraps this in output: { type: 'action', data: result }
        const createdWebsite = await ctx.runQuery(
          internal.websites.internal_queries.getWebsiteByDomain,
          { organizationId, domain: params.domain },
        );

        if (!createdWebsite) {
          throw new Error(
            `Failed to fetch created website with domain "${params.domain}"`,
          );
        }

        return createdWebsite;
      }

      case 'update': {
        // Note: execute_action_node wraps this in output: { type: 'action', data: result }
        const result = await ctx.runMutation(
          internal.websites.internal_mutations.patchWebsite,
          {
            websiteId: params.websiteId, // Required by validator
            domain: params.domain,
            title: params.title,
            description: params.description,
            scanInterval: params.scanInterval,
            lastScannedAt: params.lastScannedAt,
            status: params.status,
            metadata: params.metadata,
          },
        );

        return result;
      }

      case 'get_by_domain': {
        // Note: organizationId is already validated at the start of execute()

        // Note: execute_action_node wraps this in output: { type: 'action', data: result }
        const result = await ctx.runQuery(
          internal.websites.internal_queries.getWebsiteByDomain,
          {
            organizationId,
            domain: params.domain, // Required by validator
          },
        );

        return result;
      }

      default:
        throw new Error(
          `Unknown operation: ${(params as { operation: string }).operation}`,
        );
    }
  },
};
