/*
 * Copyright (c) 2026 by Christian Kellner.
 * Licensed under Apache-2.0 with Commons Clause and Attribution/Naming Clause
 */

import { useState } from 'react';

import { transform } from '../../../../../services/transformer/notificationAdapterTransformer';
import { xhrPost } from '../../../../../services/xhr';
import Help from './NotificationHelpDisplay';
import { useSelector } from '../../../../../services/state/store';
import { Banner, Button, Form, Modal, Select, Switch } from '@douyinfe/semi-ui-19';

import './NotificationAdapterMutator.less';
import { useScreenWidth } from '../../../../../hooks/screenWidth.js';

const sortAdapter = (a, b) => {
  if (a.name < b.name) {
    return -1;
  }
  if (a.name > b.name) {
    return 1;
  }
  return 0;
};

const validate = (selectedAdapter) => {
  const results = [];
  for (let uiElement of Object.values(selectedAdapter.fields || [])) {
    if (uiElement.value == null && !uiElement.optional && uiElement.type !== 'boolean') {
      results.push('All fields are mandatory and must be set.');
      continue;
    }
    if (uiElement.type === 'boolean' && typeof uiElement.value !== 'boolean') {
      uiElement.value = false;
    }
    if (uiElement.type === 'number') {
      const numberValue = parseFloat(uiElement.value);
      if (isNaN(numberValue) || numberValue < 0) {
        results.push('A number field cannot contain anything else and must be > 0.');
        continue;
      }
    }
    if (uiElement.type === 'boolean' && typeof uiElement.value !== 'boolean') {
      results.push('A boolean field cannot be of a different type.');
      continue;
    }
    if (typeof uiElement.value === 'string' && uiElement.value.length === 0 && !uiElement.optional) {
      results.push('All fields are mandatory and must be set.');
    }
  }

  return [...new Set(results)];
};

function spreadPrefilledAdapterWithValues(prefilled, fields) {
  if (prefilled != null && fields != null) {
    Object.keys(fields).forEach((fieldKey) => {
      prefilled.fields[fieldKey].value = fields[fieldKey];
    });
  }
}

export default function NotificationAdapterMutator({
  title,
  description,
  onVisibilityChanged,
  visible = false,
  selected = [],
  editNotificationAdapter,
  onData,
} = {}) {
  const adapter = useSelector((state) => state.notificationAdapter);

  const preFilledSelectedAdapter =
    editNotificationAdapter == null ? null : adapter.find((a) => a.id === editNotificationAdapter.id);

  spreadPrefilledAdapterWithValues(preFilledSelectedAdapter, editNotificationAdapter?.fields);

  const [selectedAdapter, setSelectedAdapter] = useState(preFilledSelectedAdapter);
  const [validationMessage, setValidationMessage] = useState(null);
  const [successMessage, setSuccessMessage] = useState(null);

  const width = useScreenWidth();
  const isMobile = width <= 850;

  const onSubmit = (doStore) => {
    if (doStore) {
      const validationResults = validate(selectedAdapter);
      if (validationResults.length > 0) {
        setValidationMessage(validationResults.join('<br/>'));
        return;
      }

      onData(
        transform({
          id: selectedAdapter.id,
          name: selectedAdapter.name,
          fields: selectedAdapter.fields || {},
        }),
      );

      setSelectedAdapter(null);
      onVisibilityChanged(false);
    } else {
      setSelectedAdapter(null);
      onVisibilityChanged(false);
    }
  };

  const onTry = () => {
    setValidationMessage(null);
    setSuccessMessage(null);

    const validationResults = validate(selectedAdapter);
    if (validationResults.length > 0) {
      setValidationMessage(validationResults.join('<br/>'));
      return;
    }

    xhrPost('/api/jobs/notificationAdapter/try', {
      id: selectedAdapter.id,
      fields: {
        ...selectedAdapter.fields,
      },
    })
      .then(() => {
        setSuccessMessage('It seems like it worked! Please check your service.');
      })
      .catch((error) =>
        setValidationMessage(`This did not work :-( I've received the following error: ${error.json.message}`),
      );
  };

  const setValue = (selectedAdapter, uiElement, key, value) => {
    uiElement.value = value;

    setSelectedAdapter({
      ...selectedAdapter,
      fields: {
        ...selectedAdapter.fields,
        [key]: {
          ...selectedAdapter.fields[key],
          value,
        },
      },
    });
  };

  const getFieldsFor = (selectedAdapter_) => {
    const selectedAdapter = Object.assign({}, selectedAdapter_);

    return Object.keys(selectedAdapter.fields || []).map((key) => {
      const uiElement = selectedAdapter.fields[key];

      return (
        <Form key={key}>
          {uiElement.type === 'boolean' ? (
            <div style={{ display: 'flex', alignItems: 'center', gap: '16px' }}>
              <Switch
              checked={uiElement.value || false}
              onChange={(checked) => {
                setValue(selectedAdapter, uiElement, key, checked);
              }}
            />
              {uiElement.label}
            </div>
          ) : (
            <Form.Input
              style={{ width: '100%' }}
              field={uiElement.label}
              type={uiElement.type}
              initValue={uiElement.value ?? ''}
              placeholder={uiElement.label}
              label={uiElement.label}
              onChange={(value) => {
                setValue(selectedAdapter, uiElement, key, value);
              }}
            />
          )}
        </Form>
      );
    });
  };

  return (
    <Modal
      title={title != null ? title : 'Adding a new Notification Adapter'}
      visible={visible}
      style={{ width: isMobile ? '95%' : '50rem' }}
      onCancel={() => onSubmit(false)}
      footer={
        <div>
          <Button type="secondary" disabled={selectedAdapter == null} style={{ float: 'left' }} onClick={onTry}>
            Try
          </Button>
          <Button theme="light" type="tertiary" onClick={() => onSubmit(false)}>
            Cancel
          </Button>
          <Button theme="solid" type="primary" onClick={() => onSubmit(true)}>
            Save
          </Button>
        </div>
      }
    >
      {description != null ? (
        <p>{description}</p>
      ) : (
        <p>
          When Fredy finds new listings, we like to report them to you. To do so, notification adapter can be
          configured. <br />
          There are multiple ways how Fredy can send new listings to you. Chose your weapon...
        </p>
      )}

      <Select
        filter
        placeholder="Select a notification adapter"
        className="providerMutator__fields"
        value={selectedAdapter == null ? '' : selectedAdapter.id}
        optionList={adapter
          .map((a) => {
            return {
              otherKey: a.id,
              value: a.id,
              label: a.name,
            };
          })
          //filter out those, that have already been selected
          .filter((option) =>
            editNotificationAdapter != null
              ? true
              : selected.find((selectedOption) => selectedOption.id === option.key) == null,
          )
          .sort(sortAdapter)}
        onChange={(value) => {
          setSuccessMessage(null);
          setValidationMessage(null);
          const selectedAdapter = adapter.find((a) => a.id === value);
          setSelectedAdapter(Object.assign({}, selectedAdapter));
        }}
      />
      <br />
      <br />
      {selectedAdapter != null && (
        <>
          <i>{selectedAdapter.description}</i>
          <br />
          <br />
          {selectedAdapter.readme != null && <Help readme={selectedAdapter.readme} />}
          <br />

          {validationMessage != null && (
            <Banner
              fullMode={false}
              type="danger"
              closeIcon={null}
              title={<div style={{ fontWeight: 600, fontSize: '14px', lineHeight: '20px' }}>Error</div>}
              style={{ marginBottom: '1rem' }}
              description={<p dangerouslySetInnerHTML={{ __html: validationMessage }} />}
            />
          )}
          {successMessage != null && (
            <Banner
              fullMode={false}
              type="success"
              closeIcon={null}
              title={<div style={{ fontWeight: 600, fontSize: '14px', lineHeight: '20px' }}>Yay!</div>}
              style={{ marginBottom: '1rem' }}
              description={<p dangerouslySetInnerHTML={{ __html: successMessage }} />}
            />
          )}

          {getFieldsFor(selectedAdapter)}
        </>
      )}
    </Modal>
  );
}
