import { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';
import {
  deleteOracSnap,
  executorSubmitForVerification,
  fetchAssessmentListProjection,
  fetchFormWithSectionsAndQuestions,
  fetchObservations
} from '../../api.js';
import { API_BASE_URL, getAuthToken } from '../../apiConfig.js';
import {
  getAssignmentStatusDisplayLabel,
  getVerifierReturnRemarks,
  isReturnByVerifier
} from './executorAssignmentCategories.js';
import {
  buildDynamicColumns,
  extractAnswerMapsFromTiming,
  resolveCellRaw
} from '../../utils/oracRiskTableColumns.js';
import './VerifierPage.css';
import './VerifierRiskDocument.css';
import './ExecutorAssignmentDocument.css';

function fmt(v) {
  return v || '—';
}

function fmtDate(v) {
  if (!v) return '—';
  try {
    return new Date(v).toLocaleDateString('en-IN', { day: '2-digit', month: 'short', year: 'numeric' });
  } catch {
    return String(v);
  }
}

function safeJson(str) {
  if (!str) return null;
  if (typeof str === 'object' && !Array.isArray(str)) return str;
  try {
    return JSON.parse(str);
  } catch {
    return null;
  }
}

function parseTiming(snap) {
  const raw = snap?.snap_timing;
  if (!raw) return {};
  return safeJson(raw) || {};
}

function bufferToDataUrl(raw) {
  if (!raw) return null;
  if (typeof raw === 'string' && raw.startsWith('data:')) return raw;

  let bytes = null;
  if (raw && typeof raw === 'object' && raw.type === 'Buffer' && Array.isArray(raw.data)) {
    bytes = new Uint8Array(raw.data);
  } else if (raw instanceof Uint8Array) {
    bytes = raw;
  } else if (raw?.buffer instanceof ArrayBuffer) {
    bytes = new Uint8Array(raw.buffer);
  }

  if (bytes) {
    const CHUNK = 8192;
    let binary = '';
    for (let i = 0; i < bytes.length; i += CHUNK) {
      binary += String.fromCharCode(...bytes.subarray(i, i + CHUNK));
    }
    try {
      return `data:image/jpeg;base64,${btoa(binary)}`;
    } catch {
      return null;
    }
  }

  if (typeof raw === 'string' && raw.length > 100 && !/\s/.test(raw)) {
    return `data:image/jpeg;base64,${raw}`;
  }
  if (typeof raw === 'string' && raw.length > 0) {
    return `${API_BASE_URL}/${raw.replace(/\\/g, '/')}`;
  }
  return null;
}

function snapImageUrl(snapId, assessmentId) {
  const sid = encodeURIComponent(snapId);
  const aid = encodeURIComponent(assessmentId);
  return `${API_BASE_URL}/api/orac/orac_snaps/${sid}/${aid}/image`;
}

function SnapImage({ snap, className, style }) {
  const [src, setSrc] = useState(null);
  const objectUrlRef = useRef(null);

  useEffect(() => {
    const sidRaw = snap?.snap_id;
    const aidRaw = snap?.assessment_id;
    const sid = sidRaw != null ? Number(sidRaw) : NaN;
    const aid = aidRaw != null ? Number(aidRaw) : NaN;
    if (!Number.isFinite(sid) || !Number.isFinite(aid)) {
      setSrc(bufferToDataUrl(snap?.snap));
      return undefined;
    }

    const hasSnap = snap?.has_snap;
    const definitelyNoBlob =
      hasSnap === 0 ||
      hasSnap === false ||
      hasSnap === '0' ||
      (typeof hasSnap === 'string' && hasSnap.trim() === '0');
    if (definitelyNoBlob) {
      setSrc(bufferToDataUrl(snap?.snap));
      return undefined;
    }

    let cancelled = false;
    const token = getAuthToken();

    fetch(snapImageUrl(sid, aid), {
      headers: token ? { Authorization: `Bearer ${token}` } : {},
      cache: 'no-store',
      mode: 'cors',
      credentials: 'omit'
    })
      .then(async (r) => {
        if (!r.ok) return null;
        return r.blob();
      })
      .then((blob) => {
        if (cancelled) return;
        if (!blob || blob.size === 0) {
          setSrc(bufferToDataUrl(snap?.snap));
          return;
        }
        if (objectUrlRef.current) {
          URL.revokeObjectURL(objectUrlRef.current);
          objectUrlRef.current = null;
        }
        const url = URL.createObjectURL(blob);
        objectUrlRef.current = url;
        setSrc(url);
      })
      .catch(() => {
        if (!cancelled) setSrc(bufferToDataUrl(snap?.snap));
      });

    return () => {
      cancelled = true;
      if (objectUrlRef.current) {
        URL.revokeObjectURL(objectUrlRef.current);
        objectUrlRef.current = null;
      }
    };
  }, [snap?.snap_id, snap?.assessment_id, snap?.has_snap]);

  if (!src) {
    return (
      <div className={`vrd-snap-ph ${className || ''}`} style={style}>
        <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5">
          <rect x="3" y="6" width="18" height="14" rx="2" />
          <circle cx="12" cy="13" r="3" />
          <path d="M9 6l1.5-3h3L15 6" />
        </svg>
      </div>
    );
  }
  return (
    <img
      key={src}
      src={src}
      alt=""
      className={className}
      style={style}
      loading="eager"
      decoding="async"
      draggable={false}
      onError={() => {
        const u = objectUrlRef.current;
        objectUrlRef.current = null;
        if (u) URL.revokeObjectURL(u);
        setSrc(null);
      }}
    />
  );
}

// ── RPN role detection ────────────────────────────────────────────────────────
function getRpnRole(questionText) {
  const t = (questionText || '').toLowerCase();
  if (t.includes('likelihood of harm')) return 'likelihood';
  if (t.includes('severity of harm')) return 'severity';
  if (t.includes('rpn')) return 'rpn';
  return null;
}

function extractSnapData(snap) {
  const t = parseTiming(snap);
  return extractAnswerMapsFromTiming(t);
}

/** Styled cell from stored answer; L/S/RPN columns use the same role rules as the snap form. */
function renderDocQuestionCell(byCol, byQid, col) {
  const raw = resolveCellRaw(byCol, byQid, col);
  const display = raw != null && String(raw).trim() !== '' ? String(raw) : '—';
  const role = getRpnRole(col.label);
  if (role === 'likelihood') {
    return <span className="vrd-badge vrd-badge--l">{display}</span>;
  }
  if (role === 'severity') {
    return <span className="vrd-badge vrd-badge--s">{display}</span>;
  }
  if (role === 'rpn') {
    const rpn = Number(display);
    const rpnCls =
      display === '—'
        ? ''
        : rpn >= 32
          ? 'vrd-rpn--hi'
          : rpn >= 8
            ? 'vrd-rpn--mid'
            : 'vrd-rpn--lo';
    return <span className={`vrd-rpn-badge ${rpnCls}`.trim()}>{display}</span>;
  }
  return display;
}

/**
 * Dynamic observations table for the executor document view.
 */
function ExecDynamicSnapTable({ snaps, formSchema, canMutate, deletingId, handleDelete }) {
  const dynCols = buildDynamicColumns(formSchema);
  const totalCols = dynCols.length + 3 + (canMutate ? 1 : 0);
  return (
    <table className="vp-table vrd-table ead-exec-doc-table">
      <thead>
        <tr>
          <th className="vp-th vrd-th vrd-th--narrow" style={{ width: 40 }}>#</th>
          <th className="vp-th vrd-th" style={{ width: 110 }}>
            Risk violation image
          </th>
          <th className="vp-th vrd-th" style={{ width: 88 }}>
            Snap time
          </th>
          {dynCols.map((col) => (
            <th key={col.colKey} className="vp-th vrd-th">
              {col.label}
            </th>
          ))}
          {canMutate ? (
            <th className="vp-th vrd-th vrd-th--narrow ead-exec-doc-th-actions">Actions</th>
          ) : null}
        </tr>
      </thead>
      <tbody>
        {snaps.length === 0 ? (
          <tr>
            <td colSpan={totalCols} className="vp-empty vrd-td-empty">
              <p>No observations saved to the database for this assessment yet.</p>
              <p className="ead-exec-doc-empty-sub">
                Go back to the assessment video, capture a snap, fill the form, and click{' '}
                <strong>Submit observations</strong> to save them here.
              </p>
            </td>
          </tr>
        ) : (
          snaps.map((snap, i) => {
            const { byCol, byQid, violationTime } = extractSnapData(snap);
            return (
              <tr key={snap.snap_id ?? i} className="vp-row vrd-tr">
                <td className="vp-td vrd-td vrd-td--ctr">{i + 1}</td>
                <td className="vp-td vrd-td vrd-td--img">
                  <SnapImage snap={snap} className="vrd-snap-img" />
                </td>
                <td className="vp-td vrd-td vrd-td--ctr vrd-td--mono">{violationTime}</td>
                {dynCols.map((col) => (
                  <td key={col.colKey} className="vp-td vrd-td">
                    {renderDocQuestionCell(byCol, byQid, col)}
                  </td>
                ))}
                {canMutate ? (
                  <td className="vp-td vrd-td vrd-td--ctr ead-exec-doc-td-actions">
                    <button
                      type="button"
                      className="ead-exec-doc-delete"
                      onClick={() => handleDelete(snap)}
                      disabled={deletingId === Number(snap.snap_id)}
                    >
                      {deletingId === Number(snap.snap_id) ? 'Deleting…' : 'Delete'}
                    </button>
                  </td>
                ) : null}
              </tr>
            );
          })
        )}
      </tbody>
    </table>
  );
}

/**
 * Executor view: saved observations from the database, optional delete while in progress,
 * and submit assignment (status 3/4 → 5 verification required).
 */
export default function ExecutorAssignmentDocument({
  assessment,
  onBack,
  onAssessmentUpdated,
  /** If set, successful submit calls this (e.g. navigate to dashboard) instead of the inline success screen. */
  onSubmittedToVerifier
}) {
  const [snaps, setSnaps] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState('');
  const [deletingId, setDeletingId] = useState(null);
  const [submitting, setSubmitting] = useState(false);
  const [submitted, setSubmitted] = useState(false);
  const [confirmOpen, setConfirmOpen] = useState(false);
  const [formSchema, setFormSchema] = useState(null);
  /** Merged with GET assessment row so `assessment_status_id` is current (prop from list can be stale). */
  const [resolvedAssessment, setResolvedAssessment] = useState(assessment);
  const assessmentRef = useRef(assessment);
  useLayoutEffect(() => {
    assessmentRef.current = assessment;
  });

  const statusId = Number(resolvedAssessment?.assessment_status_id);
  const canMutate = statusId === 3 || statusId === 4;
  const canSubmitAssignment = canMutate && snaps.length > 0;

  const load = useCallback(() => {
    const a = assessmentRef.current;
    const aid = Number(a?.assessment_id);
    if (!Number.isFinite(aid) || aid <= 0) {
      setSnaps([]);
      setResolvedAssessment(a);
      setLoading(false);
      return;
    }
    setResolvedAssessment(a);
    setLoading(true);
    setError('');
    Promise.all([fetchObservations(aid), fetchAssessmentListProjection(aid).catch(() => null)])
      .then(([rows, projRow]) => {
        const snapList = Array.isArray(rows) ? rows : [];
        setSnaps(snapList);
        if (projRow && typeof projRow === 'object') {
          setResolvedAssessment((prev) => ({ ...prev, ...projRow }));
        }
        // Load form schema for dynamic columns
        const firstSnap = snapList[0];
        const timingFormId = firstSnap ? safeJson(firstSnap.snap_timing)?.form_id : null;
        const formId = timingFormId ?? a?.form_id ?? a?.orac_form_id;
        const fid = formId != null ? Number(formId) : null;
        if (fid && Number.isFinite(fid) && fid > 0) {
          fetchFormWithSectionsAndQuestions(fid)
            .then((schema) => setFormSchema(schema))
            .catch(() => setFormSchema(null));
        }
      })
      .catch((e) => setError(e.message))
      .finally(() => setLoading(false));
  }, [assessment?.assessment_id, assessment?.form_id, assessment?.orac_form_id]);

  useEffect(() => {
    load();
  }, [load]);

  async function handleDelete(snap) {
    const sid = Number(snap?.snap_id);
    const aid = Number(snap?.assessment_id ?? assessment?.assessment_id);
    if (!Number.isInteger(sid) || !Number.isInteger(aid)) return;
    setDeletingId(sid);
    setError('');
    try {
      await deleteOracSnap(sid, aid);
      load();
    } catch (e) {
      setError(e.message || 'Delete failed.');
    } finally {
      setDeletingId(null);
    }
  }

  async function handleSubmitAssignment() {
    const aid = Number(resolvedAssessment?.assessment_id ?? assessment?.assessment_id);
    if (!Number.isInteger(aid) || aid <= 0) return;
    setConfirmOpen(false);
    setSubmitting(true);
    setError('');
    try {
      const res = await executorSubmitForVerification(aid);
      const row = await fetchAssessmentListProjection(aid);
      const nextStatus = res?.assessment_status_id ?? row?.assessment_status_id;
      if (typeof onAssessmentUpdated === 'function') {
        const base = resolvedAssessment || assessment;
        onAssessmentUpdated(
          row
            ? { ...base, ...row, assessment_status_id: nextStatus ?? row.assessment_status_id }
            : { ...base, assessment_status_id: nextStatus }
        );
      }
      if (typeof onSubmittedToVerifier === 'function') {
        onSubmittedToVerifier();
      } else {
        setSubmitted(true);
      }
    } catch (e) {
      setError(e.message || 'Could not submit assignment.');
    } finally {
      setSubmitting(false);
    }
  }

  const statusLabel = getAssignmentStatusDisplayLabel(resolvedAssessment, { forVerifier: false });

  const submitDisabledReason =
    !canMutate
      ? 'Submit Assignment is only available while the assessment is In progress or Returned from the verifier.'
      : snaps.length === 0
        ? 'Save at least one observation snapshot to the database before submitting.'
        : undefined;

  function openSubmitConfirm() {
    if (loading || submitting || !canSubmitAssignment) return;
    setConfirmOpen(true);
  }

  /* ── Success screen after submit assignment ─────────────────────────── */
  if (submitted) {
    return (
      <main className="dashboard-main vp-main vrd-page ead-exec-doc">
        <div className="vp-shell">
          <nav className="vrd-breadcrumb-bar" aria-label="Breadcrumb">
            <button type="button" className="vrd-crumb-back" onClick={onBack}>
              <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5">
                <path d="M15 18l-6-6 6-6" strokeLinecap="round" strokeLinejoin="round" />
              </svg>
              Back to assessment
            </button>
            <span className="vrd-crumb-sep">/</span>
            <span className="vrd-crumb-cur">Risk Assignment Document</span>
          </nav>

          <div className="ead-exec-doc-success">
            <div className="ead-exec-doc-success-icon" aria-hidden>
              <svg width="36" height="36" viewBox="0 0 24 24" fill="none" stroke="#ffffff" strokeWidth="2.5">
                <path d="M20 6L9 17l-5-5" strokeLinecap="round" strokeLinejoin="round" />
              </svg>
            </div>
            <h2 className="ead-exec-doc-success-title">Assignment submitted successfully</h2>
            <p className="ead-exec-doc-success-sub">
              The assessment status has been changed to <strong>Verification Needed</strong>.
              The assigned verifier has been notified and will review your observations.
            </p>
            <div className="ead-exec-doc-success-meta">
              <span>{fmt(assessment?.video_title)}</span>
              <span className="ead-exec-doc-success-sep">·</span>
              <span>{fmt(assessment?.location_name)}</span>
              <span className="ead-exec-doc-success-sep">·</span>
              <span>{snaps.length} observation{snaps.length !== 1 ? 's' : ''} on record</span>
            </div>
            <button type="button" className="ead-exec-doc-success-back" onClick={onBack}>
              Back to assessment
            </button>
          </div>
        </div>
      </main>
    );
  }

  /* ── Inline confirm overlay ──────────────────────────────────────────── */
  const ConfirmSubmit = confirmOpen ? (
    <div className="ead-exec-doc-overlay" role="dialog" aria-modal aria-label="Confirm submit assignment">
      <div className="ead-exec-doc-confirm">
        <div className="ead-exec-doc-confirm-icon" aria-hidden>
          <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#ffffff" strokeWidth="2.2">
            <path d="M12 9v4M12 17h.01" strokeLinecap="round" />
            <path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z" />
          </svg>
        </div>
        <h3 className="ead-exec-doc-confirm-title">Submit Assignment?</h3>
        <p className="ead-exec-doc-confirm-body">
          This will change the assessment status to <strong>Verification Needed</strong> and hand it
          over to the assigned verifier. You can continue working once the verifier returns it to you.
        </p>
        <div className="ead-exec-doc-confirm-btns">
          <button
            type="button"
            className="ead-exec-doc-confirm-cancel"
            onClick={() => setConfirmOpen(false)}
            disabled={submitting}
          >
            Cancel
          </button>
          <button
            type="button"
            className="ead-exec-doc-confirm-ok"
            onClick={handleSubmitAssignment}
            disabled={submitting}
          >
            {submitting ? (
              <>
                <span className="vrd-mini-spin" />
                Submitting…
              </>
            ) : (
              'Yes, submit assignment'
            )}
          </button>
        </div>
      </div>
    </div>
  ) : null;

  /* ── Main document view ──────────────────────────────────────────────── */
  return (
    <main className="dashboard-main vp-main vrd-page ead-exec-doc">
      {ConfirmSubmit}

      <div className="vp-shell">
        <nav className="vrd-breadcrumb-bar" aria-label="Breadcrumb">
          <button type="button" className="vrd-crumb-back" onClick={onBack}>
            <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5">
              <path d="M15 18l-6-6 6-6" strokeLinecap="round" strokeLinejoin="round" />
            </svg>
            Back to assessment
          </button>
          <span className="vrd-crumb-sep">/</span>
          <span className="vrd-crumb-cur">Risk Assignment Document</span>
        </nav>

        {isReturnByVerifier(resolvedAssessment) && getVerifierReturnRemarks(resolvedAssessment) ? (
          <div className="ead-exec-doc-verifier-note" role="region" aria-label="Verifier return note">
            <strong>Note from verifier</strong>
            <p>{getVerifierReturnRemarks(resolvedAssessment)}</p>
          </div>
        ) : null}

        <header className="vp-hero">
          <div className="vp-hero-text">
            <p className="vp-eyebrow">Executor · Assignment review</p>
            <h1 className="vp-title">Risk Assignment Document</h1>
            <p className="vp-lede">
              {fmt(assessment?.video_title)} · {fmt(assessment?.location_name)}
            </p>
          </div>
          <div className="vp-hero-aside ead-exec-doc-hero-aside">
            <span className="ead-exec-doc-status-pill" title="Workflow status">
              {statusLabel}
            </span>
            {canMutate && (
              <button
                type="button"
                className="ead-exec-doc-add-more"
                onClick={onBack}
              >
                Add more observations
              </button>
            )}
            <button
              type="button"
              className="vrd-btn-hero-primary ead-exec-doc-submit-v"
              onClick={openSubmitConfirm}
              disabled={loading || submitting || !canSubmitAssignment}
              title={submitDisabledReason}
            >
              {submitting ? (
                <>
                  <span className="vrd-mini-spin" />
                  Submitting…
                </>
              ) : (
                <>
                  <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" aria-hidden style={{ marginRight: '0.4rem' }}>
                    <path d="M22 2L11 13M22 2l-7 20-4-9-9-4 20-7z" strokeLinecap="round" strokeLinejoin="round" />
                  </svg>
                  Submit Assignment
                </>
              )}
            </button>
          </div>
        </header>

        <div className="vrd-meta-strip">
          {[
            ['Location', assessment?.location_name],
            ['Section / Work Area', assessment?.department_name],
            ['Contract Details', assessment?.contract_details ?? assessment?.contact_details],
            ['Capture Date', fmtDate(assessment?.video_capture_date)]
          ].flatMap(([label, val], i) => [
            i > 0 ? <div key={`sep-${i}-${label}`} className="vrd-meta-sep" aria-hidden /> : null,
            <div key={`${i}-${label}`} className="vrd-meta-item">
              <span className="vrd-meta-lbl">{label}</span>
              <span className="vrd-meta-val">{fmt(val)}</span>
            </div>
          ])}
        </div>

        {!canMutate && (
          <p className="ead-exec-doc-readonly-hint">
            {statusId === 5 ? (
              <>
                This assessment is already with the verifier for review. Observations are shown for reference only.
              </>
            ) : (
              <>
                <strong>Submit Assignment</strong> is only available when the status is <strong>In progress</strong> or{' '}
                <strong>Returned</strong> from the verifier. Current status: <strong>{statusLabel}</strong>.
              </>
            )}
          </p>
        )}

        {canMutate && snaps.length > 0 && (
          <p className="ead-exec-doc-guide-hint">
            Review your observations below. Delete any that need to be re-captured, use{' '}
            <strong>Add more observations</strong> to return to the field video and capture more snaps, then click{' '}
            <strong>Submit Assignment</strong> when you are ready to send this assessment to your verifier.
          </p>
        )}

        {error && (
          <div className="vp-error vrd-err-bar">
            {error}{' '}
            <button type="button" className="vrd-retry" onClick={load}>
              Retry
            </button>
          </div>
        )}

        <div className="vp-table-wrapper vrd-tbl-wrap">
          {loading ? (
            <div className="vp-loading vrd-loader">
              <div className="vp-spinner" />
              <span>Loading risk observations…</span>
            </div>
          ) : (
            <ExecDynamicSnapTable
              snaps={snaps}
              formSchema={formSchema}
              canMutate={canMutate}
              deletingId={deletingId}
              handleDelete={handleDelete}
            />
          )}
        </div>

        {/* Footer: count + submit button repeated for convenience */}
        {!loading && (
          <div className="vp-footer vrd-foot ead-exec-doc-foot">
            <span className="vp-footer-meta vrd-foot-meta">
              {snaps.length} observation{snaps.length !== 1 ? 's' : ''} saved in the database
            </span>
            <button
              type="button"
              className="ead-exec-doc-submit-footer"
              onClick={openSubmitConfirm}
              disabled={loading || submitting || !canSubmitAssignment}
              title={submitDisabledReason}
            >
              {submitting ? 'Submitting…' : 'Submit Assignment'}
            </button>
          </div>
        )}
      </div>
    </main>
  );
}
