/**
 * @description
 * @author Sneha
 *
 * The component used to change information
 *
 *
 */

import React, { useState, useContext, useEffect } from 'react';

import { Steps, message } from 'antd';

import './change-info.scss';

import { GlobalContext, FormCreator, Card,Button } from '../../../lib';

import { CoreScripts, Preferences } from '../../../models';

import PropTypes from 'prop-types';

/**
 *
 * @param root0
 * @param root0.reportId
 * @param root0.preferenceId
 * @returns {*}
 */
function ChangeInfo({ reportId, preferenceId }) {
  //Representing steps

  // Track the curren    //Representing steps
  const { Step } = Steps;

  // Track the current step in the process
  const [currentStep, setCurrentStep] = useState(0);

  // Store  details returned by coreScript
  const [paramterData, setParameterData] = useState([]);

  // Store title
  const [displayColumns, setdisplayColumns] = useState([]);

  // Store titles
  const [titleData, setTitleData] = useState();

  // Loading state
  const [loading, setLoading] = useState(true);

  // Store patients list
  const [information, setInformation] = useState([]);

  // Store selected patients
  const [selectedInformation, setSelectedInformation] = useState([]);

  // Retrieve global context data
  const { CustomModels = {} } = useContext(GlobalContext);

  const [titleContents, setTitleContents] = useState([]);

  /** Next step */
  const next = () => {
    setCurrentStep(currentStep + 1);
  };

  /** Previous step*/
  function prev() {
    //If currentstage is 2, beacuse we don't need setSelectedPatients there
    if (currentStep === 2) {
      // Clear selected patients when going back from step 2
      setSelectedInformation([]);
    }

    setCurrentStep(currentStep - 1);
  }

  /**
   * Fetch patient details when the component mountsGo back to the previous step
   */
  useEffect(() => {
    /**Get information */
    getInformation();
  }, []);

  /**
   * Function to fetch patient details from the backend
   */
  const getInformation = async () => {
    //CoreScript Id
    let id = reportId.selectId;

    //Getting records from coreScripts corresponding to the id
    CoreScripts.getRecord({ id }).then(({ result }) => {
      // Prepare input parameters for the form
      prepareInputParameters(result.input_parameters);

      // Set details from the fetched data
      setdisplayColumns(JSON.parse(result.display_columns));

      /**Fetching data from otherdetails */
      let otherDetails = JSON.parse(result.other_details1);

      /**Setting title datas   */
      setTitleData(otherDetails);
    });
  };

  /**
   * Prepare input parameters for the form
   * @param {object} inputParameters
   */
  const prepareInputParameters = async (inputParameters) => {
    setLoading(true);

    // Parse input parameters
    let parameters = JSON.parse(inputParameters);

    // Map and set form content based on parameters and URL params
    parameters = await parameters.map((record) => {
      if (['reference-select', 'reference-search'].indexOf(record.type) !== -1) {
        /**Get custom model based on the model name */
        let model = CustomModels[record.modelName];

        return { ...record, model };
      } else {
        return { ...record };
      }
    });

    setLoading(false);

    // Set details with prepared parameters
    setParameterData([...parameters]);
  };

  /**
   * Handle form submission
   * @param {Object} values
   */
  const handleFormSubmit = async (values) => {
    //ID
    let id;

    //Formbody
    let formBody;

    //If there is selectedPatients we need to update the patient details
    if (currentStep === 2) {
      //CoreScript Id for updation
      id = reportId.editId;

      //Defining formbody
      formBody = {
        body: {
          // Values for replacing
          values,

          selectedData: selectedInformation,
        },
      };

      //Getting coreScript data for updation
      await CoreScripts.getUserDetailsLisitng(id, formBody).then((result) => {
        // let resultDetails = result;

        //If there is data and message is suceess
        if (result && result.message === 'sucess') {
          // Update information list
          setInformation(result);

          message.success(result.message);

          // Clear selectedData and reset to the first step
          setSelectedInformation([]);

          //Setting step back to init
          setCurrentStep(0);
        } else {
          message.warning(result.message);
        }

        setLoading(false);
      });

      {
        /**Else */
      }
    } else {
      /**If there is selectedInformation we need to update the patient details */
      formBody = { body: values };

      /**Id for getting coreScrpt data */
      id = reportId.selectId;

      //Getting coreScript data for getting
      await CoreScripts.getReportingLisitng(id, formBody).then((result) => {
        let resultDetails = result[0] || (result?.result && result?.result[0]);

        if (resultDetails) {
          // Update information list
          setInformation(resultDetails);

          // Proceed to the next step
          next();
        }

        setLoading(false);
      });
    }

    setLoading(true);
  };

  /**
   * 
   * @param {*} newTitleContents 
   */
  const handleTitleContentsUpdate = (newTitleContents) => {
    setTitleContents(newTitleContents);
  };


  /**
   * Handle patient selection
   * @param {Array} selected
   */

  /**
   *
   * @param selected
   */
  const handlePatientSelection = (selected) => {
    // Update selected patients
    setSelectedInformation(selected);
  };

  /**
   * Render through each stages
   *
   * @param {number} step
   * @returns {JSX.Element} The rendered component corresponding to the current step.
   */
  const renderSwitch = (step) => {
    switch (step) {
      case 0:
        return (
          <InitialContent
            selectedInformation={selectedInformation}
            next={next}
            prev={prev}
            fields={paramterData}
            selectedData={null}
            currentStep={currentStep}
            preferenceId={preferenceId}
            titleData={titleData}
            onSubmit={handleFormSubmit}
            onTitleContentsUpdate={handleTitleContentsUpdate}
          />
        );

      case 1:
        return <GuestDetails next={next} prev={prev} displayColumns={displayColumns} information={information} onSelect={handlePatientSelection} titleData={titleData} />;

      case 2:
        return (
          <>
            <div className="change-info-container">
              <div className="change-infoheader">{titleContents && titleContents.heading ? titleContents.heading : 'Current information'}</div>

              {/*Looping through selected data  */}
              {selectedInformation.map((patient, index) => (
                <div key={index} className="info-items">
                  {/** Matching the selected data with the display columns */}
                  {displayColumns.map((detail, idx) => {
                    //Display columns fieild
                    const fieldName = detail.field;

                    //MAatchined values
                    const fieldValue = patient[fieldName];

                    return (
                      <div key={idx} className="info-field">
                        <span>{detail.title}:</span>

                        <span className="value">{fieldValue !== undefined ? fieldValue : 'N/A'}</span>

                        {/** Selected data */}
                        {patient.selected && <span className="selected">(selected)</span>}
                      </div>
                    );
                  })}
                </div>
              ))}

            </div>
            <p>{titleContents?.notes}</p>

            <p>{selectedInformation[0]?.message}</p>
            <InitialContent
              next={next}
              prev={prev}
              selectedInformation={selectedInformation}
              fields={null}
              currentStep={currentStep}
              selectedData={selectedInformation}
              onSubmit={handleFormSubmit}
              preferenceId={preferenceId}
              onTitleContentsUpdate={handleTitleContentsUpdate}
            />
          </>
        );

      default:
        return (
          <InitialContent
            selectedInformation={selectedInformation}
            next={next}
            fields={paramterData}
            loading={loading}
            currentStep={currentStep}
            onSubmit={handleFormSubmit}
            onTitleContentsUpdate={handleTitleContentsUpdate}
          />
        );
    }
  };

  return (
    <Card className="change-profile-head">
      
      <Card className="change-profile">
        <Steps size="small" current={currentStep}>
          <Step title="Enter" />

          <Step title="Edit" />

          <Step title="Select" />
        </Steps>
      </Card>

      <FormContent renderSwitch={renderSwitch} currentStep={currentStep} />
    </Card>
  );
}

// Define PropTypes for the component
ChangeInfo.propTypes = {
  reportId: PropTypes.object,
  preferenceId: PropTypes.number,
};

export default ChangeInfo;

/**
 *
 * @param root0
 * @param root0.renderSwitch
 * @param root0.currentStep
 *  @returns {JSX.Element}  JSX content
 */
function FormContent({ renderSwitch, currentStep }) {
  return (
    /* Rebder formConetent */
    <Card className="formcreator card">{renderSwitch(currentStep)}</Card>
  );
}

FormContent.propTypes = {
  renderSwitch: PropTypes.func.isRequired,
  currentStep: PropTypes.number,
};

/**
 * @param {Object}root0
 * @param root0.next
 * @param root0.prev
 * @param root0.fields
 * @param root0.selectedInformation
 * @param root0.titleData
 * @param root0.onSubmit
 * @param root0.selectedData
 * @param root0.currentStep
 * @param root0.preferenceId
 * @param root0.onTitleContentsUpdate
 * @returns {JSX.Element}  JSX content
 */
function InitialContent({ selectedInformation, next, prev, fields, onSubmit, selectedData, currentStep, preferenceId, titleData, onTitleContentsUpdate }) {
  /** @type {string} */

  let formLayout = 'inline';

  // Store preferences
  const [preference, setPreference] = useState({});

  const [titleContents, setTitleContents] = useState([]);

  /**
   * Fetch patient details if selected data exists.
   * @param {*}
   * @returns {*}
   */
  useEffect(() => {
    /**Cheaking if there is selectedData */
    if (selectedData && selectedData.length > 0) {
      getPatientDetail();
    }
  }, []);

  /**
   * Get details
   */
  const getPatientDetail = async () => {
    /**  Defining preference id*/
    let id = preferenceId;

    Preferences.fillCustomInputData({ id }).then((result) => {
      setPreference(result.fields);

      setTitleContents(result)

      // Update the parent with titleContents
      if (onTitleContentsUpdate) {
        onTitleContentsUpdate(result);
      }

      return result;
    });

    // Preferences.getRecord({ id }).then(({ result }) => {
    //   let data = JSON.parse(result.scope_value);

    //   setPreference(data.fields);

    //   return result;
    // });
  };

  /**
   *  Render the form based on the details or preferences fetched
   *
   * @returns
   */
  const renderForm = () => {
    if ((fields && fields.length > 0) || (preference && preference.length > 0)) {
      return (
        <FormCreator
          selectedInformation={selectedInformation}
          layout={formLayout}
          initialValues={{ layout: formLayout }}
          styles={{ paddingRight: '15px', alignItems: 'center' }}
          fields={fields ? fields : preference}
          modelIndex="requestId"
          model={{ fields: fields ? fields : preference }}
          onSubmit={onSubmit}
        />
      );
    }
  };

  return (
    <div>
      {/* We use this page for step 0 and 1 but we need this part only for 0 */}
      {currentStep === 0 && titleData && (
        <div>
          <h4>{titleData.title}</h4>

          <p>{titleData.description}</p>

          <p>{titleData.message}</p>
        </div>
      )}

      {renderForm()}

      <div>
        {/* We use this page for step 0 and 2 but we need bacck button all stages except 0 */}
        {currentStep !== 0 && (
          <Button type="default" onClick={prev} style={{ marginTop: '20px', marginRight: '10px' }}>
            Back
          </Button>
        )}

        {/* We use this page for step 0 and 2 but we need this part only for 2 */}
        {currentStep === 1 && (
          <Button type="primary" onClick={next} style={{ marginTop: '20px', marginLeft: '10px' }}>
            Next
          </Button>
        )}
      </div>
    </div>
  );
}

InitialContent.propTypes = {
  next: PropTypes.func.isRequired,
  prev: PropTypes.func.isRequired,
  fields: PropTypes.array,
  onSubmit: PropTypes.func.isRequired,
  selectedData: PropTypes.array,
  selectedInformation: PropTypes.array.selectedInformation,
  currentStep: PropTypes.number.isRequired,
  preferenceId: PropTypes.number.isRequired,
  titleData: PropTypes.shape({
    title: PropTypes.title,
    description: PropTypes.description,
    message: PropTypes.message,
  }),
};

/**
 * Handles the step where users select patients
 * @param root0
 * @param root0.next
 * @param root0.prev
 * @param root0.information
 * @param root0.onSelect
 * @param root0.displayColumns
 * @param root0.titleData
 * @returns {JSX.Element} The rendered component corresponding to the data
 * Render renderAdditionalInfo
 */
function GuestDetails({ next, prev, information, onSelect, displayColumns, titleData }) {
  // Track selected patients
  const [selectedInformation, setSelectedInformation] = useState([]);

  // Track selected checkbox
  const [selectedCheckbox, setSelectedCheckbox] = useState();

  /**
   *
   * @param {*} patient
   * @param {*} isChecked
   * @param {*} index
   */
  const handleCheckboxChange = (patient, isChecked, index) => {
    /**Cheaking if it is cheaked */
    if (isChecked) {
      // Set the selected checkbox by index
      setSelectedCheckbox(index);

      // Set the selectedInformation to only the current patient
      setSelectedInformation([patient]);

      // Trigger the onSelect function with the updated selection
      onSelect([patient]);
    }
  };

  /**
   * Render renderAdditionalInfo
   * @param {Array} data
   * @returns {object} displayColumns
   */
  const renderAdditionalInfo = (data) => {
    /* Matching selected data with the display columns */
    return displayColumns.map((detail, index) => {
      const fieldName = detail.field;

      return (
        <div key={index} className="selected-info-item">
          <span className="selected-info-field">{detail.title}:</span>

          <span className="selected-value">{data[fieldName] || 'N/A'}</span>
        </div>
      );
    });
  };

  return (
    <div className='middle-class'>
      <div className='content'><h3>{titleData?.content}</h3></div>
      <div>
        {/* If the coreScript data contains data */}
        {information && information.length > 0 ? (
          information.map((data, index) => (
            <Card className="change-info card" key={index} style={{ marginBottom: '10px' }}>
              <div className="change-info-details">
                <div className="change-info-patient-info">
                  <input
                    type="radio"
                    className="patient-radio"
                    checked={selectedCheckbox === index}
                    onChange={(e) => handleCheckboxChange(data, e.target.checked, index)}
                  />
                </div>

                <div className="additional-info">{renderAdditionalInfo(data)}</div>
              </div>
            </Card>
          ))
        ) : (
          <p>No patient data available</p>
        )}
      </div>
      <Button type="default" onClick={prev}>
        Back
      </Button>

      <Button
        type="primary"
        onClick={next}
        style={{ marginTop: '20px', marginLeft: '10px' }}
        // Disable button if no patients are selected
        disabled={selectedInformation.length === 0}
      >
        Edit Details
      </Button>
    </div>
  );
}

GuestDetails.propTypes = {
  next: PropTypes.func.isRequired,
  prev: PropTypes.func.isRequired,
  onSelect: PropTypes.array,
  displayColumns: PropTypes.object,
  information: PropTypes.array,
};
