import { useCallback, useEffect, useMemo, useState } from 'react';
import { fetchAssessmentsForExecutor, fetchAssessmentStatuses } from '../../api.js';
import ExecutorAssessmentDetail from './ExecutorAssessmentDetail.jsx';
import ExecutorAssignmentDocument from './ExecutorAssignmentDocument.jsx';
import SnapDetailCreatePage from './SnapDetailCreatePage.jsx';
import {
  buildCategoryMapsFromStatuses,
  categorizeAssignmentRow,
  categorizeExecutorRow,
  countByCategory,
  getAssignmentStatusDisplayLabel,
  getVerifierReturnRemarks
} from './executorAssignmentCategories.js';
import QueueStatusSummaryBar from './QueueStatusSummaryBar.jsx';
import './VerifierPage.css';

/** Prefer human-readable capture; avoid concatenating a formatted date with a raw ISO timestamp. */
function formatCaptureWhen(v) {
  const rawDate = v?.video_capture_date;
  const rawTime = v?.video_capture_time;
  if (!rawDate && (rawTime == null || rawTime === '')) return '—';
  if (rawTime != null && rawTime !== '') {
    const s = String(rawTime);
    if (s.includes('T') || s.endsWith('Z')) {
      try {
        const dt = new Date(s);
        if (!Number.isNaN(dt.getTime())) {
          return dt.toLocaleString('en-IN', {
            day: '2-digit',
            month: 'short',
            year: 'numeric',
            hour: '2-digit',
            minute: '2-digit',
            hour12: true
          });
        }
      } catch {
        /* fall through */
      }
    }
  }
  if (rawDate) {
    try {
      const dt = new Date(rawDate);
      if (!Number.isNaN(dt.getTime())) {
        const datePart = dt.toLocaleDateString('en-IN', {
          day: '2-digit',
          month: 'short',
          year: 'numeric'
        });
        if (rawTime != null && rawTime !== '') {
          const t = String(rawTime);
          if (!t.includes('T') && !t.endsWith('Z')) {
            return `${datePart} · ${t}`;
          }
        }
        return datePart;
      }
    } catch {
      /* fall through */
    }
  }
  return '—';
}

function PersonCell({ name, id }) {
  const n = name && String(name).trim();
  const idStr = id != null && id !== '' ? String(id) : '';
  const showName = n && n !== idStr;
  if (showName) {
    return (
      <div className="vp-person">
        <span className="vp-person-name">{n}</span>
        {idStr ? <span className="vp-person-id">#{idStr}</span> : null}
      </div>
    );
  }
  if (idStr) {
    return (
      <span className="vp-person-id vp-person-id--solo" title="User id">
        #{idStr}
      </span>
    );
  }
  return <span className="vp-muted">—</span>;
}

const VIEW_STORAGE_KEY = 'executorQueueView';

function readStoredView() {
  try {
    const s = localStorage.getItem(VIEW_STORAGE_KEY);
    if (s === 'card' || s === 'list') return s;
  } catch {
    /* ignore */
  }
  return 'list';
}

function ExecutorVideoPage({ onNavigateToReview, onNavigateExecutorDashboard }) {
  const [videos, setVideos] = useState([]);
  const [statusList, setStatusList] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState('');
  const [search, setSearch] = useState('');
  const [entriesPerPage, setEntriesPerPage] = useState(10);
  const [currentPage, setCurrentPage] = useState(1);
  const [selectedAssessment, setSelectedAssessment] = useState(null);
  const [assignmentDocOpen, setAssignmentDocOpen] = useState(false);
  const [snapRiskDraft, setSnapRiskDraft] = useState(null);
  const [snapResumeSeek, setSnapResumeSeek] = useState(null);
  const [assessmentDetailNotice, setAssessmentDetailNotice] = useState(null);
  const [viewMode, setViewMode] = useState(readStoredView);

  useEffect(() => {
    setAssignmentDocOpen(false);
  }, [selectedAssessment?.assessment_id]);

  useEffect(() => {
    try {
      localStorage.setItem(VIEW_STORAGE_KEY, viewMode);
    } catch {
      /* ignore */
    }
  }, [viewMode]);

  const load = useCallback(() => {
    setLoading(true);
    setError('');
    Promise.all([fetchAssessmentsForExecutor(), fetchAssessmentStatuses()])
      .then(([vids, statuses]) => {
        setVideos(Array.isArray(vids) ? vids : []);
        setStatusList(Array.isArray(statuses) ? statuses : []);
      })
      .catch((e) => setError(e.message))
      .finally(() => setLoading(false));
  }, []);

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

  const { executorMap } = buildCategoryMapsFromStatuses(statusList);

  const queueCounts = useMemo(
    () => countByCategory(videos, categorizeExecutorRow, executorMap),
    [videos, executorMap]
  );

  const categorizeRow = useCallback(
    (v) => categorizeAssignmentRow(v, { roleView: 'executor', executorMap }),
    [executorMap]
  );

  function pillClass(v) {
    const cat = categorizeRow(v);
    if (cat === 'done') return 'vp-pill vp-pill--success';
    if (cat === 'in_process') return 'vp-pill vp-pill--info';
    if (cat === 'not_started') return 'vp-pill vp-pill--warning';
    if (cat === 'verification_required') return 'vp-pill vp-pill--verification';
    if (cat === 'returned') return 'vp-pill vp-pill--return';
    return 'vp-pill vp-pill--neutral';
  }

  function formatDate(val) {
    if (!val) return '--';
    try {
      const d = new Date(val);
      return d.toLocaleDateString('en-IN', { day: '2-digit', month: 'short', year: 'numeric' });
    } catch {
      return val;
    }
  }

  const filtered = videos.filter((v) => {
    if (!search) return true;
    const q = search.toLowerCase();
    return (
      (v.video_title || '').toLowerCase().includes(q) ||
      (v.location_name || '').toLowerCase().includes(q) ||
      (v.department_name || '').toLowerCase().includes(q) ||
      ((v.contract_details ?? v.contact_details) || '').toLowerCase().includes(q) ||
      (v.uploaded_by_name || '').toLowerCase().includes(q) ||
      (getVerifierReturnRemarks(v) || '').toLowerCase().includes(q)
    );
  });

  const totalPages = Math.max(1, Math.ceil(filtered.length / entriesPerPage));
  const safePage = Math.min(currentPage, totalPages);
  const paginated = filtered.slice((safePage - 1) * entriesPerPage, safePage * entriesPerPage);

  function handleSearch(val) {
    setSearch(val);
    setCurrentPage(1);
  }

  function handleEntriesChange(val) {
    setEntriesPerPage(Number(val));
    setCurrentPage(1);
  }

  if (snapRiskDraft) {
    return (
      <SnapDetailCreatePage
        draft={snapRiskDraft}
        onObservationsSubmitted={({ observationCount, assessmentRow }) => {
          if (assessmentRow) {
            setSelectedAssessment((prev) => (prev ? { ...prev, ...assessmentRow } : prev));
          }
          setAssessmentDetailNotice(
            `Saved ${observationCount} observation${observationCount !== 1 ? 's' : ''} to the database. ` +
              'Open View Assignment Document when you are ready to review, remove observations, or submit the assignment to your verifier.'
          );
          load();
        }}
        onBack={(payload) => {
          if (payload != null && typeof payload === 'object' && payload.resumeVideoSeconds != null) {
            setSnapResumeSeek(Number(payload.resumeVideoSeconds));
          } else {
            setSnapResumeSeek(null);
          }
          setSnapRiskDraft(null);
          if (payload?.afterSubmit && payload?.assessment) {
            setSelectedAssessment(payload.assessment);
          }
        }}
      />
    );
  }

  if (selectedAssessment && assignmentDocOpen) {
    return (
      <ExecutorAssignmentDocument
        assessment={selectedAssessment}
        onBack={() => setAssignmentDocOpen(false)}
        onAssessmentUpdated={(row) => {
          if (row) setSelectedAssessment((prev) => (prev ? { ...prev, ...row } : row));
          load();
        }}
        onSubmittedToVerifier={() => {
          setAssignmentDocOpen(false);
          setSelectedAssessment(null);
          onNavigateExecutorDashboard?.();
        }}
      />
    );
  }

  if (selectedAssessment) {
    return (
      <ExecutorAssessmentDetail
        key={selectedAssessment.assessment_id}
        assessment={selectedAssessment}
        snapResumeSeekSeconds={snapResumeSeek}
        onSnapResumeSeekConsumed={() => setSnapResumeSeek(null)}
        detailNotice={assessmentDetailNotice}
        onDetailNoticeConsumed={() => setAssessmentDetailNotice(null)}
        onBack={() => {
          setSelectedAssessment(null);
          load();
        }}
        onOpenSnapRiskForm={(ctx) => setSnapRiskDraft(ctx)}
        onOpenAssignmentDocument={() => setAssignmentDocOpen(true)}
        onAssessmentUpdated={(row) => {
          setSelectedAssessment((prev) => (prev && row ? { ...prev, ...row } : row));
        }}
      />
    );
  }

  return (
    <main className="dashboard-main vp-main">
      <div className="vp-shell">
        <header className="vp-hero">
          <div className="vp-hero-text">
            <p className="vp-eyebrow">Executor queue</p>
            <h1 className="vp-title">Video details</h1>
            <p className="vp-lede">
              Open a row to work on the field video, capture snaps, and complete your assessment tasks.
            </p>
          </div>
          <div className="vp-hero-aside">
            <div className="vp-stat" aria-live="polite">
              <span className="vp-stat-value">{loading ? '…' : filtered.length}</span>
              <span className="vp-stat-label">{filtered.length === 1 ? 'Assessment' : 'Assessments'}</span>
            </div>
            {typeof onNavigateToReview === 'function' && (
              <button
                type="button"
                className="vp-btn-refresh vp-btn-review-queue"
                title="Open the review queue to verify assessments"
                onClick={onNavigateToReview}
              >
                Review
              </button>
            )}
            <button type="button" className="vp-btn-refresh" title="Refresh list" onClick={load}>
              <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
                <path d="M23 4v6h-6" />
                <path d="M1 20v-6h6" />
                <path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15" />
              </svg>
              Refresh
            </button>
          </div>
        </header>

        {!loading ? (
          <QueueStatusSummaryBar role="executor" counts={queueCounts} total={videos.length} />
        ) : null}

        <div className="vp-toolbar">
          <div className="vp-toolbar-cluster">
            <label className="vp-entries-label">
              <span className="vp-label-quiet">Rows per page</span>
              <select
                className="vp-entries-select"
                value={entriesPerPage}
                onChange={(e) => handleEntriesChange(e.target.value)}
              >
                {[10, 25, 50, 100].map((n) => (
                  <option key={n} value={n}>
                    {n}
                  </option>
                ))}
              </select>
            </label>
            <div className="vp-view-toggle" role="group" aria-label="Layout">
              <span className="vp-label-quiet vp-view-toggle-label">View</span>
              <div className="vp-view-toggle-inner">
                <button
                  type="button"
                  className={`vp-view-btn ${viewMode === 'list' ? 'vp-view-btn--active' : ''}`}
                  onClick={() => setViewMode('list')}
                  aria-pressed={viewMode === 'list'}
                  title="List view"
                >
                  <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" aria-hidden>
                    <path d="M8 6h13M8 12h13M8 18h13M3 6h.01M3 12h.01M3 18h.01" />
                  </svg>
                  <span className="vp-view-btn-text">List</span>
                </button>
                <button
                  type="button"
                  className={`vp-view-btn ${viewMode === 'card' ? 'vp-view-btn--active' : ''}`}
                  onClick={() => setViewMode('card')}
                  aria-pressed={viewMode === 'card'}
                  title="Card view"
                >
                  <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" aria-hidden>
                    <rect x="3" y="3" width="7" height="7" rx="1" />
                    <rect x="14" y="3" width="7" height="7" rx="1" />
                    <rect x="3" y="14" width="7" height="7" rx="1" />
                    <rect x="14" y="14" width="7" height="7" rx="1" />
                  </svg>
                  <span className="vp-view-btn-text">Cards</span>
                </button>
              </div>
            </div>
          </div>
          <div className="vp-search-wrap">
            <span className="vp-search-icon" aria-hidden>
              <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
                <circle cx="11" cy="11" r="7" />
                <path d="M21 21l-4.3-4.3" />
              </svg>
            </span>
            <input
              className="vp-search-input"
              type="search"
              value={search}
              onChange={(e) => handleSearch(e.target.value)}
              placeholder="Search location, title, contract…"
              aria-label="Search assessments"
            />
          </div>
        </div>

        {error && <div className="vp-error">{error}</div>}

        <div className={`vp-table-wrapper ${viewMode === 'card' ? 'vp-table-wrapper--cards' : ''}`}>
        {loading ? (
          <div className="vp-loading">
            <div className="vp-spinner" />
            <span>Loading assessments…</span>
          </div>
        ) : viewMode === 'list' ? (
          <table className="vp-table">
            <thead>
              <tr>
                <th className="vp-th vp-th--num">#</th>
                <th className="vp-th">Location</th>
                <th className="vp-th">Section / work area</th>
                <th className="vp-th">Contract</th>
                <th className="vp-th">Video title</th>
                <th className="vp-th vp-th--capture">Capture</th>
                <th className="vp-th">Uploaded by</th>
                <th className="vp-th">Upload date</th>
                <th className="vp-th">Status</th>
                <th className="vp-th" title="Note from verifier when this assessment was returned to you">
                  Verifier note
                </th>
                <th className="vp-th">Assigned</th>
                <th className="vp-th">Verifier</th>
                <th className="vp-th vp-th--action"> </th>
              </tr>
            </thead>
            <tbody>
              {paginated.length === 0 ? (
                <tr>
                  <td colSpan={13} className="vp-empty">
                    {videos.length === 0
                      ? 'No assessments are currently assigned to you as executor.'
                      : 'No assessments match your search.'}
                  </td>
                </tr>
              ) : (
                paginated.map((v, idx) => {
                  const canOpenExecutor = categorizeRow(v) !== 'verification_required';
                  const rowCat = categorizeRow(v);
                  const verifierNote =
                    rowCat === 'returned' && getVerifierReturnRemarks(v)
                      ? getVerifierReturnRemarks(v)
                      : null;
                  return (
                  <tr key={v.assessment_id} className="vp-row">
                    <td className="vp-td vp-td--num">{(safePage - 1) * entriesPerPage + idx + 1}</td>
                    <td className="vp-td">{v.location_name || <span className="vp-muted">—</span>}</td>
                    <td className="vp-td">{v.department_name || <span className="vp-muted">—</span>}</td>
                    <td className="vp-td vp-td--mono">{(v.contract_details ?? v.contact_details) || <span className="vp-muted">—</span>}</td>
                    <td className="vp-td vp-cell-title">{v.video_title || <span className="vp-muted">—</span>}</td>
                    <td className="vp-td vp-td--capture">{formatCaptureWhen(v)}</td>
                    <td className="vp-td">
                      <PersonCell name={v.uploaded_by_name} id={v.uploader_user_id} />
                    </td>
                    <td className="vp-td">{formatDate(v.created_at)}</td>
                    <td className="vp-td">
                      <span className={pillClass(v)} title={getAssignmentStatusDisplayLabel(v)}>
                        {getAssignmentStatusDisplayLabel(v)}
                      </span>
                    </td>
                    <td className="vp-td vp-td--verifier-note">
                      {verifierNote || <span className="vp-muted">—</span>}
                    </td>
                    <td className="vp-td">{formatDate(v.assigned_date || v.executor_assigned_at || v.verifier_assigned_at)}</td>
                    <td className="vp-td">
                      <PersonCell name={v.verifier_name} id={v.verifier_id} />
                    </td>
                    <td className="vp-td vp-td--action">
                      <button
                        type="button"
                        className="vp-action-btn"
                        disabled={!canOpenExecutor}
                        title={
                          canOpenExecutor
                            ? 'Execute assessment — open field video and tasks'
                            : 'Awaiting verifier review — opens when returned to you'
                        }
                        onClick={() => {
                          if (canOpenExecutor) setSelectedAssessment(v);
                        }}
                      >
                        <span className="vp-action-label">Execute</span>
                        <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" aria-hidden>
                          <polygon points="5 3 19 12 5 21 5 3" />
                        </svg>
                      </button>
                    </td>
                  </tr>
                  );
                })
              )}
            </tbody>
          </table>
        ) : paginated.length === 0 ? (
          <div className="vp-card-empty">
            {videos.length === 0
              ? 'No assessments are currently assigned to you as executor.'
              : 'No assessments match your search.'}
          </div>
        ) : (
          <div className="vp-card-grid">
            {paginated.map((v, idx) => {
              const canOpenExecutor = categorizeRow(v) !== 'verification_required';
              const rowCat = categorizeRow(v);
              const verifierNote =
                rowCat === 'returned' && getVerifierReturnRemarks(v)
                  ? getVerifierReturnRemarks(v)
                  : null;
              return (
              <article key={v.assessment_id} className="vp-assessment-card">
                <div className="vp-card-top">
                  <span className="vp-card-num">#{(safePage - 1) * entriesPerPage + idx + 1}</span>
                  <span className={pillClass(v)} title={getAssignmentStatusDisplayLabel(v)}>
                    {getAssignmentStatusDisplayLabel(v)}
                  </span>
                </div>
                <h2 className="vp-card-title">{v.video_title?.trim() || 'Untitled video'}</h2>
                <dl className="vp-card-meta">
                  <div className="vp-card-row">
                    <dt>Location</dt>
                    <dd>{v.location_name || '—'}</dd>
                  </div>
                  <div className="vp-card-row">
                    <dt>Section / work area</dt>
                    <dd>{v.department_name || '—'}</dd>
                  </div>
                  <div className="vp-card-row">
                    <dt>Contract</dt>
                    <dd className="vp-card-mono">{(v.contract_details ?? v.contact_details) || '—'}</dd>
                  </div>
                  <div className="vp-card-row">
                    <dt>Capture</dt>
                    <dd>{formatCaptureWhen(v)}</dd>
                  </div>
                  <div className="vp-card-row">
                    <dt>Uploaded by</dt>
                    <dd>
                      <PersonCell name={v.uploaded_by_name} id={v.uploader_user_id} />
                    </dd>
                  </div>
                  <div className="vp-card-row">
                    <dt>Upload date</dt>
                    <dd>{formatDate(v.created_at)}</dd>
                  </div>
                  <div className="vp-card-row">
                    <dt>Assigned</dt>
                    <dd>{formatDate(v.assigned_date || v.executor_assigned_at || v.verifier_assigned_at)}</dd>
                  </div>
                  <div className="vp-card-row">
                    <dt>Verifier</dt>
                    <dd>
                      <PersonCell name={v.verifier_name} id={v.verifier_id} />
                    </dd>
                  </div>
                  {verifierNote ? (
                    <div className="vp-card-row">
                      <dt>Verifier note</dt>
                      <dd className="vp-card-verifier-note">{verifierNote}</dd>
                    </div>
                  ) : null}
                </dl>
                <div className="vp-card-actions">
                  <button
                    type="button"
                    className="vp-action-btn vp-action-btn--full"
                    disabled={!canOpenExecutor}
                    title={
                      canOpenExecutor
                        ? 'Execute assessment — open field video and tasks'
                        : 'Awaiting verifier review — opens when returned to you'
                    }
                    onClick={() => {
                      if (canOpenExecutor) setSelectedAssessment(v);
                    }}
                  >
                    <span className="vp-action-label">Execute</span>
                    <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" aria-hidden>
                      <polygon points="5 3 19 12 5 21 5 3" />
                    </svg>
                  </button>
                </div>
              </article>
              );
            })}
          </div>
        )}
      </div>

      {/* Footer */}
      {!loading && (
        <div className="vp-footer">
          <span className="vp-footer-meta">
            {filtered.length === 0
              ? 'No entries to show'
              : `Showing ${(safePage - 1) * entriesPerPage + 1}–${Math.min(safePage * entriesPerPage, filtered.length)} of ${filtered.length}`}
          </span>
          <div className="vp-pagination">
            <button
              type="button"
              className="vp-page-btn"
              disabled={safePage === 1}
              onClick={() => setCurrentPage((p) => Math.max(1, p - 1))}
            >
              Previous
            </button>
            {Array.from({ length: totalPages }, (_, i) => i + 1)
              .filter((p) => p === 1 || p === totalPages || Math.abs(p - safePage) <= 1)
              .reduce((acc, p, i, arr) => {
                if (i > 0 && p - arr[i - 1] > 1) acc.push('...');
                acc.push(p);
                return acc;
              }, [])
              .map((item, i) =>
                item === '...' ? (
                  <span key={`ellipsis-${i}`} className="vp-page-ellipsis">…</span>
                ) : (
                  <button
                    key={item}
                    className={`vp-page-btn ${item === safePage ? 'vp-page-btn--active' : ''}`}
                    onClick={() => setCurrentPage(item)}
                  >
                    {item}
                  </button>
                )
              )}
            <button
              type="button"
              className="vp-page-btn"
              disabled={safePage === totalPages}
              onClick={() => setCurrentPage((p) => Math.min(totalPages, p + 1))}
            >
              Next
            </button>
          </div>
        </div>
      )}
      </div>
    </main>
  );
}

export default ExecutorVideoPage;
