import './App.css'
import * as FluentUI from '@fluentui/react';
import type { IElixFormsComponentFormState } from './IElixFormsComponentFormState';
import type { IElixFormsComponentProperties } from './IElixFormsComponentProperties';
import { ElixFormsElement } from './ElixFormsElement';
import { QueryParamHelper } from './QueryParamHelper';
import { Component, type FormEvent, type JSX, useState } from 'react';
import React from 'react';
import type { IElixFormsComponentCustomFormFieldFactory } from './IElixFormsComponentCustomFormFieldFactory';
import type { ElixFormsCheckboxOption, ElixFormsDropdownOption, ElixFormsRadioOption } from './ElixFormsTypes';

export default abstract class ElixFormsComponentAbstract extends Component<IElixFormsComponentProperties, IElixFormsComponentFormState> {
  constructor(props: IElixFormsComponentProperties) {
    super(props);

    this.state = {
      formData: {}
    };

    // const [formData, setFormData] = useState({});
    // const handleAnyInputChange = (name: string) => (event: any, valueOrOption: any) => { //ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement> | SyntheticEvent<HTMLElement, Event>
    //   let value: any = null;
    //   // Fluent UI Dropdown passes (event, option)
    //   if (valueOrOption && valueOrOption.key !== undefined) {
    //     value = valueOrOption.key;
    //   }
    //   // Fluent UI TextField passes (event, newValue)
    //   else if (typeof valueOrOption === "string") {
    //     value = valueOrOption;
    //   }
    //   // Fluent UI Checkbox passes (event, checked)
    //   else if (typeof valueOrOption === "boolean") {
    //     value = valueOrOption;
    //   }
    //   // Native HTML inputs
    //   else if (event?.target) {
    //     value = event.target.type === "checkbox"
    //       ? event.target.checked
    //       : event.target.value;
    //   }
    //   setFormData(prev => ({
    //     ...prev,
    //     [name]: value
    //   }));
    //   console.log(`Input ${name} changed to ${value}. Current form data:`, JSON.stringify(formData));
    // };
  }

  private checkboxValues = new Map<string, number[]>();

  private mandatoryFormFieldNames: string[] = [
    "RWE2_MODULE_ID",
    "RWE2_REQUEST_ID",
    "custom-workflow-back-url",
    "custom-workflow-generic-id",
    "custom-workflow-current-tabrel-genid",
    "custom-workflow-source-field",
    "crc",
    "MODULE_TESTMODE_KEY",
    "ELANG"
  ];

  private createMandatoryFormFields(queryParams: URLSearchParams): JSX.Element {
    const hiddenInputs: JSX.Element[] = [];

    // Create a hidden input for each mandatory Elix parameter
    this.mandatoryFormFieldNames.forEach(paramName => {
      const value = queryParams.get(paramName) ?? "";
      // Create the input element
      hiddenInputs.push(this.createHiddenInput(paramName));
    });

    return <>{hiddenInputs}</>;
  }

  private createAdditionalFormFields(): React.ReactElement {
    const schema = JSON.parse(this.props.additionalFieldsJson || "[]");

    return (
      <>
        {schema.map((field: { key: React.Key | null | undefined; }) => (
          <div key={field.key}>
            {this.renderField(field)}
          </div>
        ))}
      </>
    );
  }

  protected createCustomFormFields(formFieldFactory: IElixFormsComponentCustomFormFieldFactory): JSX.Element {
    return <></>;
  }

  private renderCustomFormFields(): JSX.Element {
    const formFieldFactory = {
      createBooleanInput: (name: string, label: string, required: boolean = false) =>
        this.createBooleanInput(name, label, required),
      createCheckboxInput: (name: string, label: string, options: Array<ElixFormsCheckboxOption>) =>
        this.createCheckboxInput(name, label, options),
      createDropdownInput: (name: string, label: string, options: Array<ElixFormsDropdownOption>, required: boolean = false) =>
        this.createDropdownInput(name, label, options, required),
      createHiddenInput: (name: string) =>
        this.createHiddenInput(name),
      createNumberInput: (name: string, label: string, required: boolean = false) =>
        this.createNumberInput(name, label, required),
      createRadioInput: (name: string, label: string, options: Array<ElixFormsRadioOption>, required: boolean = false) =>
        this.createRadioInput(name, label, options, required),
      createTextInput: (name: string, label: string, required: boolean = false) =>
        this.createTextInput(name, label, required),
      createTextAreaInput: (name: string, label: string, required: boolean = false) =>
        this.createTextAreaInput(name, label, required),
    };

    return this.createCustomFormFields(formFieldFactory);
  }

  protected renderExtraContentPre(): JSX.Element | null {
    return null;
  }

  protected renderExtraContentPost(): JSX.Element | null {
    return null;
  }

  public override render(): React.ReactElement<IElixFormsComponentProperties> {
    const {
      description,
      isDarkTheme,
      environmentMessage,
      hasTeamsContext,
      userDisplayName,
      additionalFieldsJson,
      headerTitle,
      pageTitle,
      pageDescription,
      submitDescription,
      heroImageSrc
    } = this.props;

    const queryParams = new URLSearchParams(window.location.search);
    const missingMandatoryParams = this.mandatoryFormFieldNames.filter(paramName => !queryParams.has(paramName));
    const hasAuthenticationError = missingMandatoryParams.length > 0;

    return (
      <div className="container_12" id="pageBody">
        <div className="grid_12">
          <div id="userConsole" className="fe-behaviour">
            <header>
              <div className="neutral">
                <div className="grid_12">
                  <div className="console_header">
                    <div className="leftDiv">
                      <h1>elixForms</h1>
                      <div className="logo"><a href="https://www.unipr.it/" title="Torna alla homepage dell'Università: di Parma"><img src="https://console-unipr.elixforms.it/elixFormsCustom/images/logo.png" alt="Logo Università: di Parma" /></a>
                      </div>
                    </div>
                    <div className="rightDiv">
                      <div className="rightDivInside info padding_r">
                        <div className="clear"></div>
                      </div>
                    </div>
                    <div className="clear"></div>
                  </div>
                </div>
                <div className="clear"></div>
              </div>
            </header>

            <div className="grid_12 console_main">
              <div className="inside">
                {headerTitle && (
                  <div>
                    <div className="fe-module-header-container">
                      <h2>{headerTitle}</h2>
                    </div>
                  </div>
                )}
                <div className="mainview">
                  <div className="container">
                    {pageTitle && <h1>{pageTitle}</h1>}
                    {heroImageSrc && <img src={heroImageSrc} alt="Hero Image" className="hero-image" />}
                    {pageDescription && <p>{pageDescription}</p>}

                    {environmentMessage && <div>{environmentMessage}</div>}
                    {description && <div>{description}</div>}

                    {hasAuthenticationError ? (
                      <FluentUI.MessageBar messageBarType={FluentUI.MessageBarType.error} isMultiline={false}>
                        Accesso non autorizzato. Parametri obbligatori mancanti ({missingMandatoryParams.join(', ')}).
                      </FluentUI.MessageBar>
                    ) : (
                      <>
                        {this.renderExtraContentPre()}

                        <form action="https://procedure.unipr.it/rwe2/ComeBackToElixAndSave" method="post" acceptCharset="ISO-8859-1">
                          {this.createMandatoryFormFields(queryParams)}
                          {this.createAdditionalFormFields()}
                          {this.renderCustomFormFields()}
                          <br/>
                          <input type="submit" value={submitDescription ?? 'Submit'} />
                        </form>

                        {this.renderExtraContentPost()}
                      </>
                    )}
                  </div>
                </div>
              </div>
            </div>

            <div className="clear"></div>

            <footer className="it-footer">
              <div className="it-footer-main">
                <div className="container">
                  <div className="row clearfix">
                    <div className="col-sm-12">
                      <div className="footer-content">
                        <div className="subfooter-top">powered by <span className="highlight">elixForms</span></div>
                        <div className="subfooter-bottom"><div>versione 1.24.0</div></div>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </footer>
          </div>
          <div className="clear"></div>
        </div>
      </div>
    );
  }

  private createCheckboxInput(paramName: string, label: string, values: Array<ElixFormsCheckboxOption>): JSX.Element {
    const checkedValues = QueryParamHelper.getCheckedFromQuery(paramName);

    if (!this.checkboxValues.get(paramName)) {
      this.checkboxValues.set(paramName, checkedValues);
    }

    const checkboxes: React.ReactElement[] = [];
    const stackTokens = { childrenGap: 10 };

    values.forEach((entry, entryIndex) => {
      const id = `${paramName}_${entryIndex}`;
      checkboxes.push(
        <FluentUI.Checkbox title={label} key={id} id={id} label={entry.label} required={entry.required ?? false} defaultChecked={checkedValues.indexOf(entryIndex) !== -1} className='isiportalPartialAdminCheckboxFieldItem'
          onChange={(event, checked) => {
            const currentCheckboxValues = this.checkboxValues.get(paramName)!;
            const checkboxIndex = currentCheckboxValues.indexOf(entryIndex);
            if (checked && checkboxIndex === -1) {
              currentCheckboxValues.push(entryIndex);
            } else if (!checked && checkboxIndex !== -1) {
              currentCheckboxValues.splice(checkboxIndex, 1);
            }
            const newValue = currentCheckboxValues.join(',').trim();
            this.setState({ formData: { ...this.state.formData, [paramName]: newValue } }, () => {
              console.log(`Checkbox ${id} changed to ${checked}. Current values for ${paramName}: ${this.state.formData[paramName]}`);
            });
          }}
        />
      );
    });

    const currentValue = this.state.formData[paramName] !== undefined
                           ? this.state.formData[paramName]
                           : (this.checkboxValues.get(paramName)?.join(',').trim() ?? '');

    return new ElixFormsElement(
      <><FluentUI.Label htmlFor={paramName}>{label}</FluentUI.Label></>,
      <><FluentUI.Stack tokens={stackTokens}>
        {checkboxes}
      </FluentUI.Stack>
        <input type='hidden' id={paramName} name={paramName} value={currentValue} />
      </>
    ).render();
  }

  private createRadioInput(paramName: string, label: string, values: Array<ElixFormsRadioOption>, required: boolean = false): JSX.Element {
    const radioValue = QueryParamHelper.getOptionFromQuery(paramName);
    const radios: FluentUI.IChoiceGroupOption[] = [];

    values.forEach((entry, _) => {
      const id = `${paramName}_${entry.value}`;
      radios.push(
        {
          key: id,
          text: entry.label,
          id: id,
          name: paramName,
          value: entry.value,
          className: 'isiportalPartialAdminFormFieldRadio'
        }
      );
    });

    return new ElixFormsElement(
      <></>,
      <FluentUI.ChoiceGroup
        name={paramName}
        label={label}
        options={radios}
        required={required}
        defaultSelectedKey={`${paramName}_${radioValue}`}
        onChange={(event, option) => {
          const value = option?.value ?? '';
          this.setState({ formData: { ...this.state.formData, [paramName]: value } }, () =>
            console.log(`Radio ${option?.id} changed to ${value}. Current value for ${paramName}: ${this.state.formData[paramName]}`)
          );
        }}
      />
    ).render();
  }

  private createBooleanInput(paramName: string, label: string, required: boolean = false): JSX.Element {
    const boolValue = QueryParamHelper.getOptionFromQuery(paramName);
    const radios: FluentUI.IChoiceGroupOption[] = [];

    [{ "value": "true", "label": "Sì" }, { "value": "false", "label": "No" }].forEach((val) => {
      const id = `${paramName}_${val.value}`;
      radios.push(
        {
          key: id,
          text: val.label,
          id: id,
          name: paramName,
          value: val.value,
          className: 'isiportalPartialAdminFormFieldRadio'
        }
      );
    });

    return new ElixFormsElement(
      <></>,
      <FluentUI.ChoiceGroup
        name={paramName}
        label={label}
        options={radios}
        required={required}
        defaultSelectedKey={`${paramName}_${boolValue}`}
        onChange={(event, option) => {
          const value = option?.value ?? '';
          this.setState({ formData: { ...this.state.formData, [paramName]: value } }, () =>
            console.log(`Boolean ${option?.id} changed to ${value}. Current value for ${paramName}: ${this.state.formData[paramName]}`)
          );
        }}
      />
    ).render();
  }

  private createTextAreaInput(paramName: string, label: string, required: boolean = false): JSX.Element {
    const textareaValue = QueryParamHelper.getDecodedTextFromQuery(paramName) ?? "";
    return new ElixFormsElement(
      <FluentUI.Label htmlFor={paramName}>{label}</FluentUI.Label>,
      <FluentUI.TextField id={paramName} name={paramName} defaultValue={textareaValue} multiline rows={4} required={required} className='isiportalPartialAdminFormFieldMultiLineText'
        onChange={(event, value) => {
          this.setState({ formData: { ...this.state.formData, [paramName]: value } }, () =>
            console.log(`TextArea ${paramName} changed to ${value}. Current value for ${paramName}: ${this.state.formData[paramName]}`)
          );
        }}
      />
    ).render();
  }

  private createTextInput(paramName: string, label: string, required: boolean = false): JSX.Element {
    const textValue = QueryParamHelper.getDecodedTextFromQuery(paramName) ?? "";
    return new ElixFormsElement(
      <FluentUI.Label htmlFor={paramName}>{label}</FluentUI.Label>,
      <FluentUI.TextField id={paramName} name={paramName} defaultValue={textValue} required={required} className='isiportalPartialAdminFormFieldSingleLineText'
        onChange={(event, value) => {
          this.setState({ formData: { ...this.state.formData, [paramName]: value } }, () =>
            console.log(`TextInput ${paramName} changed to ${value}. Current value for ${paramName}: ${this.state.formData[paramName]}`)
          );
        }}
      />
    ).render();
  }

  private createHiddenInput(paramName: string): JSX.Element {
    const textValue = QueryParamHelper.getDecodedTextFromQuery(paramName) ?? "";
    return <input type="hidden" id={`${paramName}_hidden`} name={paramName} defaultValue={textValue} />;
  }

  private createNumberInput(paramName: string, label: string, required: boolean = false): JSX.Element {
    const textValue = QueryParamHelper.getDecodedTextFromQuery(paramName) ?? "";
    return new ElixFormsElement(
      <FluentUI.Label htmlFor={paramName}>{label}</FluentUI.Label>,
      <FluentUI.TextField id={paramName} name={paramName} defaultValue={textValue} type="number" required={required} className='isiportalPartialAdminFormFieldSingleLineText'
        onChange={(event, value) => {
          this.setState({ formData: { ...this.state.formData, [paramName]: value } }, () =>
            console.log(`NumberInput ${paramName} changed to ${value}. Current value for ${paramName}: ${this.state.formData[paramName]}`)
          );
        }}
      />
    ).render();
  }

  private createDropdownInput(paramName: string, label: string, values: Array<ElixFormsDropdownOption>, required: boolean = false): JSX.Element {
    const queryValue = QueryParamHelper.getOptionFromQuery(paramName);
    const currentValue = this.state.formData[paramName] !== undefined 
                           ? this.state.formData[paramName] 
                           : (queryValue?.toString() ?? '');

    const options: FluentUI.IDropdownOption[] = [];

    values.forEach(entry => {
      options.push(
        {
          key: entry.value.toString(),
          text: entry.label
        }
      );
    });

    return new ElixFormsElement(
      <FluentUI.Label htmlFor={paramName}>{label}</FluentUI.Label>,
      <>
        <FluentUI.Dropdown
          id={paramName}
          options={options}
          selectedKey={currentValue}
          placeholder='---'
          required={required}
          className='isiportalPartialAdminFormFieldSelect'
          onChange={(event, option) => {
            if (option) {
              const value = option.key.toString();
              this.setState({ formData: { ...this.state.formData, [paramName]: value } }, () =>
                console.log(`Dropdown ${paramName} changed to ${value}. Current value for ${paramName}: ${this.state.formData[paramName]}`)
              );
            }
          }}
        />
        <input type="hidden" name={paramName} id={paramName + '_hidden'} value={currentValue} />
      </>
    ).render();
  }

  private renderField(field: any): JSX.Element {
    //const value = this.state.formData[field.key] || "";

    switch (field.type) {
      case "text":
        return this.createTextInput(field.key, field.label, field.required ?? false);

      case "textarea":
        return this.createTextAreaInput(field.key, field.label, field.required ?? false);

      case "radio":
        return this.createRadioInput(field.key, field.label,
          new Array<ElixFormsRadioOption>().concat(...field.options.map((o: any) => [[o.value, o.label]])),
          field.required ?? false);

      case "boolean":
        return this.createBooleanInput(field.key, field.label, field.required ?? false);

      case "checkbox":
        return this.createCheckboxInput(field.key, field.label,
          new Array<ElixFormsCheckboxOption>().concat(...field.options.map((o: any) => [[o.value, o.label, o.required ?? false]])));

      case "number":
        return this.createNumberInput(field.key, field.label, field.required ?? false);

      case "dropdown":
        return this.createDropdownInput(field.key, field.label,
          new Array<ElixFormsDropdownOption>().concat(...field.options.map((o: any) => [[o.value, o.label]])),
          field.required ?? false);

      default:
        return <></>;
    }
  }
}