import React, { useState, useEffect, useCallback } from 'react';
import { Button, Spinner, Badge, Form } from 'react-bootstrap';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import {
  faChevronRight, faChevronLeft, faSearch,
  faCheck, faTimes, faShieldAlt
} from '@fortawesome/free-solid-svg-icons';
import { getResourceOptions, assignCapability } from '../services/authorizationService';
import { Modal, ModalHeader } from '../../../globalComponents/ui/Modal';
import MultiSelectDropdown from '../../../globalComponents/form/dropdowns/MultiSelectDropdown';

/**
 * CapabilityAssignDrawer
 *
 * Props:
 *   show: boolean
 *   onHide: () => void
 *   capability: { id, name, requiredDimensions: string[], description }
 *   resourceTypeMap: { [name]: ResourceTypeEntity }  — name -> { relationType, parentTypeId, ... }
 *   userId: number
 *   onAssigned: () => void
 */

// Resolve the full structural chain for a dimension that is STRUCTURAL:
// e.g. dimension = 'tree' but chain is project -> plot -> tree
const resolveStructuralChain = (dimensionName, resourceTypeMap) => {
  // Build parent->children map
  const nameById = {};
  Object.values(resourceTypeMap).forEach(rt => { nameById[rt.id] = rt.name; });

  // Find root: the ancestor of dimensionName with no parent (within STRUCTURAL)
  const chain = [];
  let current = resourceTypeMap[dimensionName];
  while (current) {
    chain.unshift(current);
    if (!current.parentTypeId) break;
    const parentName = nameById[current.parentTypeId];
    current = parentName ? resourceTypeMap[parentName] : null;
  }
  return chain; // [root, ..., leaf=dimension]
};

// ── Single dimension step ─────────────────────────────────────────────────────
const DimensionStep = ({ stepIndex, totalSteps, dimension, resourceTypeMap, parentResourceId, onSelect, selectedIds, isLast }) => {
  const [resources, setResources] = useState([]);
  const [loading, setLoading] = useState(true);
  const [search, setSearch] = useState('');

  useEffect(() => {
    setLoading(true);
    setSearch('');
    getResourceOptions({ resourceType: dimension, resourceId: parentResourceId })
      .then(setResources)
      .catch(() => setResources([]))
      .finally(() => setLoading(false));
  }, [dimension, parentResourceId]);

  const filtered = resources.filter(r =>
    !search || r.name.toLowerCase().includes(search.toLowerCase())
  );

  return (
    <div className="dim-step">
      <div className="dim-step-header">
        <span className="dim-step-label">
          {stepIndex + 1} / {totalSteps}
        </span>
        <span className="dim-step-type">{dimension}</span>
        {isLast && <Badge className="dim-last-badge">Multi-select</Badge>}
      </div>

      {isLast ? (
        loading ? (
          <div className="dim-loading" style={{ margin: "20px 0" }}><Spinner size="sm" /> Loading...</div>
        ) : (
          <div style={{ padding: "10px 0 160px" }}>
            <MultiSelectDropdown
              options={resources.map(r => ({ value: r.id, label: r.name }))}
              selected={selectedIds}
              onChange={(newIds) => {
                const selectedResources = resources.filter(r => newIds.includes(r.id));
                onSelect(null, isLast, selectedResources);
              }}
              placeholder={`Select ${dimension}...`}
            />
          </div>
        )
      ) : (
        <>
          <div className="dim-search-wrap">
            <FontAwesomeIcon icon={faSearch} className="dim-search-icon" />
            <input
              type="text"
              placeholder={`Search ${dimension}...`}
              value={search}
              onChange={e => setSearch(e.target.value)}
              className="dim-search-input"
            />
          </div>

          <div className="dim-resource-list">
            {loading ? (
              <div className="dim-loading"><Spinner size="sm" /> Loading...</div>
            ) : filtered.length === 0 ? (
              <div className="dim-empty">No resources found</div>
            ) : filtered.map(r => {
              const selected = selectedIds.includes(r.id);
              return (
                <div
                  key={r.id}
                  className={`dim-resource-item ${selected ? 'selected' : ''}`}
                  onClick={() => onSelect(r, isLast)}
                >
                  <span className="dim-resource-name">{r.name}</span>
                  {selected
                    ? <FontAwesomeIcon icon={faCheck} className="dim-check" />
                    : !isLast && <FontAwesomeIcon icon={faChevronRight} className="dim-arrow" />
                  }
                </div>
              );
            })}
          </div>
        </>
      )}
    </div>
  );
};

// ── Main Drawer ───────────────────────────────────────────────────────────────
const CapabilityAssignDrawer = ({ show, onHide, capability, resourceTypeMap, userId, onAssigned }) => {
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState(null);

  // scope state: array of { dimensionName, selectedResources: [{id,name}] }
  // We walk through requiredDimensions one by one
  const [scopeSteps, setScopeSteps] = useState([]); // built as user selects
  const [structuralSteps, setStructuralSteps] = useState([]); // for current structural dim

  const dims = capability?.requiredDimensions || [];
  const hasDimensions = dims.length > 0;

  // Reset on open
  useEffect(() => {
    if (show) {
      setScopeSteps([]);
      setStructuralSteps([]);
      setError(null);
    }
  }, [show, capability?.id]);

  // Current dimension index we are collecting
  const currentDimIdx = scopeSteps.length; // 0-based; when === dims.length we're done
  const isDone = currentDimIdx >= dims.length;

  // Current dimension
  const currentDimName = !isDone ? dims[currentDimIdx] : null;
  const currentRT = currentDimName ? resourceTypeMap?.[currentDimName] : null;
  const isStructural = currentRT?.relationType === 'STRUCTURAL';

  // For structural: resolve the chain once per dim
  const structuralChain = isStructural && currentDimName
    ? resolveStructuralChain(currentDimName, resourceTypeMap || {})
    : [];

  // For structural we walk structuralSteps (sub-steps within this dim)
  // structuralSteps = [{ typeName, selectedResource: {id,name} }, ...]
  const structuralLevel = structuralSteps.length; // which level in chain we're at
  const atLeaf = isStructural && structuralLevel === structuralChain.length - 1;
  const parentForNextStructural = structuralSteps.length > 0
    ? structuralSteps[structuralSteps.length - 1].selectedResource?.id
    : undefined;

  // Handle selection for contextual (non-structural) dimension
  const handleContextualSelect = (resource, isLast, allSelectedResources) => {
    if (isLast) {
      if (allSelectedResources) {
        setScopeSteps(prev => {
          const without = prev.filter(s => s.dim !== currentDimName);
          return [...without, { dim: currentDimName, selected: allSelectedResources }];
        });
        return;
      }
      // Toggle multi-select on last dim
      setScopeSteps(prev => {
        const existing = prev.find(s => s.dim === currentDimName);
        if (existing) {
          const alreadyIn = existing.selected.find(r => r.id === resource.id);
          return prev.map(s => s.dim === currentDimName
            ? { ...s, selected: alreadyIn ? s.selected.filter(r => r.id !== resource.id) : [...s.selected, resource] }
            : s
          );
        }
        return [...prev, { dim: currentDimName, selected: [resource] }];
      });
    } else {
      // Single select, advance to next dim
      setScopeSteps(prev => {
        const without = prev.filter(s => s.dim !== currentDimName);
        return [...without, { dim: currentDimName, selected: [resource] }];
      });
    }
  };

  // Confirm current contextual dim and advance
  const confirmContextualDim = () => {
    // already in scopeSteps — just proceed (currentDimIdx advances automatically)
  };

  // Handle structural level selection
  const handleStructuralSelect = (resource, isLast, allSelectedResources) => {
    if (atLeaf) {
      if (allSelectedResources) {
        setScopeSteps(prev => {
          const without = prev.filter(s => s.dim !== currentDimName);
          return [...without, { dim: currentDimName, selected: allSelectedResources }];
        });
        return;
      }
      // Toggle multi-select at leaf
      setScopeSteps(prev => {
        const existing = prev.find(s => s.dim === currentDimName);
        if (existing) {
          const alreadyIn = existing.selected.find(r => r.id === resource.id);
          return prev.map(s => s.dim === currentDimName
            ? { ...s, selected: alreadyIn ? s.selected.filter(r => r.id !== resource.id) : [...s.selected, resource] }
            : s
          );
        }
        return [...prev, { dim: currentDimName, selected: [resource] }];
      });
    } else {
      // Drill down
      setStructuralSteps(prev => [...prev.slice(0, structuralLevel), { typeName: structuralChain[structuralLevel].name, selectedResource: resource }]);
    }
  };

  // Confirm structural dim (leaf selected), advance to next dim
  const confirmStructuralDim = () => {
    setStructuralSteps([]);
  };

  // Go back one structural level
  const structuralBack = () => {
    setStructuralSteps(prev => prev.slice(0, -1));
    setScopeSteps(prev => prev.filter(s => s.dim !== currentDimName));
  };

  // Go back one dimension
  const dimBack = () => {
    setScopeSteps(prev => prev.slice(0, -1));
    setStructuralSteps([]);
  };

  // Current selected ids for rendering
  const currentSelected = scopeSteps.find(s => s.dim === currentDimName)?.selected || [];
  const currentSelectedIds = currentSelected.map(r => r.id);

  // Build final scope object
  const buildScope = () => {
    const scope = {};
    scopeSteps.forEach(({ dim, selected }) => {
      scope[dim] = selected.length === 1 ? selected[0].id : selected.map(r => r.id);
    });
    return scope;
  };

  const handleAssign = async () => {
    setSaving(true);
    setError(null);
    try {
      const scope = hasDimensions ? buildScope() : {};
      await assignCapability({ userId, capabilityId: capability.id, scope });
      onAssigned?.();
      onHide();
    } catch (e) {
      setError(e?.message || 'Failed to assign capability');
    } finally {
      setSaving(false);
    }
  };

  const canAssign = !hasDimensions || (isDone && scopeSteps.every(s => s.selected.length > 0));

  // ── Render current step ───────────────────────────────────────────────────
  const renderCurrentStep = () => {
    if (!hasDimensions || isDone) return null;

    if (isStructural) {
      const chainLevel = structuralLevel < structuralChain.length ? structuralChain[structuralLevel] : null;
      if (!chainLevel) return null;

      const isLeafLevel = structuralLevel === structuralChain.length - 1;
      const parentId = structuralLevel > 0
        ? structuralSteps[structuralLevel - 1].selectedResource?.id
        : undefined;

      return (
        <DimensionStep
          key={`${currentDimName}-${structuralLevel}`}
          stepIndex={currentDimIdx}
          totalSteps={dims.length}
          dimension={chainLevel.name}
          resourceTypeMap={resourceTypeMap}
          parentResourceId={parentId}
          selectedIds={isLeafLevel ? currentSelectedIds : (structuralSteps[structuralLevel]?.selectedResource ? [structuralSteps[structuralLevel].selectedResource.id] : [])}
          onSelect={handleStructuralSelect}
          isLast={isLeafLevel}
        />
      );
    }

    // Contextual
    const isLastDim = currentDimIdx === dims.length - 1;
    return (
      <DimensionStep
        key={currentDimName}
        stepIndex={currentDimIdx}
        totalSteps={dims.length}
        dimension={currentDimName}
        resourceTypeMap={resourceTypeMap}
        parentResourceId={undefined}
        selectedIds={currentSelectedIds}
        onSelect={handleContextualSelect}
        isLast={isLastDim}
      />
    );
  };

  // Determine if we should show "Next" or the step auto-advances
  const showNextBtn = () => {
    if (!hasDimensions || isDone) return false;
    if (isStructural) {
      if (atLeaf) return currentSelectedIds.length > 0; // confirm leaf
      return false; // structural non-leaf auto-drills on click
    }
    // contextual last dim: show Next to confirm
    if (currentDimIdx === dims.length - 1) return currentSelectedIds.length > 0;
    // contextual non-last: auto-advance on single click — no Next needed
    return false;
  };

  const handleNext = () => {
    if (isStructural && atLeaf) {
      confirmStructuralDim();
    }
    // For contextual last dim — scopeSteps already has selection, just force advance
    // We do this by ensuring the step is committed
  };

  return (
    <Modal show={show} onClose={onHide} maxWidth={640}>
      <ModalHeader title={capability?.name || 'Assign Capability'} subtitle={capability?.description || ''} onClose={onHide} />
      <div style={{ padding: "18px 24px 24px", overflowY: "auto", maxHeight: "80vh", display: "flex", flexDirection: "column", gap: 14 }}>
        {error && <div className="cap-assign-error">{error}</div>}

        {!hasDimensions ? (
          <div className="cap-no-dims">
            <FontAwesomeIcon icon={faShieldAlt} />
            <p>This capability applies globally — no scope required.</p>
          </div>
        ) : (
          <>
            {/* Progress breadcrumb */}
            <div className="cap-dim-progress">
              {dims.map((dim, i) => {
                const done = i < currentDimIdx;
                const active = i === currentDimIdx;
                const step = scopeSteps.find(s => s.dim === dim);
                return (
                  <React.Fragment key={dim}>
                    <div className={`cap-dim-crumb ${done ? 'done' : ''} ${active ? 'active' : ''}`}>
                      <div className="cap-dim-crumb-dot">
                        {done ? <FontAwesomeIcon icon={faCheck} /> : i + 1}
                      </div>
                      <div className="cap-dim-crumb-info">
                        <span className="cap-dim-crumb-name">{dim}</span>
                        {done && step && (
                          <span className="cap-dim-crumb-val">
                            {step.selected.map(r => r.name).join(', ')}
                          </span>
                        )}
                      </div>
                    </div>
                    {i < dims.length - 1 && <div className={`cap-dim-connector ${done ? 'done' : ''}`} />}
                  </React.Fragment>
                );
              })}
            </div>

            {/* Structural breadcrumb within current dim */}
            {isStructural && structuralChain.length > 1 && (
              <div className="structural-trail">
                {structuralChain.slice(0, structuralLevel + 1).map((rt, i) => (
                  <React.Fragment key={rt.name}>
                    {i > 0 && <FontAwesomeIcon icon={faChevronRight} className="trail-sep" />}
                    <span
                      className={`trail-item ${i === structuralLevel ? 'active' : 'done'}`}
                      onClick={() => i < structuralLevel && setStructuralSteps(prev => prev.slice(0, i))}
                    >
                      {i < structuralLevel ? structuralSteps[i]?.selectedResource?.name : rt.name}
                    </span>
                  </React.Fragment>
                ))}
              </div>
            )}

            {/* Current step */}
            {!isDone && renderCurrentStep()}

            {/* Done state */}
            {isDone && (
              <div className="cap-scope-summary">
                <div className="scope-summary-title">Scope Summary</div>
                {scopeSteps.map(({ dim, selected }) => (
                  <div key={dim} className="scope-summary-row">
                    <span className="scope-summary-dim">{dim}</span>
                    <div className="scope-summary-vals">
                      {selected.map(r => (
                        <Badge key={r.id} className="scope-val-badge">{r.name}</Badge>
                      ))}
                    </div>
                  </div>
                ))}
              </div>
            )}
          </>
        )}

        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginTop: 12 }}>
          <div className="cap-assign-footer-left">
            {hasDimensions && !isDone && currentDimIdx > 0 && !isStructural && (
              <button className="cap-back-btn" onClick={dimBack}>
                <FontAwesomeIcon icon={faChevronLeft} className="me-1" /> Back
              </button>
            )}
            {hasDimensions && !isDone && isStructural && structuralLevel > 0 && (
              <button className="cap-back-btn" onClick={structuralBack}>
                <FontAwesomeIcon icon={faChevronLeft} className="me-1" /> Back
              </button>
            )}
            {hasDimensions && isDone && (
              <button className="cap-back-btn" onClick={dimBack}>
                <FontAwesomeIcon icon={faChevronLeft} className="me-1" /> Edit scope
              </button>
            )}
          </div>
          <div className="cap-assign-footer-right" style={{ display: "flex", gap: 8 }}>
            <Button variant="outline-secondary" onClick={onHide}>Cancel</Button>
            {showNextBtn() && (
              <Button className="auth-btn-primary" onClick={handleNext}>
                Confirm selection
              </Button>
            )}
            {(isDone || !hasDimensions) && (
              <Button className="auth-btn-primary" onClick={handleAssign} disabled={saving}>
                {saving && <Spinner size="sm" className="me-2" />}
                Assign Capability
              </Button>
            )}
          </div>
        </div>
      </div>
    </Modal>
  );
};

export default CapabilityAssignDrawer;