import { componentName } from '../src/components/descope-new-password';
import { toggleDefaultErrorMessageValueMissingDecorator, withForm } from './helpers';
import {
  sizeControl,
  fullWidthControl,
  directionControl,
  disabledControl,
  readOnlyControl,
  requiredControl,
  borderedControl,
  errorMissingValueControl,
  errorPatternMismatchControl,
  errorBadInputControl,
  minLengthControl,
  inputLabelTypeControl,
  errorMessageIconControl,
  errorMessageIconAttrs,
  defaultValueMissingControl,
} from './commonControls';

// HTML-attribute-escape user-supplied values (and JSON blobs) so quotes in
// e.g. the disallowedchars pattern don't break out of attribute quoting.
const escapeAttr = (v) =>
  String(v ?? '')
    .replace(/&/g, '&amp;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#39;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;');

const policyData = [
  {
    id: 'minlength',
    message: 'At least {{value}} characters',
    pattern: '^.{{{value}},}$',
    data: {
      value: 8,
    },
  },
  {
    id: 'passwordstrength',
    message: 'Password strength',
    compare: 'GTE',
    data: {
      expected: 1,
    },
  },
  {
    id: 'lowercase',
    message: '1 lowercase letter',
    pattern: '[a-z]',
  },
  {
    id: 'uppercase',
    message: '1 uppercase letter',
    pattern: '[A-Z]',
  },
  {
    id: 'anyletter',
    message: '1 letter (any case)',
    pattern: '[a-zA-Z]',
  },
  {
    id: 'number',
    message: '1 number',
    pattern: '\\d',
  },
  {
    id: 'nonalphanumeric',
    message: '1 symbol',
    pattern: '[^a-zA-Z0-9]',
  },
  {
    id: 'disallowedchars',
    message: 'Does not contain: {{value}}',
    pattern: `^[^'"]*$`,
    data: { value: `'"` },
  },
  {
    id: 'disallowemail',
    message: 'Does not match your email',
    compare: 'STR_NEQ_CI',
    data: { expected: 'user@example.com' },
  },
];

const Template = ({
  'password-label': passwordLabel,
  'confirm-label': confirmLabel,
  'password-placeholder': passwordPlaceholder,
  'confirm-placeholder': confirmPlaceholder,
  size,
  bordered,
  direction,
  required,
  minlength,
  'full-width': fullWidth,
  disabled,
  readonly,
  'external-input': externalInput,
  'has-confirm': hasConfirm,
  'has-validation': hasValidation,
  'policy-label': policyLabel,
  'available-policies': availablePolicies,
  'data-password-policy-value-minlength': minLengthDataAttr,
  'data-password-policy-value-passwordstrength': passwordStrengthDataAttr,
  'active-policies': activePolicies,
  'data-errormessage-value-missing': customErrorMissingValue,
  'data-errormessage-pattern-mismatch': customErrorTypeMismatch,
  'data-errormessage-bad-input': customErrorPolicyMismatch,
  'st-policy-preview-background-color': stPolicyPreviewBgColor,
  'st-policy-preview-padding': stPolicyPreviewPadding,
  'label-type': labelType,
  'manual-visibility-toggle': manualVisibilityToggle,
  errorMsgIcon,
}) =>
  `
    <descope-new-password
      size="${size}"
      bordered="${bordered}"
      password-label="${passwordLabel || ''}"
      password-placeholder="${passwordPlaceholder || ''}"
      confirm-label="${confirmLabel || ''}"
      confirm-placeholder="${confirmPlaceholder || ''}"
      has-confirm="${hasConfirm || false}"
      has-validation="${hasValidation || false}"
      required="${required || false}"
      full-width="${fullWidth || false}"
      disabled="${disabled || false}"
      readonly="${readonly || false}"
      minlength="${minlength || ''}"
      data-errormessage-value-missing="${customErrorMissingValue || ''}"
      data-errormessage-pattern-mismatch="${customErrorTypeMismatch || ''}"
      data-errormessage-bad-input="${customErrorPolicyMismatch || ''}"
      data-password-policy-value-minlength="${minLengthDataAttr}"
      data-password-policy-value-passwordstrength="${passwordStrengthDataAttr}"
      st-host-direction="${direction ?? ''}"
      available-policies="${escapeAttr(JSON.stringify(availablePolicies) || '')}"
      active-policies="${activePolicies || ''}"
      policy-label="${policyLabel || ''}"
      st-policy-preview-background-color="${stPolicyPreviewBgColor || ''}"
      st-policy-preview-padding="${stPolicyPreviewPadding || ''}"
      label-type="${labelType || ''}"
      manual-visibility-toggle="${manualVisibilityToggle}"
      external-input="${externalInput || false}"
      ${errorMsgIcon ? errorMessageIconAttrs : ''}
    ></descope-new-password>
  `;

export default {
  component: componentName,
  title: 'descope-new-password',
  decorators: [toggleDefaultErrorMessageValueMissingDecorator, withForm],
  argTypes: {
    ...sizeControl,
    ...inputLabelTypeControl,
    ...fullWidthControl,
    ...disabledControl,
    ...readOnlyControl,
    ...requiredControl,
    ...borderedControl,
    ...errorMissingValueControl,
    ...errorPatternMismatchControl,
    ...errorBadInputControl,
    ...minLengthControl,
    ...directionControl,
    ...errorMessageIconControl,
    ...defaultValueMissingControl,
    'has-confirm': {
      name: 'Has Confirmation',
      control: { type: 'boolean' },
    },
    'password-label': {
      name: 'Password Label',
      control: { type: 'text' },
    },
    'confirm-label': {
      name: 'Confirm Label',
      control: { type: 'text' },
    },
    'password-placeholder': {
      name: 'Password Placeholder',
      control: { type: 'text' },
    },
    'confirm-placeholder': {
      name: 'Confirm Placeholder',
      control: { type: 'text' },
    },
    'has-validation': {
      name: 'Has Validation',
      control: { type: 'boolean' },
    },
    'policy-label': {
      name: 'Policy Label',
      control: { type: 'text' },
    },
    'available-policies': {
      name: 'Available Policies',
      control: { type: 'object' },
    },
    'manual-visibility-toggle': {
      name: 'Manual Visibility Toggle',
      control: { type: 'boolean' },
    },
    'external-input': {
      control: { type: 'boolean' },
    },
  },
};

export const Default = Template.bind({});

Default.args = {
  size: 'md',
  bordered: true,
  'has-validation': false,
  'policy-label': 'Your password must have:',
  'available-policies': policyData,
  'active-policies': [
    'minlength',
    'lowercase',
    'uppercase',
    'anyletter',
    'number',
    'nonalphanumeric',
    'passwordstrength',
    'disallowedchars',
    'disallowemail',
  ],
  'data-password-policy-value-minlength': '8',
  'data-password-policy-value-passwordstrength': '2',
  'st-policy-preview-background-color': 'transparent',
  'st-policy-preview-padding': '0',
  'data-errormessage-value-missing': 'Please fill out this field.',
  'data-errormessage-pattern-mismatch': 'Please match the requested format.',
};
