import { useEffect, useRef, useState, useMemo, useCallback } from 'react';
import {
  assignAssessmentForm,
  fetchAssessmentListProjection,
  fetchOracFormDetailsList,
  fetchOracLocationFormsDetailsByLocationId,
  fetchParticipants
} from '../../api.js';
import { API_BASE_URL } from '../../apiConfig.js';
import {
  clearPendingSnap,
  getPendingSnapForAssessment
} from './executorSnapObservationCache.js';
import { submitPendingSnapObservationsToDatabase } from './executorPendingSnapSubmit.js';
import {
  getAssignmentStatusDisplayLabel,
  getVerifierReturnRemarks,
  isReturnByVerifier
} from './executorAssignmentCategories.js';
import SnapMarkEditorModal from './SnapMarkEditorModal.jsx';
import './ExecutorAssessmentDetail.css';

/* ── helpers ── */
function fmt(val) { return val || '—'; }
function fmtDate(val) {
  if (!val) return '—';
  try { return new Date(val).toLocaleDateString('en-IN', { day: '2-digit', month: 'short', year: 'numeric' }); }
  catch { return val; }
}
function fmtTime(secs) {
  const m = String(Math.floor(secs / 60)).padStart(2, '0');
  const s = String(Math.floor(secs % 60)).padStart(2, '0');
  return `${m}:${s}`;
}
function videoSrc(assessment) {
  const raw = assessment?.video;
  if (!raw) return null;
  // Already a full URL or data URL
  if (typeof raw === 'string' && (raw.startsWith('http') || raw.startsWith('data:'))) return raw;
  // File path from server (e.g. "uploads\video.mp4") — build full URL
  if (typeof raw === 'string' && raw.length > 0) {
    return `${API_BASE_URL}/${raw.replace(/\\/g, '/')}`;
  }
  return null;
}

const EMPTY_PARTICIPANT_ROWS = [];

/** Prefer `participants_json` from assessment list / projection (same data as GET orac_participants). */
function participantsFromAssessment(assessment) {
  const raw = assessment?.participants_json;
  if (raw == null) return EMPTY_PARTICIPANT_ROWS;
  if (Array.isArray(raw)) return raw.length ? raw : EMPTY_PARTICIPANT_ROWS;
  if (typeof raw === 'string') {
    try {
      const p = JSON.parse(raw);
      return Array.isArray(p) && p.length ? p : EMPTY_PARTICIPANT_ROWS;
    } catch {
      return EMPTY_PARTICIPANT_ROWS;
    }
  }
  return EMPTY_PARTICIPANT_ROWS;
}


/* ── Icons ── */
const IC = (d, extra = '') => () => (
  <svg viewBox="0 0 20 20" fill="none" stroke="currentColor" strokeWidth="1.6" aria-hidden>
    <path d={d} strokeLinecap="round" strokeLinejoin="round" />
    {extra && <path d={extra} strokeLinecap="round" strokeLinejoin="round" />}
  </svg>
);
const IconLocation  = IC('M10 18s-7-6.686-7-10.5a7 7 0 1 1 14 0C17 11.314 10 18 10 18Z');
const IconCalendar  = IC('M6 2v4M14 2v4M2.5 9h15', 'M4 5h12a1.5 1.5 0 0 1 1.5 1.5v10A1.5 1.5 0 0 1 16 18H4a1.5 1.5 0 0 1-1.5-1.5v-10A1.5 1.5 0 0 1 4 5Z');
const IconClock     = IC('M10 6v4.5l3 2');
const IconUser      = IC('M3 17a7 7 0 0 1 14 0', 'M10 3.5a3.5 3.5 0 1 1 0 7 3.5 3.5 0 0 1 0-7Z');
const IconBuilding  = IC('M7 17V9h6v8M2 8h16', 'M3 5h14a1 1 0 0 1 1 1v11H2V6a1 1 0 0 1 1-1Z');
const IconClipboard = IC('M7 3h6a1 1 0 0 1 1 1v1H6V4a1 1 0 0 1 1-1Z', 'M4.5 5h11a1.5 1.5 0 0 1 1.5 1.5v10A1.5 1.5 0 0 1 15.5 18h-11A1.5 1.5 0 0 1 3 16.5v-10A1.5 1.5 0 0 1 4.5 5Z');
const IconTag       = IC('M3 10.5V4.5a1 1 0 0 1 1-1h6l6.5 6.5-7 7L3 10.5Z');
const IconBack      = () => (
  <svg viewBox="0 0 20 20" fill="none" stroke="currentColor" strokeWidth="2" aria-hidden>
    <path d="M13 4L7 10l6 6" strokeLinecap="round" strokeLinejoin="round" />
  </svg>
);
const IconCamera    = () => (
  <svg viewBox="0 0 20 20" fill="none" stroke="currentColor" strokeWidth="1.7" aria-hidden>
    <path d="M2 6.5A1.5 1.5 0 0 1 3.5 5h1.382a1.5 1.5 0 0 0 1.342-.83L7 3h6l.776 1.17A1.5 1.5 0 0 0 15.118 5H16.5A1.5 1.5 0 0 1 18 6.5v9A1.5 1.5 0 0 1 16.5 17h-13A1.5 1.5 0 0 1 2 15.5v-9Z" strokeLinejoin="round" />
    <circle cx="10" cy="11" r="3" />
  </svg>
);
/* ── Info row ── */
function InfoRow({ icon, label, value, highlight }) {
  return (
    <div className="eadp-info-row">
      <span className="eadp-info-icon">{icon}</span>
      <span className="eadp-info-label">{label}</span>
      <span className={`eadp-info-value${highlight ? ' eadp-info-value--highlight' : ''}`}>{value || '—'}</span>
    </div>
  );
}

/* ══════════════════════════════════════
   Main component
══════════════════════════════════════ */
export default function ExecutorAssessmentDetail({
  assessment,
  onBack,
  onOpenSnapRiskForm,
  onAssessmentUpdated,
  onOpenAssignmentDocument,
  /** Seconds to seek the video after returning from the snap form (executor workflow). */
  snapResumeSeekSeconds = null,
  onSnapResumeSeekConsumed,
  /** Short-lived success/info line after observations are saved (parent clears via onDetailNoticeConsumed). */
  detailNotice = null,
  onDetailNoticeConsumed
}) {
  const videoRef = useRef(null);
  const [participants, setParticipants] = useState([]);
  const [loadingPart, setLoadingPart] = useState(true);
  const [snapOpen, setSnapOpen] = useState(false);
  const [snapDataUrl, setSnapDataUrl] = useState(null);
  const [violationTime, setViolationTime] = useState('00:00');

  const [pendingSnapPayload, setPendingSnapPayload] = useState(null);
  const [snapSubmitBusy, setSnapSubmitBusy] = useState(false);
  const [snapSubmitError, setSnapSubmitError] = useState('');

  const [formOptions, setFormOptions] = useState([]);
  const [formOptionsLoading, setFormOptionsLoading] = useState(true);
  const [selectedFormId, setSelectedFormId] = useState('');
  const [formAssignBusy, setFormAssignBusy] = useState(false);
  const [formAssignError, setFormAssignError] = useState('');
  const [formAssignOk, setFormAssignOk] = useState('');
  /** Shown after retry-from-banner succeeds (parent `detailNotice` is for snap-flow saves). */
  const [localDetailNotice, setLocalDetailNotice] = useState(null);

  const explicitForm = useMemo(() => {
    const v = assessment?.form_id;
    if (v == null || v === '') return false;
    const n = Number(v);
    return Number.isInteger(n) && n > 0;
  }, [assessment?.form_id]);

  const refreshPendingSnap = useCallback(() => {
    if (!assessment?.assessment_id) {
      setPendingSnapPayload(null);
      return;
    }
    setPendingSnapPayload(getPendingSnapForAssessment(assessment.assessment_id));
  }, [assessment?.assessment_id]);

  /* Load participants — always set loading when fetching; ignore stale async results */
  const assessmentIdForParticipants =
    assessment?.assessment_id != null && assessment?.assessment_id !== ''
      ? String(assessment.assessment_id)
      : null;

  const embeddedParticipantsKey = useMemo(
    () => JSON.stringify(assessment?.participants_json ?? null),
    [assessment?.participants_json]
  );

  const embeddedParticipants = useMemo(
    () => participantsFromAssessment(assessment),
    [embeddedParticipantsKey, assessmentIdForParticipants]
  );

  useEffect(() => {
    if (!assessmentIdForParticipants) {
      setParticipants([]);
      setLoadingPart(false);
      return undefined;
    }

    const embedded = embeddedParticipants;
    if (embedded.length > 0) {
      setParticipants(embedded);
      setLoadingPart(false);
    } else {
      setLoadingPart(true);
      setParticipants([]);
    }

    let cancelled = false;
    fetchParticipants(assessmentIdForParticipants)
      .then((rows) => {
        if (!cancelled) setParticipants(Array.isArray(rows) ? rows : []);
      })
      .catch(() => {
        if (!cancelled && embedded.length === 0) setParticipants([]);
      })
      .finally(() => {
        if (!cancelled) setLoadingPart(false);
      });

    return () => {
      cancelled = true;
    };
  }, [assessmentIdForParticipants, embeddedParticipants]);

  useEffect(() => {
    const v = assessment?.form_id;
    if (v != null && v !== '') {
      setSelectedFormId(String(v));
    } else {
      setSelectedFormId('');
    }
  }, [assessment?.assessment_id, assessment?.form_id]);

  useEffect(() => {
    let cancelled = false;
    (async () => {
      setFormOptionsLoading(true);
      try {
        const allForms = await fetchOracFormDetailsList({ leaf_only: true, with_version: true });
        let options = allForms.map((f) => ({
          value: f.form_id,
          label: `${f.title || 'Untitled'}${f.version != null ? ` (v${f.version})` : ''}`
        }));
        const locId = assessment?.location_id;
        if (locId != null && locId !== '') {
          const links = await fetchOracLocationFormsDetailsByLocationId(locId);
          const allowed = new Set(links.map((l) => Number(l.form_id)));
          if (allowed.size > 0) {
            options = options.filter((o) => allowed.has(Number(o.value)));
          }
        }
        if (!cancelled) setFormOptions(options);
      } catch {
        if (!cancelled) setFormOptions([]);
      } finally {
        if (!cancelled) setFormOptionsLoading(false);
      }
    })();
    return () => {
      cancelled = true;
    };
  }, [assessment?.assessment_id, assessment?.location_id]);

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

  useEffect(() => {
    if (snapResumeSeekSeconds == null || Number.isNaN(Number(snapResumeSeekSeconds))) {
      return;
    }
    const v = videoRef.current;
    const t = Number(snapResumeSeekSeconds);
    if (v && t >= 0 && Number.isFinite(t)) {
      try {
        v.currentTime = t;
      } catch {
        /* ignore */
      }
    }
    onSnapResumeSeekConsumed?.();
  }, [snapResumeSeekSeconds, assessment?.assessment_id, onSnapResumeSeekConsumed]);

  useEffect(() => {
    if (!detailNotice || !onDetailNoticeConsumed) return undefined;
    const id = window.setTimeout(() => onDetailNoticeConsumed(), 6000);
    return () => clearTimeout(id);
  }, [detailNotice, onDetailNoticeConsumed]);

  useEffect(() => {
    if (!localDetailNotice) return undefined;
    const id = window.setTimeout(() => setLocalDetailNotice(null), 6000);
    return () => clearTimeout(id);
  }, [localDetailNotice]);

  async function handleSaveOracForm(e) {
    e?.preventDefault?.();
    if (!selectedFormId || !assessment?.assessment_id) return;
    setFormAssignBusy(true);
    setFormAssignError('');
    setFormAssignOk('');
    try {
      await assignAssessmentForm(assessment.assessment_id, Number(selectedFormId));
      const row = await fetchAssessmentListProjection(assessment.assessment_id);
      if (row && typeof onAssessmentUpdated === 'function') {
        onAssessmentUpdated({ ...assessment, ...row });
      }
      setFormAssignOk('Form saved.');
    } catch (err) {
      setFormAssignError(err.message || 'Could not save form.');
    } finally {
      setFormAssignBusy(false);
    }
  }

  async function handleSubmitCachedObservations() {
    const p = getPendingSnapForAssessment(assessment.assessment_id);
    if (!p) return;
    const n = p.observations?.length ?? 0;
    if (
      !window.confirm(
        `Retry saving ${n} cached observation${n !== 1 ? 's' : ''} to the database?`
      )
    ) {
      return;
    }
    setSnapSubmitBusy(true);
    setSnapSubmitError('');
    try {
      const r = await submitPendingSnapObservationsToDatabase(p);
      refreshPendingSnap();
      const cnt = r?.observationCount ?? n;
      setLocalDetailNotice(
        `Saved ${cnt} cached observation${cnt !== 1 ? 's' : ''} to the database.`
      );
      try {
        const row = await fetchAssessmentListProjection(assessment.assessment_id);
        if (row && typeof onAssessmentUpdated === 'function') {
          onAssessmentUpdated({ ...assessment, ...row });
        }
      } catch {
        /* optional */
      }
    } catch (e) {
      setSnapSubmitError(e.message || 'Submit failed.');
    } finally {
      setSnapSubmitBusy(false);
    }
  }

  function handleDiscardCachedObservations() {
    if (!window.confirm('Discard all cached observations for this snap?')) return;
    clearPendingSnap();
    refreshPendingSnap();
  }

  /* Snap Photo handler — capture current video frame */
  function handleSnapPhoto() {
    const video = videoRef.current;
    if (!video) return;
    video.pause();
    setViolationTime(fmtTime(video.currentTime));

    // Try to capture the current frame.
    // If the video is cross-origin and the server doesn't send CORS headers,
    // toDataURL() throws a SecurityError — we still open the modal (canvas will be blank).
    try {
      const canvas = document.createElement('canvas');
      canvas.width  = video.videoWidth  || 1280;
      canvas.height = video.videoHeight || 720;
      canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);
      setSnapDataUrl(canvas.toDataURL('image/jpeg', 0.92));
    } catch {
      // CORS tainted — open modal without frame preview
      setSnapDataUrl(null);
    }
    setSnapOpen(true);
  }

  function handleExecuteVideo() {
    const video = videoRef.current;
    if (!video) return;
    video.play().catch(() => {});
  }

  if (!assessment) {
    return (
      <main className="dashboard-main eadp-shell">
        <p className="eadp-empty">No assessment selected.</p>
      </main>
    );
  }

  const src = videoSrc(assessment);
  const [p1 = null, p2 = null, p3 = null] = participants;

  return (
    <main className="dashboard-main eadp-shell">

      {(detailNotice || localDetailNotice) && (
        <div className="eadp-detail-notice eadp-detail-notice--success" role="status">
          {detailNotice || localDetailNotice}
        </div>
      )}

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

      {pendingSnapPayload && (
        <div className="eadp-pending-snap-banner" role="region" aria-label="Pending snap observations">
          <div className="eadp-pending-snap-banner__text">
            <strong>
              {pendingSnapPayload.observations?.length ?? 0} observation
              {(pendingSnapPayload.observations?.length ?? 0) !== 1 ? 's' : ''}
            </strong>{' '}
            were not saved to the database (a previous submit may have failed). Retry saving now, or discard.
          </div>
          <div className="eadp-pending-snap-banner__actions">
            <button
              type="button"
              className="eadp-btn eadp-btn--primary"
              onClick={handleSubmitCachedObservations}
              disabled={snapSubmitBusy}
            >
              {snapSubmitBusy ? 'Retrying…' : 'Retry saving to database'}
            </button>
            <button
              type="button"
              className="eadp-btn eadp-btn--outline"
              onClick={handleDiscardCachedObservations}
              disabled={snapSubmitBusy}
            >
              Discard
            </button>
          </div>
          {snapSubmitError && <p className="eadp-pending-snap-banner__err">{snapSubmitError}</p>}
        </div>
      )}

      {/* ── Top bar + ORAC form (form row directly under toolbar) ── */}
      <div className="eadp-topbar eadp-topbar--with-orac">
        <div className="eadp-topbar-main-row">
          <button type="button" className="eadp-back-btn" onClick={onBack}>
            <IconBack /> Back
          </button>
          <div className="eadp-topbar-center">
            <h1 className="eadp-title">{fmt(assessment.video_title)}</h1>
            <span className="eadp-status-pill eadp-status-pill--pending" title="Workflow status">
              {getAssignmentStatusDisplayLabel(assessment, { forVerifier: false })}
            </span>
          </div>
          <div className="eadp-topbar-actions">
            <button
              type="button"
              className="eadp-btn eadp-btn--outline"
              onClick={() => onOpenAssignmentDocument?.()}
            >
              View Assignment Document
            </button>
            <button
              type="button"
              className="eadp-btn eadp-btn--primary"
              onClick={handleSnapPhoto}
              disabled={!src || !explicitForm}
              title={
                !explicitForm
                  ? 'Select and save an ORAC form in the section below first'
                  : !src
                    ? 'No video loaded'
                    : 'Capture current frame'
              }
            >
              <IconCamera /> Snap Photo
            </button>
          </div>
        </div>

        <section className="eadp-orac-form-strip" aria-label="ORAC form for this assessment">
          <div className="eadp-orac-form-strip__header">
            <span className="eadp-orac-form-strip__title">ORAC form for this assessment</span>
            {!explicitForm ? (
              <span className="eadp-orac-form-strip__badge">Required before snaps</span>
            ) : (
              <span className="eadp-orac-form-strip__badge eadp-orac-form-strip__badge--ok">Saved</span>
            )}
          </div>
          {formOptionsLoading ? (
            <p className="eadp-loading-text eadp-orac-form-strip__loading">Loading forms…</p>
          ) : (
            <form className="eadp-form-assign-row eadp-form-assign-row--strip" onSubmit={handleSaveOracForm}>
              <select
                className="eadp-form-select"
                value={selectedFormId}
                onChange={(e) => setSelectedFormId(e.target.value)}
                aria-label="ORAC form"
              >
                <option value="">Select a form…</option>
                {formOptions.map((o) => (
                  <option key={o.value} value={o.value}>
                    {o.label}
                  </option>
                ))}
              </select>
              <button
                type="submit"
                className="eadp-btn eadp-btn--primary"
                disabled={formAssignBusy || !selectedFormId}
              >
                {formAssignBusy ? 'Saving…' : 'Save form'}
              </button>
            </form>
          )}
          {!formOptions.length && !formOptionsLoading ? (
            <p className="eadp-form-assign-hint eadp-form-assign-hint--strip">
              No forms are listed for this location. Ask an admin to link forms to the location in ORAC, or create
              forms.
            </p>
          ) : null}
          {formAssignError ? (
            <p className="eadp-pending-snap-banner__err eadp-orac-form-strip__msg">{formAssignError}</p>
          ) : null}
          {formAssignOk ? <p className="eadp-form-assign-ok eadp-orac-form-strip__msg">{formAssignOk}</p> : null}
          {!explicitForm ? (
            <p className="eadp-form-assign-hint eadp-form-assign-hint--strip">
              Choose and save a form before capturing snaps. The risk questionnaire uses this form.
            </p>
          ) : null}
        </section>
      </div>

      {/* ── Body ── */}
      <div className="eadp-body">

        {/* Left — video */}
        <div className="eadp-video-col">
          <div className="eadp-video-card">
            <p className="eadp-card-label">Field Video</p>
            {src ? (
              <>
                <video ref={videoRef} className="eadp-video" controls crossOrigin="anonymous">
                  <source src={src} />
                  Your browser does not support the video tag.
                </video>
                <div className="eadp-video-actions">
                  <button
                    type="button"
                    className="eadp-btn eadp-btn--primary"
                    onClick={handleExecuteVideo}
                  >
                    Assess Video
                  </button>
                </div>
              </>
            ) : (
              <div className="eadp-video-placeholder">
                <svg viewBox="0 0 48 48" fill="none" stroke="currentColor" strokeWidth="1.5" aria-hidden>
                  <rect x="4" y="10" width="40" height="28" rx="4" />
                  <polygon points="20,17 34,24 20,31" fill="currentColor" stroke="none" opacity="0.4" />
                </svg>
                <span>No video attached</span>
              </div>
            )}
          </div>
        </div>

        {/* Right — details, participants at bottom */}
        <div className="eadp-details-col">
          <div className="eadp-card">
            <p className="eadp-card-label">Site Information</p>
            <div className="eadp-info-list">
              <InfoRow icon={<IconLocation />}  label="Location"           value={assessment.location_name} />
              <InfoRow icon={<IconBuilding />}  label="Section / Work Area" value={assessment.department_name} />
              <InfoRow icon={<IconTag />}       label="Contract Details"   value={assessment.contract_details ?? assessment.contact_details} />
            </div>
          </div>
          <div className="eadp-card">
            <p className="eadp-card-label">Capture Details</p>
            <div className="eadp-info-list">
              <InfoRow icon={<IconCalendar />}  label="Capture Date"  value={fmtDate(assessment.video_capture_date)} />
              <InfoRow icon={<IconClock />}     label="Capture Time"  value={fmt(assessment.video_capture_time)} />
              <InfoRow icon={<IconClipboard />} label="Remark"        value={fmt(assessment.remarks)} />
              <InfoRow icon={<IconUser />}      label="Uploaded By"   value={fmt(assessment.uploaded_by_name || assessment.uploader_user_id)} />
            </div>
          </div>
          <div className="eadp-card">
            <p className="eadp-card-label">Assignment</p>
            <div className="eadp-info-list">
              <InfoRow icon={<IconUser />} label="Executor" value={assessment.executor_name || assessment.executor_id} highlight />
              <InfoRow icon={<IconUser />} label="Verifier" value={assessment.verifier_name || assessment.verifier_id} highlight />
            </div>
          </div>
          <div className="eadp-card">
            <p className="eadp-card-label">Participants</p>
            {loadingPart ? (
              <p className="eadp-loading-text">Loading…</p>
            ) : (
              <div className="eadp-participants">
                {[p1, p2, p3].map((p, i) => (
                  <div className="eadp-participant-row" key={i}>
                    <span className="eadp-participant-number">P{i + 1}</span>
                    <span className="eadp-participant-name">
                      {p
                        ? fmt(
                            (p.participants_name && String(p.participants_name).trim()) ||
                              (p.participant_name && String(p.participant_name).trim()) ||
                              p.participant_user_id
                          )
                        : '—'}
                    </span>
                  </div>
                ))}
              </div>
            )}
          </div>
        </div>
      </div>

      {/* ── Snap Modal ── */}
      {snapOpen && (
        <SnapMarkEditorModal
          snapDataUrl={snapDataUrl}
          violationTime={violationTime}
          onTimeChange={setViolationTime}
          onClose={() => setSnapOpen(false)}
          onApply={(markedDataUrl, marksJson, baseFrameDataUrl) => {
            setSnapOpen(false);
            const video = videoRef.current;
            const resumeVideoSeconds =
              video && Number.isFinite(video.currentTime) ? video.currentTime : null;
            onOpenSnapRiskForm?.({
              assessment,
              markedImageDataUrl: markedDataUrl,
              marksJson,
              baseFrameDataUrl: baseFrameDataUrl ?? snapDataUrl,
              violationTime,
              resumeVideoSeconds
            });
          }}
        />
      )}
    </main>
  );
}
