import { useEffect, useState, useRef, useCallback, useMemo } from 'react';
import { fetchUsers, fetchRoles, fetchUserRoles, assignExecutor, assignVerifier, addParticipant } from '../../api.js';
import {
  isExecuterVerifierRole,
  normalizeRoleKey,
  RISK_EXECUTOR_VERIFIER_ROLE_ID
} from '../../authRoles.js';
import { uploadAssetUrl } from '../../apiConfig.js';
import './admin-shared.css';
import './AdminAssignVideoPage.css';

/** Users who may be assigned as executor (role_id 4 EXECUTER/VARIFIER, or legacy name match). */
function userQualifiesAsExecutor(roleNames, roleIds) {
  if ((roleIds || []).some((rid) => Number(rid) === RISK_EXECUTOR_VERIFIER_ROLE_ID)) {
    return true;
  }
  return (roleNames || []).some(
    (n) => isExecuterVerifierRole(n) || normalizeRoleKey(n) === 'executor'
  );
}

/** Users who may be assigned as verifier (same EV role id 4, or legacy name match). */
function userQualifiesAsVerifier(roleNames, roleIds) {
  if ((roleIds || []).some((rid) => Number(rid) === RISK_EXECUTOR_VERIFIER_ROLE_ID)) {
    return true;
  }
  return (roleNames || []).some(
    (n) => isExecuterVerifierRole(n) || normalizeRoleKey(n) === 'verifier'
  );
}

function buildUserIdToRoleNames(users, roles, userRoleRows) {
  const roleNameById = new Map((roles || []).map((r) => [r.role_id, r.role_name]));
  const map = new Map();
  for (const u of users || []) {
    map.set(u.user_id, { names: [], ids: [] });
  }
  for (const ur of userRoleRows || []) {
    if (!map.has(ur.user_id)) map.set(ur.user_id, { names: [], ids: [] });
    const entry = map.get(ur.user_id);
    entry.ids.push(ur.role_id);
    const name = roleNameById.get(ur.role_id);
    if (name != null) entry.names.push(name);
  }
  return map;
}

function SearchSelect({ id, label, value, options, onChange, required, placeholder }) {
  const [search, setSearch] = useState('');
  const [open, setOpen] = useState(false);
  const wrapRef = useRef(null);

  const selectedLabel = options.find((o) => String(o.value) === String(value))?.label || '';

  const filtered = options.filter((o) =>
    o.label.toLowerCase().includes(search.toLowerCase())
  );

  useEffect(() => {
    const handler = (e) => {
      if (wrapRef.current && !wrapRef.current.contains(e.target)) setOpen(false);
    };
    document.addEventListener('mousedown', handler);
    return () => document.removeEventListener('mousedown', handler);
  }, []);

  const handlePick = (val) => {
    onChange(val);
    setSearch('');
    setOpen(false);
  };

  const handleClear = (e) => {
    e.stopPropagation();
    onChange('');
    setSearch('');
  };

  return (
    <div className="assign-field" ref={wrapRef}>
      <label htmlFor={id}>{label}</label>
      <div className={`ss-wrap ${open ? 'ss-wrap--open' : ''}`}>
        <input
          id={id}
          className="ss-input"
          type="text"
          autoComplete="off"
          placeholder={value ? selectedLabel : (placeholder || 'Search and select...')}
          value={open ? search : (value ? selectedLabel : '')}
          onFocus={() => { setOpen(true); setSearch(''); }}
          onChange={(e) => setSearch(e.target.value)}
        />
        {value && (
          <button type="button" className="ss-clear" onClick={handleClear} aria-label="Clear">×</button>
        )}
        {open && (
          <ul className="ss-dropdown">
            {filtered.length === 0 && (
              <li className="ss-empty">No matches</li>
            )}
            {filtered.map((o) => (
              <li
                key={o.value}
                className={`ss-option ${String(o.value) === String(value) ? 'ss-option--selected' : ''}`}
                onMouseDown={() => handlePick(String(o.value))}
              >
                {o.label}
              </li>
            ))}
          </ul>
        )}
      </div>
      {required && <input type="hidden" required value={value} />}
    </div>
  );
}

function AdminAssignVideoPage({ video, onBack, onAssignmentComplete }) {
  const [users, setUsers] = useState([]);
  const [roles, setRoles] = useState([]);
  const [userRoleRows, setUserRoleRows] = useState([]);
  const [executor, setExecutor] = useState('');
  const [participant1, setParticipant1] = useState('');
  const [participant2, setParticipant2] = useState('');
  const [participant3, setParticipant3] = useState('');
  const [verifier, setVerifier] = useState('');
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState('');
  const [showSuccessModal, setShowSuccessModal] = useState(false);
  const onCompleteRef = useRef(onAssignmentComplete);
  onCompleteRef.current = onAssignmentComplete;

  useEffect(() => {
    let cancelled = false;
    setError('');
    Promise.all([fetchUsers(), fetchRoles(), fetchUserRoles()])
      .then(([u, r, ur]) => {
        if (cancelled) return;
        setUsers(Array.isArray(u) ? u : []);
        setRoles(Array.isArray(r) ? r : []);
        setUserRoleRows(Array.isArray(ur) ? ur : []);
      })
      .catch((e) => {
        if (!cancelled) setError(`Could not load users or roles: ${e.message}`);
      });
    return () => {
      cancelled = true;
    };
  }, []);

  const userIdToRoleNames = useMemo(
    () => buildUserIdToRoleNames(users, roles, userRoleRows),
    [users, roles, userRoleRows]
  );

  const executorUserOptions = useMemo(() => {
    return users
      .filter((u) => {
        const row = userIdToRoleNames.get(u.user_id);
        return userQualifiesAsExecutor(row?.names, row?.ids);
      })
      .map((u) => ({
        value: u.user_id,
        label: u.employee_name || u.email_id || `User ${u.user_id}`
      }));
  }, [users, userIdToRoleNames]);

  const verifierUserOptions = useMemo(() => {
    return users
      .filter((u) => {
        const row = userIdToRoleNames.get(u.user_id);
        return userQualifiesAsVerifier(row?.names, row?.ids);
      })
      .map((u) => ({
        value: u.user_id,
        label: u.employee_name || u.email_id || `User ${u.user_id}`
      }));
  }, [users, userIdToRoleNames]);

  const participantUserOptions = useMemo(
    () =>
      users.map((u) => ({
        value: u.user_id,
        label: u.employee_name || u.email_id || `User ${u.user_id}`
      })),
    [users]
  );

  const handleSubmit = async (e) => {
    e.preventDefault();

    if (!executor || !verifier) {
      setError('Executor and Verifier are required.');
      return;
    }

    setSubmitting(true);
    setError('');

    try {
      await assignExecutor(video.assessment_id, Number(executor));
      await assignVerifier(video.assessment_id, Number(verifier));

      const participants = [participant1, participant2, participant3].filter(Boolean);
      for (const pid of participants) {
        await addParticipant(video.assessment_id, Number(pid));
      }

      setShowSuccessModal(true);
    } catch (err) {
      setError(err.message);
    } finally {
      setSubmitting(false);
    }
  };

  const selected = { executor, participant1, participant2, participant3, verifier };

  const getAvailable = (fieldName) => {
    const base =
      fieldName === 'executor'
        ? executorUserOptions
        : fieldName === 'verifier'
          ? verifierUserOptions
          : participantUserOptions;
    const taken = new Set(
      Object.entries(selected)
        .filter(([n, v]) => {
          if (!v || n === fieldName) return false;
          if (fieldName === 'executor' && n === 'verifier') return false;
          if (fieldName === 'verifier' && n === 'executor') return false;
          return true;
        })
        .map(([, v]) => String(v))
    );
    return base.filter(
      (o) => !taken.has(String(o.value)) || String(o.value) === String(selected[fieldName])
    );
  };

  const videoUrl = uploadAssetUrl(video.video);

  const runNavigateToAssigned = useCallback(() => {
    const fn = onCompleteRef.current;
    if (typeof fn === 'function') fn();
  }, []);

  return (
    <main className="dashboard-main">
      <header className="admin-page-header admin-page-header--with-actions">
        <div>
          <div className="admin-page-badge">Video assignment</div>
          <h1>Video Details</h1>
          <p>Review the uploaded video and assign team members. The executor chooses the ORAC form when they open the assessment.</p>
        </div>
        <button type="button" className="admin-outline-button" onClick={onBack}>
          Back to list
        </button>
      </header>

      <div className="assign-layout">
        <div className="assign-top-layout">
          <section className="assign-video-col">
            <div className="assign-video-player">
              {videoUrl ? (
                <video
                  key={videoUrl}
                  className="assign-video-element"
                  controls
                  playsInline
                >
                  <source src={videoUrl} />
                </video>
              ) : (
                <div className="assign-video-placeholder">
                  <div className="assign-play-icon">&#9654;</div>
                  <div className="assign-video-bar">
                    <span>No video file available</span>
                  </div>
                </div>
              )}
            </div>
          </section>

          <section className="assign-details-col">
            <div className="assign-info-card">
              <h2 className="assign-info-heading">Information</h2>
              <dl className="assign-info-grid">
                <dt>Assessment ID</dt>
                <dd>{video.assessment_id}</dd>
                <dt>Video Title</dt>
                <dd>{video.video_title || '—'}</dd>
                <dt>Contract Details</dt>
                <dd>{(video.contract_details ?? video.contact_details) || '—'}</dd>
                <dt>Capture Date</dt>
                <dd>{video.video_capture_date || '—'}</dd>
                <dt>Capture Time</dt>
                <dd>{video.video_capture_time || '—'}</dd>
                <dt>Remarks</dt>
                <dd>{video.remarks || '—'}</dd>
                <dt>Location</dt>
                <dd>{video.location_name || video.Location_name || video.location_id || '—'}</dd>
                <dt>Department</dt>
                <dd>{video.department_name || video.Department_name || video.department_id || '—'}</dd>
                <dt>Status</dt>
                <dd>
                  <span className="status-pill status-pill--warning">
                    {video.assessment_status_name || video._statusLabel || `Status ${video.assessment_status_id}`}
                  </span>
                </dd>
              </dl>
            </div>
          </section>
        </div>

        <form className="assign-form-card" onSubmit={handleSubmit}>
          <h2 className="assign-info-heading">Assign Team</h2>

          {error ? <div className="assign-message assign-message--error">{error}</div> : null}

          <div className="assign-form-grid">
            <SearchSelect id="executor" label="Executor" value={executor} options={getAvailable('executor')} onChange={setExecutor} required placeholder="Search executor..." />
            <SearchSelect id="verifier" label="Verifier" value={verifier} options={getAvailable('verifier')} onChange={setVerifier} required placeholder="Search verifier..." />
            <SearchSelect id="p1" label="Participants 1" value={participant1} options={getAvailable('participant1')} onChange={setParticipant1} placeholder="Search participant..." />
            <SearchSelect id="p2" label="Participants 2" value={participant2} options={getAvailable('participant2')} onChange={setParticipant2} placeholder="Search participant..." />
            <SearchSelect id="p3" label="Participants 3" value={participant3} options={getAvailable('participant3')} onChange={setParticipant3} placeholder="Search participant..." />
          </div>

          <button type="submit" className="assign-submit-button" disabled={submitting}>
            {submitting ? 'Submitting...' : 'Submit Assignment'}
          </button>
        </form>
      </div>

      {showSuccessModal ? (
        <div className="assign-success-overlay" role="dialog" aria-modal="true" aria-labelledby="assign-success-title">
          <div className="assign-success-dialog">
            <button
              type="button"
              className="assign-success-close"
              onClick={() => setShowSuccessModal(false)}
              aria-label="Close success message"
            >
              ×
            </button>
            <div className="assign-success-icon" aria-hidden="true">&#10003;</div>
            <h2 id="assign-success-title" className="assign-success-title">
              Assignment complete
            </h2>
            <p className="assign-success-text">
              The assessment has been assigned successfully. Do you want to go to the assigned videos page?
            </p>
            <div className="assign-success-actions">
              <button type="button" className="assign-success-button" onClick={runNavigateToAssigned}>
                Yes, go now
              </button>
              <button type="button" className="assign-success-button assign-success-button--secondary" onClick={() => setShowSuccessModal(false)}>
                No, stay here
              </button>
            </div>
          </div>
        </div>
      ) : null}
    </main>
  );
}

export default AdminAssignVideoPage;
