import { createAction, Property } from '@activepieces/pieces-framework';
import { SESClient, UpdateTemplateCommand } from '@aws-sdk/client-ses';
import { amazonSesAuth } from '../auth';
import {
  getEmailTemplates,
  getEmailTemplate,
  createSESClient,
  validateTemplateContent,
  validateTemplateVariables,
  getTemplateErrorMessage,
  extractTemplateVariables,
  createTemplatePreview,
  compareTemplateContent,
} from '../common/ses-utils';

export const updateEmailTemplate = createAction({
  auth: amazonSesAuth,
  name: 'update_email_template',
  displayName: 'Update Email Template',
  description: 'Modify an existing email template with new content',
  audience: 'both',
  aiMetadata: {
    description:
      'Overwrites an existing Amazon SES email template, replacing its subject and HTML/text content; an optional preserve-unspecified mode keeps the current HTML or text when a field is left blank instead of clearing it. Use to edit a template that already exists, not to create one. Idempotent: repeating the call with the same input leaves the template in the same final state.',
    idempotent: true,
  },
  props: {
    templateName: Property.Dropdown({
      auth: amazonSesAuth,
      displayName: 'Template to Update',
      description: 'Select template to modify',
      required: true,
      refreshers: ['loadCurrentContent'],
      options: async ({ auth }) => {
        if (!auth) {
          return {
            disabled: true,
            options: [],
            placeholder: 'Please authenticate first',
          };
        }
        const templates = await getEmailTemplates(auth.props);

        if (templates.length === 0) {
          return {
            disabled: false,
            placeholder: 'No templates found. Create a template first.',
            options: [],
          };
        }

        return {
          disabled: false,
          options: templates.map((template) => ({
            label: template,
            value: template,
          })),
        };
      },
    }),
    loadCurrentContent: Property.Checkbox({
      displayName: 'Load Current Content',
      description: 'Pre-fill fields with existing template content',
      required: false,
      defaultValue: true,
    }),
    templateFormat: Property.StaticDropdown({
      displayName: 'Template Format',
      description: 'Choose template format',
      required: true,
      defaultValue: 'html',
      options: {
        options: [
          { label: 'HTML', value: 'html' },
          { label: 'Plain Text', value: 'text' },
          { label: 'Both HTML and Text', value: 'both' },
        ],
      },
    }),
    subjectPart: Property.ShortText({
      displayName: 'Subject',
      description: 'Email subject (use {{variable}} for dynamic content)',
      required: true,
    }),
    htmlPart: Property.LongText({
      displayName: 'HTML Content',
      description: 'HTML email content with variables like {{firstName}}',
      required: false,
    }),
    textPart: Property.LongText({
      displayName: 'Text Content',
      description: 'Plain text email content with variables like {{firstName}}',
      required: false,
    }),
    preserveUnspecified: Property.Checkbox({
      displayName: 'Preserve Unspecified Content',
      description: 'Keep existing HTML/text content if not provided',
      required: false,
      defaultValue: false,
    }),
    sampleData: Property.Object({
      displayName: 'Sample Variable Data',
      description: 'Test data for template variables (optional preview)',
      required: false,
    }),
  },
  async run(context) {
    const {
      templateName,
      templateFormat,
      subjectPart,
      htmlPart,
      textPart,
      preserveUnspecified,
      sampleData,
    } = context.propsValue;

    const { accessKeyId, secretAccessKey, region } = context.auth.props;

    const sesClient = createSESClient({ accessKeyId, secretAccessKey, region });

    let currentTemplate = null;
    if (preserveUnspecified) {
      currentTemplate = await getEmailTemplate(
        { accessKeyId, secretAccessKey, region },
        templateName
      );

      if (!currentTemplate) {
        throw new Error(
          `Template "${templateName}" does not exist. Cannot update non-existent template.`
        );
      }
    }

    let finalHtmlPart = htmlPart;
    let finalTextPart = textPart;

    if (preserveUnspecified && currentTemplate) {
      finalHtmlPart = htmlPart || currentTemplate.htmlPart;
      finalTextPart = textPart || currentTemplate.textPart;
    }

    if (templateFormat === 'html' && !finalHtmlPart) {
      throw new Error('HTML content is required when using HTML format');
    }
    if (templateFormat === 'text' && !finalTextPart) {
      throw new Error('Text content is required when using text format');
    }
    if (templateFormat === 'both' && (!finalHtmlPart || !finalTextPart)) {
      throw new Error(
        'Both HTML and text content are required when using both formats'
      );
    }

    validateTemplateContent(finalHtmlPart, finalTextPart);

    const templateVariables = validateTemplateVariables(
      subjectPart,
      finalHtmlPart,
      finalTextPart
    );

    const templateData: any = {
      TemplateName: templateName,
      SubjectPart: subjectPart,
    };

    if (templateFormat === 'html' || templateFormat === 'both') {
      templateData.HtmlPart = finalHtmlPart;
    }
    if (templateFormat === 'text' || templateFormat === 'both') {
      templateData.TextPart = finalTextPart;
    }

    const updateTemplateCommand = new UpdateTemplateCommand({
      Template: templateData,
    });

    try {
      await sesClient.send(updateTemplateCommand);

      let preview: any = {};
      if (
        sampleData &&
        Object.keys(sampleData as Record<string, string>).length > 0
      ) {
        const sampleDataRecord = sampleData as Record<string, string>;
        preview = {
          subject: createTemplatePreview(subjectPart, sampleDataRecord),
          ...(finalHtmlPart && {
            html: createTemplatePreview(finalHtmlPart, sampleDataRecord),
          }),
          ...(finalTextPart && {
            text: createTemplatePreview(finalTextPart, sampleDataRecord),
          }),
        };
      }

      let changes: any = {};
      if (currentTemplate) {
        changes = compareTemplateContent(
          {
            subjectPart: currentTemplate.subjectPart,
            htmlPart: currentTemplate.htmlPart,
            textPart: currentTemplate.textPart,
          },
          {
            subjectPart,
            htmlPart: finalHtmlPart,
            textPart: finalTextPart,
          }
        );
      }

      return {
        success: true,
        templateName,
        message: 'Email template updated successfully',
        format: templateFormat,
        variables: templateVariables,
        variableCount: templateVariables.length,
        ...(Object.keys(preview).length > 0 && { preview }),
        ...(Object.keys(changes).length > 0 && { changes }),
        details: {
          hasHtml: !!finalHtmlPart,
          hasText: !!finalTextPart,
          subjectLength: subjectPart.length,
          htmlLength: finalHtmlPart?.length || 0,
          textLength: finalTextPart?.length || 0,
          preservedContent: preserveUnspecified,
        },
      };
    } catch (error: any) {
      const errorMessage = getTemplateErrorMessage(error, templateName);
      throw new Error(errorMessage);
    }
  },
});
