/**
 * @file NotesTab.tsx - Tab component for viewing and adding notes.
 * When a folder node is selected, shows work item-level notes. When a document node is selected, shows document-specific notes.
 * Uses the Linkify library for automatic URL detection in the note text.
 * Notes are displayed in a numbered list with submitter name, text, and timestamp.
 * Adding a note requires the AddNote permission.
 */

import { type FC, useRef, useState } from 'react';
import { AtAllowRights } from '../../../../types/atAllowRights.ts';
import { Alert, Button, FloatingLabel, Form, ListGroup } from 'react-bootstrap';
import { addNote, type Note } from '../../../../api/note.ts';
import type {
  DocumentNode,
  FolderNode,
} from '../../DetailsFolderPanel/sections/FolderSection/FolderTree.tsx';
import { toast } from 'react-toastify';
import { useProcessPermissions } from '../../../../contexts/ProcessPermissionsContext.tsx';
import { useWorkItem } from '../../../../contexts/WorkItemContext.tsx';
import { useProcessingUI } from '../../../../contexts/ProcessingUIContext.tsx';
import { useNamedAnchorRemainingHeight } from '../../../../hooks/useNamedAnchorRemainingHeight.ts';
import { Icon } from '../../../Icon.tsx';
import { MAX_NOTE_LENGTH } from '../../../../constants.ts';
import { useTranslation } from 'react-i18next';
import Linkify from 'linkify-react';

/**
 * Props for the NotesTab component.
 */
interface NotesTabProps {
  /** Whether the tab content is currently visible (controls d-none CSS class) */
  show: boolean;
}

/**
 * Notes tab within the Fields/Notes/Tracking panel that displays work item or document notes depending on the selected FolderTree node.
 * Supports adding new notes with automatic link detection.
 */
export const NotesTab: FC<NotesTabProps> = ({ show }) => {
  const { registerAnchor, maxHeight } = useNamedAnchorRemainingHeight('notes');

  // Required contexts for work item processing
  const { workItem, notes, setNotes } = useWorkItem();
  const { selectedNode, isMobile } = useProcessingUI();
  const { hasPermission } = useProcessPermissions();

  const newNoteTextarea = useRef<HTMLTextAreaElement | null>(null);
  const [addNoteDisabled, setAddNoteDisabled] = useState(true);

  /**
   * Creates and submits a new note via the API, scoped to the current folder or document node.
   */
  const addNewNote = () => {
    const newNote: Note = {
      workItemId: workItem?.workItemReferenceId as number,
      documentId: null,
      note: newNoteTextarea.current?.value as string,
    };
    // If a document node is selected, associate the note with that document
    if ((selectedNode as DocumentNode)?.documentId !== undefined) {
      newNote.documentId = (selectedNode as DocumentNode)?.documentId;
    }

    addNote(newNote)
      .then((addedNote) => {
        if (newNoteTextarea.current) {
          newNoteTextarea.current.value = '';
          setAddNoteDisabled(true);
        }

        setNotes(notes.concat(addedNote));

        toast.success(t('functions.add_new_note.success'));
      })
      .catch(() => {
        toast.error(t('functions.add_new_note.errors.failed_to_add'));
      });
  };

  const { t } = useTranslation(undefined, {
    keyPrefix: 'components.processing.fields_notes_tracking_panel.tabs.notes',
  });

  return (
    <div className={show ? '' : 'd-none'}>
      {
        // Add note section (works for folder and document notes)
        hasPermission(AtAllowRights.AddNote) && (
          <>
            <FloatingLabel
              controlId={'new-note-textarea'}
              label={<span>{t('inputs.new_note.label')}</span>}
            >
              <Form.Control
                ref={newNoteTextarea}
                as={'textarea'}
                style={{ height: '6.25rem' }}
                placeholder={t('inputs.new_note.label')}
                className={'mb-2'}
                onChange={(event) =>
                  setAddNoteDisabled(!event.target.value.trim().length)
                }
                maxLength={Number(MAX_NOTE_LENGTH)}
              />
            </FloatingLabel>
            <Button
              variant={'primary'}
              className={'w-100 mt-2'}
              disabled={addNoteDisabled}
              onClick={addNewNote}
            >
              <div
                className={'d-flex justify-content-center align-items-center'}
              >
                <Icon iconName={'JournalPlus'} size={20} />
                <span className={'ms-2'}>
                  {t('buttons.add_note.button_text')}
                </span>
              </div>
            </Button>
            <hr />
          </>
        )
      }

      <div ref={registerAnchor('notes')} />
      <div
        className={'overflow-y-auto'}
        style={{ maxHeight: isMobile ? undefined : maxHeight }}
      >
        {/* Folder notes */}
        {(selectedNode as FolderNode)?.folderId !== undefined &&
          (() => {
            const folderNotes = notes.filter((note) => !note.documentId);

            return (
              <>
                {folderNotes.length ? (
                  <ListGroup numbered>
                    {folderNotes.map((note) => (
                      <ListGroup.Item
                        key={note.noteId}
                        className={
                          'd-flex justify-content-between align-items-start'
                        }
                      >
                        <div className={'ms-2 me-auto'}>
                          <div className={'fw-bold'}>{note.submitter}</div>
                          <div className={'text-break'}>
                            <Linkify
                              options={{
                                target: '_blank',
                                rel: 'noreferrer',
                              }}
                            >
                              {note.note}
                            </Linkify>
                            <br />
                            <small>
                              {new Date(
                                note.submitDate as string
                              ).toLocaleString()}
                            </small>
                          </div>
                        </div>
                      </ListGroup.Item>
                    ))}
                  </ListGroup>
                ) : (
                  <Alert variant={'light'} className={'text-center mb-0'}>
                    {t('alerts.folder_notes.none')}
                  </Alert>
                )}
              </>
            );
          })()}

        {/* Document notes */}
        {(selectedNode as DocumentNode)?.documentId !== undefined &&
          (() => {
            const documentNotes = notes.filter(
              (note) =>
                note.documentId === (selectedNode as DocumentNode).documentId
            );

            return (
              <>
                {documentNotes.length ? (
                  <ListGroup numbered>
                    {documentNotes.map((note) => (
                      <ListGroup.Item
                        key={note.noteId}
                        className={
                          'd-flex justify-content-between align-items-start'
                        }
                      >
                        <div className={'ms-2 me-auto'}>
                          <div className={'fw-bold'}>{note.submitter}</div>
                          <div className={'text-break'}>
                            {note.note}
                            <br />
                            <small>
                              {new Date(
                                note.submitDate as string
                              ).toLocaleString()}
                            </small>
                          </div>
                        </div>
                      </ListGroup.Item>
                    ))}
                  </ListGroup>
                ) : (
                  <Alert variant={'light'} className={'text-center mb-0'}>
                    {t('alerts.document_notes.none')}
                  </Alert>
                )}
              </>
            );
          })()}
      </div>
    </div>
  );
};
