import React, { useCallback, useEffect, useMemo, useState } from "react";
import AssignUserModal from "../../components/admin/AssignUserModal.jsx";
import AssignmentViewToggle from "../../components/swi/assignments/AssignmentViewToggle.jsx";
import {
  buildAssignDocumentPayload,
  fetchDocuments,
  fetchUsers,
  updateDocument,
} from "../../services/swiApi.js";
import { canAdminAssignDocument } from "../../constants/swiDocumentStatus.js";
import { getApiErrorMessage } from "../../utils/apiError.js";

const VIEW_STORAGE_KEY = "swi-admin-assign-view";

function labelForUser(u) {
  return u.employee_name || u.email_id || `User #${u.user_id}`;
}

function docKey(d) {
  return `${d.document_id}-${d.document_number}`;
}

function readStoredView() {
  try {
    const v = localStorage.getItem(VIEW_STORAGE_KEY);
    return v === "card" ? "card" : "list";
  } catch {
    return "list";
  }
}

function formatDate(value) {
  if (!value) return "—";
  const d = new Date(value);
  if (Number.isNaN(d.getTime())) return "—";
  return d.toLocaleDateString(undefined, {
    year: "numeric",
    month: "short",
    day: "numeric",
  });
}

function statusLabel(doc) {
  if (doc.document_status_id === 1) return "Opened";
  if (doc.document_status_id === 2) return "Assigned";
  if (doc.document_status_id === 3) return "In Progress";
  if (doc.document_status_id === 4) return "Completed";
  return doc.assigned_to_user_id ? "Assigned" : "Unassigned";
}

function statusClass(doc) {
  if (doc.document_status_id === 3) return "swi-status-badge--in-progress";
  if (doc.document_status_id === 4) return "swi-status-badge--completed";
  if (doc.document_status_id === 1) return "swi-status-badge--opened";
  if (doc.assigned_to_user_id) return "swi-status-badge--assigned";
  return "swi-status-badge--opened";
}

export default function AssignDocumentPage() {
  const [documents, setDocuments] = useState([]);
  const [users, setUsers] = useState([]);
  const [assignModalDoc, setAssignModalDoc] = useState(null);
  const [modalSaving, setModalSaving] = useState(false);
  const [modalError, setModalError] = useState("");
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState("");
  const [success, setSuccess] = useState("");
  const [view, setView] = useState(readStoredView);
  const [query, setQuery] = useState("");

  const usersById = useMemo(() => {
    const map = new Map();
    for (const u of users) {
      map.set(Number(u.user_id), u);
    }
    return map;
  }, [users]);

  const load = useCallback(async () => {
    setError("");
    const [docs, userList] = await Promise.all([fetchDocuments(), fetchUsers()]);
    setDocuments(docs);
    setUsers(userList);
    return { docs, userList };
  }, []);

  useEffect(() => {
    load()
      .catch((e) =>
        setError(getApiErrorMessage(e, "Could not load documents."))
      )
      .finally(() => setLoading(false));
  }, [load]);

  useEffect(() => {
    if (assignModalDoc && !canAdminAssignDocument(assignModalDoc)) {
      setAssignModalDoc(null);
      setModalError("");
    }
  }, [documents, assignModalDoc]);

  const assigneeLabel = useCallback(
    (userId) => {
      if (userId == null || userId === "") return null;
      const u = usersById.get(Number(userId));
      return u ? labelForUser(u) : `User #${userId}`;
    },
    [usersById]
  );

  const filteredDocuments = useMemo(() => {
    const q = query.trim().toLowerCase();
    if (!q) return documents;
    return documents.filter((d) => {
      const name = (d.document_name || "").toLowerCase();
      const id = String(d.document_id);
      const assignee = assigneeLabel(d.assigned_to_user_id)?.toLowerCase() || "";
      return name.includes(q) || id.includes(q) || assignee.includes(q);
    });
  }, [documents, query, assigneeLabel]);

  const openAssignModal = (doc) => {
    if (!canAdminAssignDocument(doc)) return;
    setAssignModalDoc(doc);
    setModalError("");
    setSuccess("");
    setError("");
  };

  const closeAssignModal = () => {
    if (modalSaving) return;
    setAssignModalDoc(null);
    setModalError("");
  };

  const handleAssignConfirm = async (userId) => {
    if (!assignModalDoc || !canAdminAssignDocument(assignModalDoc)) return;

    setModalSaving(true);
    setModalError("");
    try {
      const payload = buildAssignDocumentPayload(userId, {
        existingRow: assignModalDoc,
      });
      const saved = await updateDocument(
        assignModalDoc.document_id,
        assignModalDoc.document_number,
        payload
      );
      const name = assigneeLabel(saved.assigned_to_user_id);
      setSuccess(
        `Assigned "${saved.document_name || "document"}" to ${name || "user"}. Status set to Assigned.`
      );
      await load();
      setAssignModalDoc(null);
    } catch (e) {
      setModalError(getApiErrorMessage(e, "Assignment failed."));
    } finally {
      setModalSaving(false);
    }
  };

  const changeView = (next) => {
    setView(next);
    try {
      localStorage.setItem(VIEW_STORAGE_KEY, next);
    } catch {
      /* ignore */
    }
  };

  if (loading) {
    return <p className="swi-muted">Loading documents…</p>;
  }

  const assignedCount = documents.filter((d) => d.assigned_to_user_id).length;
  const unassignedCount = documents.length - assignedCount;
  const modalDocKey = assignModalDoc ? docKey(assignModalDoc) : "";

  return (
    <div className="swi-admin-assign-page">
      <header className="portal-page-header portal-page-header--solo">
        <div className="portal-page-header__text">
          <h1 className="portal-page-title">Assign document</h1>
          <p className="portal-page-subtitle">
            Choose an unassigned document and pick a user from the assignment list.
          </p>
        </div>
        <div className="portal-page-header__actions">
          <AssignmentViewToggle view={view} onChange={changeView} />
        </div>
      </header>

      {error ? (
        <div className="swi-error" role="alert">
          {error}
        </div>
      ) : null}
      {success ? (
        <div className="swi-success" role="status">
          {success}
        </div>
      ) : null}

      <div className="swi-admin-assign-toolbar swi-panel">
        <div className="swi-admin-assign-stats">
          <span className="swi-admin-assign-stat">
            <strong>{documents.length}</strong> total
          </span>
          <span className="swi-admin-assign-stat">
            <strong>{assignedCount}</strong> assigned
          </span>
          <span className="swi-admin-assign-stat">
            <strong>{unassignedCount}</strong> unassigned
          </span>
        </div>
        <label className="swi-admin-assign-search">
          <span className="visually-hidden">Search documents</span>
          <input
            type="search"
            className="swi-input"
            placeholder="Search by name, ID, or assignee…"
            value={query}
            onChange={(e) => setQuery(e.target.value)}
          />
        </label>
      </div>

      <div className="swi-admin-assign-hint swi-panel" role="note">
        Click <strong>Assign</strong> on an unassigned document to open the user list.
      </div>

      <section className="swi-panel swi-admin-assign-content">
        {!filteredDocuments.length ? (
          <p className="swi-muted swi-admin-assign-empty">
            {documents.length
              ? "No documents match your search."
              : "No documents yet. Create one on the Create document page."}
          </p>
        ) : view === "list" ? (
          <div className="swi-table-wrap swi-admin-assign-table-wrap">
            <table className="swi-table swi-admin-assign-table">
              <thead>
                <tr>
                  <th>Document</th>
                  <th>ID / Rev</th>
                  <th>Assignee</th>
                  <th>Assigned date</th>
                  <th>Status</th>
                  <th aria-label="Action" />
                </tr>
              </thead>
              <tbody>
                {filteredDocuments.map((d) => {
                  const key = docKey(d);
                  const modalOpen = key === modalDocKey;
                  const assignee = assigneeLabel(d.assigned_to_user_id);
                  const canAssign = canAdminAssignDocument(d);
                  return (
                    <tr
                      key={key}
                      className={`swi-admin-assign-table__row${modalOpen ? " is-selected" : ""}`}
                    >
                      <td data-label="Document">
                        <span className="swi-admin-assign-table__name">
                          {d.document_name || "Untitled"}
                        </span>
                        {d.process_name ? (
                          <span className="swi-muted small">{d.process_name}</span>
                        ) : null}
                      </td>
                      <td data-label="ID / Rev">
                        {d.document_id} · #{d.document_number}
                      </td>
                      <td data-label="Assignee">
                        {assignee || (
                          <span className="swi-muted">Not assigned</span>
                        )}
                      </td>
                      <td data-label="Assigned date">
                        {formatDate(d.assigned_at)}
                      </td>
                      <td data-label="Status">
                        <span className={`swi-status-badge ${statusClass(d)}`}>
                          {statusLabel(d)}
                        </span>
                      </td>
                      <td data-label="Action">
                        {canAssign ? (
                          <button
                            type="button"
                            className="swi-btn swi-btn--compact swi-btn--primary"
                            onClick={() => openAssignModal(d)}
                          >
                            Assign
                          </button>
                        ) : (
                          <span className="swi-muted small">Already assigned</span>
                        )}
                      </td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
          </div>
        ) : (
          <ul className="swi-admin-assign-card-grid">
            {filteredDocuments.map((d) => {
              const key = docKey(d);
              const modalOpen = key === modalDocKey;
              const assignee = assigneeLabel(d.assigned_to_user_id);
              const canAssign = canAdminAssignDocument(d);
              return (
                <li key={key}>
                  <article
                    className={`swi-admin-assign-card${modalOpen ? " is-selected" : ""}`}
                  >
                    <div className="swi-admin-assign-card__head">
                      <h3 className="swi-admin-assign-card__title">
                        {d.document_name || "Untitled"}
                      </h3>
                      <span className={`swi-status-badge ${statusClass(d)}`}>
                        {statusLabel(d)}
                      </span>
                    </div>
                    <dl className="swi-admin-assign-card__meta">
                      <div>
                        <dt>Document</dt>
                        <dd>
                          ID {d.document_id} · #{d.document_number}
                        </dd>
                      </div>
                      <div>
                        <dt>Assignee</dt>
                        <dd>{assignee || "Not assigned"}</dd>
                      </div>
                      <div>
                        <dt>Assigned</dt>
                        <dd>{formatDate(d.assigned_at)}</dd>
                      </div>
                    </dl>
                    {canAssign ? (
                      <button
                        type="button"
                        className="swi-btn swi-btn--compact swi-btn--primary"
                        onClick={() => openAssignModal(d)}
                      >
                        Assign to user
                      </button>
                    ) : (
                      <p className="swi-muted small swi-admin-assign-card__locked">
                        Already assigned — reassignment is not allowed.
                      </p>
                    )}
                  </article>
                </li>
              );
            })}
          </ul>
        )}
      </section>

      <AssignUserModal
        open={Boolean(assignModalDoc)}
        doc={assignModalDoc}
        users={users}
        saving={modalSaving}
        error={modalError}
        onClose={closeAssignModal}
        onAssign={handleAssignConfirm}
      />
    </div>
  );
}
