import { useCallback, useEffect, useMemo, useState } from 'react';
import {
  createOracFormDetail,
  fetchLookupCountries,
  fetchLocationsList,
  fetchOracFormDetailsList,
  fetchOracSectionDetailsList,
  mapLocationToForm,
  mapSectionToForm
} from '../../api.js';
import { getSessionUserId } from './adminOracSession.js';
import { formAllowedForNewUse } from '../../utils/oracFormDetails.js';
import './admin-shared.css';
import './AdminFormBuilderPage.css';
import './AdminFormsCompositionPage.css';

/** @returns {{ dateStr: string, timeStr: string }} Local date (YYYY-MM-DD) and time (HH:mm) for inputs. */
function localDateParts(d = new Date()) {
  const pad = (n) => String(n).padStart(2, '0');
  return {
    dateStr: `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`,
    timeStr: `${pad(d.getHours())}:${pad(d.getMinutes())}`
  };
}

function locationDisplayName(loc) {
  if (!loc) return '';
  return loc.Location_name || loc.location_name || `Location ${loc.location_id}`;
}

/** Create new forms; edit metadata and composition on the Form details page. */
function AdminFormsCompositionPage({ onNavigateToFormList }) {
  const [forms, setForms] = useState([]);

  const [newFormTitle, setNewFormTitle] = useState('');
  const [newFormDescription, setNewFormDescription] = useState('');
  const [newFormCreatedDate, setNewFormCreatedDate] = useState('');
  const [newFormCreatedTime, setNewFormCreatedTime] = useState('');
  const [newFormParentId, setNewFormParentId] = useState('');

  const [sectionsCatalog, setSectionsCatalog] = useState([]);
  const [selectedSectionIds, setSelectedSectionIds] = useState(() => new Set());

  const [countries, setCountries] = useState([]);
  /** Location catalog (loaded once; filtered by country in the UI). */
  const [allLocations, setAllLocations] = useState([]);
  const [locationCountryFilter, setLocationCountryFilter] = useState('');
  const [locationDropdownPick, setLocationDropdownPick] = useState('');
  const [selectedLocationIds, setSelectedLocationIds] = useState(() => new Set());

  const [loading, setLoading] = useState(true);
  const [busy, setBusy] = useState(false);
  const [message, setMessage] = useState('');
  const [error, setError] = useState('');
  const [successDialog, setSuccessDialog] = useState({ open: false, title: '', body: '' });

  const uid = getSessionUserId();

  function openSuccessDialog(title, body) {
    setSuccessDialog({ open: true, title, body });
  }

  function closeSuccessDialogAndGoToList() {
    setSuccessDialog((s) => ({ ...s, open: false }));
    if (typeof onNavigateToFormList === 'function') {
      onNavigateToFormList();
    }
  }

  /** Parent picker: only forms allowed for new use (not archived, not superseded intermediate versions). */
  const formsForParentSelect = useMemo(() => {
    return [...forms].filter(formAllowedForNewUse).sort((a, b) => Number(a.form_id) - Number(b.form_id));
  }, [forms]);

  const countriesSorted = useMemo(() => {
    return [...countries].sort((a, b) =>
      String(a.country_name || '').localeCompare(String(b.country_name || ''), undefined, { sensitivity: 'base' })
    );
  }, [countries]);

  const loadCatalog = useCallback(async () => {
    const [f, s, c, locs] = await Promise.all([
      fetchOracFormDetailsList({ with_version: true }).catch(() => []),
      fetchOracSectionDetailsList().catch(() => []),
      fetchLookupCountries().catch(() => []),
      fetchLocationsList().catch(() => [])
    ]);
    setForms(Array.isArray(f) ? f : []);
    setSectionsCatalog(Array.isArray(s) ? s : []);
    setCountries(Array.isArray(c) ? c : []);
    setAllLocations(Array.isArray(locs) ? locs : []);
  }, []);

  /** Locations that match the selected country (or all, if "all"). */
  const filteredLocations = useMemo(() => {
    if (!locationCountryFilter) return [];
    if (locationCountryFilter === 'all') return [...allLocations];
    return allLocations.filter(
      (l) => l.country_id != null && String(l.country_id) === String(locationCountryFilter)
    );
  }, [allLocations, locationCountryFilter]);

  /** Dropdown options: same filter, excluding locations already queued for the form. */
  const locationsAvailableInDropdown = useMemo(() => {
    return [...filteredLocations]
      .filter((l) => {
        const id = Number(l.location_id);
        if (!Number.isInteger(id) || id <= 0) return true;
        return !selectedLocationIds.has(id);
      })
      .sort((a, b) =>
        locationDisplayName(a).localeCompare(locationDisplayName(b), undefined, { sensitivity: 'base' })
      );
  }, [filteredLocations, selectedLocationIds]);

  const selectedLocationsDisplay = useMemo(() => {
    return [...selectedLocationIds]
      .map((id) => {
        const loc = allLocations.find((l) => String(l.location_id) === String(id));
        return { id, loc };
      })
      .sort((a, b) => {
        const na = a.loc ? locationDisplayName(a.loc) : String(a.id);
        const nb = b.loc ? locationDisplayName(b.loc) : String(b.id);
        return na.localeCompare(nb, undefined, { sensitivity: 'base' });
      });
  }, [selectedLocationIds, allLocations]);

  useEffect(() => {
    setLoading(true);
    setError('');
    loadCatalog()
      .catch((e) => setError(e.message || 'Failed to load forms'))
      .finally(() => setLoading(false));
  }, [loadCatalog]);

  useEffect(() => {
    const { dateStr, timeStr } = localDateParts(new Date());
    setNewFormCreatedDate(dateStr);
    setNewFormCreatedTime(timeStr);
  }, []);

  useEffect(() => {
    setLocationDropdownPick('');
  }, [locationCountryFilter]);

  useEffect(() => {
    if (!successDialog.open) return undefined;
    function onKey(e) {
      if (e.key === 'Escape') closeSuccessDialogAndGoToList();
    }
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [successDialog.open]);

  const toggleSectionId = (sectionId) => {
    setSelectedSectionIds((prev) => {
      const next = new Set(prev);
      if (next.has(sectionId)) next.delete(sectionId);
      else next.add(sectionId);
      return next;
    });
  };

  /** Choosing a location in the dropdown adds it to the form immediately (no separate “Add” step). */
  const handleLocationSelectChange = (value) => {
    if (!value || value === '') {
      setLocationDropdownPick('');
      return;
    }
    const id = Number(value);
    if (!Number.isInteger(id) || id <= 0) return;
    setSelectedLocationIds((prev) => new Set([...prev, id]));
    setLocationDropdownPick('');
  };

  const removeSelectedLocation = (locationId) => {
    const id = Number(locationId);
    if (!Number.isInteger(id) || id <= 0) return;
    setSelectedLocationIds((prev) => {
      const next = new Set(prev);
      next.delete(id);
      return next;
    });
  };

  const showMsg = (text, isErr = false) => {
    setMessage(text);
    setError(isErr ? text : '');
    if (!isErr) {
      window.setTimeout(() => setMessage(''), 4000);
    }
  };

  const handleCreateForm = async (e) => {
    e.preventDefault();
    const title = newFormTitle.trim();
    if (!title) {
      showMsg('Enter form title', true);
      return;
    }
    setBusy(true);
    setError('');
    try {
      const parentId = newFormParentId.trim();
      const parentNum = parentId === '' ? null : Number(parentId);
      const body = {
        title,
        description: newFormDescription.trim() || null,
        form_parent_id:
          parentNum != null && Number.isInteger(parentNum) && parentNum > 0 ? parentNum : null
      };
      if (uid != null && Number.isFinite(uid)) body.created_by = uid;
      const datePart = newFormCreatedDate.trim();
      const timePart = newFormCreatedTime.trim();
      if (datePart && timePart) {
        const withSec = timePart.split(':').length >= 3 ? timePart : `${timePart}:00`;
        body.created_date = `${datePart} ${withSec}`.slice(0, 19);
      } else {
        const n = new Date();
        body.created_date = `${n.getFullYear()}-${String(n.getMonth() + 1).padStart(2, '0')}-${String(n.getDate()).padStart(2, '0')} ${String(n.getHours()).padStart(2, '0')}:${String(n.getMinutes()).padStart(2, '0')}:${String(n.getSeconds()).padStart(2, '0')}`;
      }
      const sectionIdsToMap = [...selectedSectionIds];
      const pendingPick = Number(locationDropdownPick);
      const locationIdsToMap = [
        ...new Set([
          ...[...selectedLocationIds]
            .map((id) => Number(id))
            .filter((id) => Number.isInteger(id) && id > 0),
          ...(Number.isInteger(pendingPick) && pendingPick > 0 ? [pendingPick] : [])
        ])
      ];
      const res = await createOracFormDetail(body);
      const newIdRaw = res?.insertedId ?? res?.insertId;
      const newId =
        newIdRaw != null && newIdRaw !== '' ? Number(newIdRaw) : NaN;

      if (
        Number.isInteger(newId) &&
        newId > 0 &&
        (locationIdsToMap.length > 0 || sectionIdsToMap.length > 0)
      ) {
        try {
          for (const lid of locationIdsToMap) {
            await mapLocationToForm(newId, lid);
          }
          for (const sid of sectionIdsToMap) {
            await mapSectionToForm(newId, sid);
          }
        } catch (mapErr) {
          setError(
            `Form created (id ${newId}), but linking a location or section failed: ${mapErr.message || 'Unknown error'}. You can add them on the form details page.`
          );
          setMessage('');
          setNewFormTitle('');
          setNewFormDescription('');
          const now = localDateParts(new Date());
          setNewFormCreatedDate(now.dateStr);
          setNewFormCreatedTime(now.timeStr);
          setNewFormParentId('');
          setSelectedSectionIds(new Set());
          setSelectedLocationIds(new Set());
          setLocationCountryFilter('');
          setLocationDropdownPick('');
          await loadCatalog();
          return;
        }
      }

      setNewFormTitle('');
      setNewFormDescription('');
      const now = localDateParts(new Date());
      setNewFormCreatedDate(now.dateStr);
      setNewFormCreatedTime(now.timeStr);
      setNewFormParentId('');
      setSelectedSectionIds(new Set());
      setSelectedLocationIds(new Set());
      setLocationCountryFilter('');
      setLocationDropdownPick('');
      await loadCatalog();
      openSuccessDialog('Form created', `Form #${newId > 0 ? newId : 'new'} was created successfully.`);
    } catch (err) {
      setError(err.message || 'Could not create form');
    } finally {
      setBusy(false);
    }
  };

  if (loading) {
    return (
      <main className="dashboard-main admin-dashboard admin-dashboard-v2 admin-form-builder admin-orac-page admin-forms-page">
        <p style={{ textAlign: 'center', padding: 40, color: 'var(--theme-gray-500)' }}>Loading…</p>
      </main>
    );
  }

  return (
    <main className="dashboard-main admin-dashboard admin-dashboard-v2 admin-form-builder admin-orac-page admin-forms-page">
      <header className="admin-page-header">
        <div>
          <div className="admin-page-badge">Admin</div>
          <h1>Add form</h1>
          <p className="admin-forms-page__intro">
            Create a new form here. Use <strong>Form list</strong> or <strong>Edit form</strong> in the sidebar to open an
            existing form and attach sections and questions.
          </p>
        </div>
      </header>

      {error && (
        <p className="admin-form-builder-msg admin-form-builder-msg--err" role="alert">
          {error}
        </p>
      )}
      {message && !error && <p className="admin-form-builder-msg admin-form-builder-msg--ok">{message}</p>}

      <div className="admin-form-builder-panel">
        <div className="admin-forms-content">
          <section className="admin-forms-panel" aria-labelledby="admin-forms-create-title">
            <h2 id="admin-forms-create-title" className="admin-forms-panel__title">
              Create form
            </h2>
            <p className="admin-forms-panel__lead">
              Enter the title, description, optional parent form, and when the form was created. Leave parent as “None” for
              a new standalone form. Choose a country, then pick each location from the dropdown — each is linked to this
              form when you save. Then select sections below.
            </p>

            <form onSubmit={handleCreateForm} className="admin-forms-create-grid">
              <div className="admin-form-builder-field">
                <label htmlFor="new-form-title">Title</label>
                <input
                  id="new-form-title"
                  value={newFormTitle}
                  onChange={(ev) => setNewFormTitle(ev.target.value)}
                  placeholder="e.g. Site ORAC — 2025"
                  disabled={busy}
                  autoComplete="off"
                />
              </div>
              <div className="admin-form-builder-field">
                <label htmlFor="new-form-parent">Parent form</label>
                <select
                  id="new-form-parent"
                  value={newFormParentId}
                  onChange={(ev) => setNewFormParentId(ev.target.value)}
                  disabled={busy}
                >
                  <option value="">None — root form (no parent)</option>
                  {formsForParentSelect.map((f) => (
                    <option key={f.form_id} value={String(f.form_id)}>
                      #{f.form_id} — {f.title || 'Untitled'}
                      {f.form_parent_id != null &&
                      f.form_parent_id !== '' &&
                      Number(f.form_parent_id) > 0
                        ? ` (child of #${f.form_parent_id})`
                        : ''}
                    </option>
                  ))}
                </select>
                <p className="admin-form-builder-hint">
                  Optional. To base this form on an existing one, pick a parent — or open <strong>Form details</strong> later
                  to adjust sections (that may create a new version).
                </p>
              </div>
              <div className="admin-form-builder-field">
                <label htmlFor="new-form-desc">Description (optional)</label>
                <textarea
                  id="new-form-desc"
                  value={newFormDescription}
                  onChange={(ev) => setNewFormDescription(ev.target.value)}
                  placeholder="Short internal note"
                  disabled={busy}
                />
              </div>
              <div className="admin-forms-datetime-row">
                <div className="admin-form-builder-field">
                  <label htmlFor="new-form-created-date">Created date</label>
                  <input
                    id="new-form-created-date"
                    type="date"
                    value={newFormCreatedDate}
                    onChange={(ev) => setNewFormCreatedDate(ev.target.value)}
                    disabled={busy}
                  />
                </div>
                <div className="admin-form-builder-field">
                  <label htmlFor="new-form-created-time">Created time</label>
                  <input
                    id="new-form-created-time"
                    type="time"
                    value={newFormCreatedTime}
                    onChange={(ev) => setNewFormCreatedTime(ev.target.value)}
                    disabled={busy}
                  />
                </div>
                <p className="admin-forms-datetime-row__hint admin-form-builder-hint">
                  Filled automatically with the current date and time; you can change them before saving.
                </p>
              </div>

              <div className="admin-form-builder-field admin-form-builder-field--full">
                <div className="admin-forms-section-picker">
                  <div className="admin-forms-section-picker__head">
                    <label htmlFor="new-form-location-country" className="admin-forms-section-picker__title">
                      Locations for this form
                    </label>
                    <p className="admin-forms-section-picker__subtitle">
                      Pick a country to load sites, then choose each location from the dropdown — it is added to this form
                      right away. When you click <strong>Create form</strong>, those locations are saved with the form.
                    </p>
                  </div>
                  <div className="admin-form-builder-field admin-forms-section-picker__country-field">
                    <label htmlFor="new-form-location-country">Country</label>
                    <select
                      id="new-form-location-country"
                      value={locationCountryFilter}
                      onChange={(ev) => setLocationCountryFilter(ev.target.value)}
                      disabled={busy}
                    >
                      <option value="">— Select country —</option>
                      <option value="all">All countries</option>
                      {countriesSorted.map((c) => (
                        <option key={c.country_id} value={String(c.country_id)}>
                          {c.country_name || `Country #${c.country_id}`}
                        </option>
                      ))}
                    </select>
                    <p className="admin-form-builder-hint">Only locations in the selected country are shown.</p>
                  </div>
                  {!locationCountryFilter ? (
                    <p className="admin-forms-section-picker__empty">Select a country to load locations for the dropdown.</p>
                  ) : filteredLocations.length === 0 ? (
                    <p className="admin-forms-section-picker__empty">No locations in the catalog for this filter.</p>
                  ) : (
                    <div className="admin-forms-location-dropdown-block">
                      <div className="admin-form-builder-field">
                        <label htmlFor="new-form-location-pick">Add location to this form</label>
                        <select
                          id="new-form-location-pick"
                          value={locationDropdownPick}
                          onChange={(ev) => handleLocationSelectChange(ev.target.value)}
                          disabled={busy || !locationsAvailableInDropdown.length}
                        >
                          <option value="">
                            {locationsAvailableInDropdown.length
                              ? '— Choose a location to add —'
                              : '— All matching locations already added —'}
                          </option>
                          {locationsAvailableInDropdown.map((loc) => (
                            <option key={loc.location_id} value={String(loc.location_id)}>
                              {locationDisplayName(loc)} (#{loc.location_id})
                            </option>
                          ))}
                        </select>
                        <p className="admin-form-builder-hint">
                          Each choice is added to the list below right away. Use Remove if you change your mind.
                        </p>
                      </div>
                    </div>
                  )}
                  {selectedLocationsDisplay.length > 0 && (
                    <div className="admin-forms-selected-locations">
                      <p className="admin-forms-selected-locations__label">Locations that will be linked when you create the form</p>
                      <ul className="admin-forms-selected-locations__list">
                        {selectedLocationsDisplay.map(({ id: lid, loc }) => {
                          const cname = loc
                            ? countries.find((x) => String(x.country_id) === String(loc.country_id))?.country_name ||
                              (loc.country_id != null ? `#${loc.country_id}` : '—')
                            : '—';
                          return (
                            <li key={lid} className="admin-forms-selected-locations__item">
                              <span>
                                <strong>{loc ? locationDisplayName(loc) : `Location #${lid}`}</strong>
                                <span className="admin-forms-selected-locations__meta">
                                  {' '}
                                  · #{lid}
                                  {loc ? ` · ${cname}` : ''}
                                </span>
                              </span>
                              <button
                                type="button"
                                className="admin-outline-button"
                                onClick={() => removeSelectedLocation(lid)}
                                disabled={busy}
                              >
                                Remove
                              </button>
                            </li>
                          );
                        })}
                      </ul>
                    </div>
                  )}
                </div>
              </div>

              <div className="admin-form-builder-field admin-form-builder-field--full">
                <div className="admin-forms-section-picker">
                  <div className="admin-forms-section-picker__head">
                    <label id="new-form-sections-label" className="admin-forms-section-picker__title">
                      Sections to include
                    </label>
                    <p className="admin-forms-section-picker__subtitle">
                      Optional — selected sections are linked to the form when you save.
                    </p>
                  </div>
                  {sectionsCatalog.length === 0 ? (
                    <p className="admin-forms-section-picker__empty">
                      No sections yet. Create one under <strong>Section management</strong> in the sidebar first.
                    </p>
                  ) : (
                    <div
                      className="admin-forms-section-picker__scroll"
                      role="group"
                      aria-labelledby="new-form-sections-label"
                    >
                      <div className="admin-forms-section-picker__grid">
                        {[...sectionsCatalog]
                          .sort((a, b) => Number(a.section_id) - Number(b.section_id))
                          .map((s) => {
                            const sid = s.section_id;
                            const label = s.title || `Section ${sid}`;
                            const checked = selectedSectionIds.has(sid);
                            return (
                              <label
                                key={sid}
                                className={
                                  checked
                                    ? 'admin-forms-section-picker__item admin-forms-section-picker__item--on'
                                    : 'admin-forms-section-picker__item'
                                }
                              >
                                <input
                                  type="checkbox"
                                  checked={checked}
                                  onChange={() => toggleSectionId(sid)}
                                  disabled={busy}
                                />
                                <span className="admin-forms-section-picker__text">
                                  <span className="admin-forms-section-picker__name">{label}</span>
                                  <span className="admin-forms-section-picker__id">#{sid}</span>
                                </span>
                              </label>
                            );
                          })}
                      </div>
                    </div>
                  )}
                </div>
              </div>

              <div className="admin-forms-create-actions">
                <button type="submit" className="admin-action-button" disabled={busy}>
                  Create form
                </button>
              </div>
            </form>
          </section>
        </div>
      </div>

      {successDialog.open && (
        <div
          className="admin-orac-form-popup-overlay"
          role="dialog"
          aria-modal="true"
          aria-labelledby="admin-form-create-success-title"
          onClick={(e) => {
            if (e.target === e.currentTarget) closeSuccessDialogAndGoToList();
          }}
        >
          <div className="admin-orac-form-popup-dialog">
            <h3 id="admin-form-create-success-title">{successDialog.title}</h3>
            <p>{successDialog.body}</p>
            <button
              type="button"
              className="admin-action-button admin-orac-form-popup-ok"
              onClick={closeSuccessDialogAndGoToList}
            >
              Go to form list
            </button>
          </div>
        </div>
      )}
    </main>
  );
}

export default AdminFormsCompositionPage;
