'use client';

import * as React from 'react';
import Link from 'next/link';

const STATUS_COLUMNS = [
  { key: 'backlog', label: 'Backlog' },
  { key: 'todo', label: 'To do' },
  { key: 'in_progress', label: 'In progress' },
  { key: 'in_review', label: 'In review' },
  { key: 'blocked', label: 'Blocked' },
  { key: 'done', label: 'Done' },
  { key: 'cancelled', label: 'Cancelled' },
];

const STATUS_KEYS = STATUS_COLUMNS.map((c) => c.key);
const PRIORITIES = ['low', 'medium', 'high', 'urgent'];
const VIEW_STORAGE_KEY = 'madarx.tasksView';
const PROJECT_STORAGE_KEY = 'madarx.activeProjectId';

function statusTone(status) {
  if (status === 'done') return 'ready';
  if (status === 'blocked' || status === 'cancelled') return 'danger';
  if (status === 'in_progress' || status === 'in_review') return 'warn';
  return 'neutral';
}

function shortDate(iso) {
  if (!iso) return null;
  const date = new Date(iso);
  if (Number.isNaN(date.getTime())) return iso.slice(0, 10);
  const now = new Date();
  const diff = (now.getTime() - date.getTime()) / 1000;
  if (diff < 60) return 'just now';
  if (diff < 3600) return `${Math.floor(diff / 60)}m ago`;
  if (diff < 86400) return `${Math.floor(diff / 3600)}h ago`;
  if (diff < 86400 * 7) return `${Math.floor(diff / 86400)}d ago`;
  return iso.slice(0, 10);
}

function dueTone(iso) {
  if (!iso) return null;
  const date = new Date(iso);
  if (Number.isNaN(date.getTime())) return null;
  const diff = date.getTime() - Date.now();
  if (diff < 0) return 'overdue';
  if (diff < 86_400_000) return 'soon';
  return 'future';
}

function dueLabel(iso) {
  if (!iso) return null;
  const date = new Date(iso);
  if (Number.isNaN(date.getTime())) return iso.slice(0, 10);
  const today = new Date();
  const ymd = (d) => d.toISOString().slice(0, 10);
  if (ymd(date) === ymd(today)) return 'Today';
  const tomorrow = new Date(today.getTime() + 86_400_000);
  if (ymd(date) === ymd(tomorrow)) return 'Tomorrow';
  const yesterday = new Date(today.getTime() - 86_400_000);
  if (ymd(date) === ymd(yesterday)) return 'Yesterday';
  return date.toLocaleDateString(undefined, { month: 'short', day: 'numeric' });
}

function estimateLabel(minutes) {
  if (minutes == null || minutes <= 0) return null;
  if (minutes < 60) return `${minutes}m`;
  const h = Math.floor(minutes / 60);
  const m = minutes % 60;
  return m ? `${h}h${m}m` : `${h}h`;
}

function formatStatus(status) {
  return STATUS_COLUMNS.find((c) => c.key === status)?.label || status;
}

export default function TasksWorkspace({ taskRows, agents, projects }) {
  const agentsById = React.useMemo(
    () => new Map(agents.map((a) => [a.id, a])),
    [agents],
  );
  const projectsById = React.useMemo(
    () => new Map(projects.map((p) => [p.id, p])),
    [projects],
  );

  const [view, setView] = React.useState('list');
  const [projectId, setProjectId] = React.useState('');
  const [status, setStatus] = React.useState('');
  const [priority, setPriority] = React.useState('');
  const [assignee, setAssignee] = React.useState('');
  const [tag, setTag] = React.useState('');
  const [sortBy, setSortBy] = React.useState('updated');
  const [groupBy, setGroupBy] = React.useState('status');

  const allTags = React.useMemo(() => {
    const set = new Set();
    for (const { task } of taskRows) (task.tags || []).forEach((t) => set.add(t));
    return Array.from(set).sort();
  }, [taskRows]);

  React.useEffect(() => {
    try {
      const storedView = localStorage.getItem(VIEW_STORAGE_KEY);
      if (storedView === 'board' || storedView === 'list') setView(storedView);
      setProjectId(localStorage.getItem(PROJECT_STORAGE_KEY) || '');
    } catch {}
    const onProject = (e) => setProjectId(e?.detail?.project_id || '');
    window.addEventListener('madarx:project-change', onProject);
    return () => window.removeEventListener('madarx:project-change', onProject);
  }, []);

  function changeView(next) {
    setView(next);
    try { localStorage.setItem(VIEW_STORAGE_KEY, next); } catch {}
  }

  const filtered = React.useMemo(() => {
    const rows = taskRows.filter(({ task }) => {
      if (projectId && task.project_id !== projectId) return false;
      if (status && task.status !== status) return false;
      if (priority && task.priority !== priority) return false;
      if (assignee && task.assignee_agent_id !== assignee) return false;
      if (tag && !(Array.isArray(task.tags) && task.tags.includes(tag))) return false;
      return true;
    });
    if (sortBy === 'due') {
      const FAR = Number.MAX_SAFE_INTEGER;
      return [...rows].sort((a, b) => {
        const da = a.task.due_at ? new Date(a.task.due_at).getTime() : FAR;
        const db = b.task.due_at ? new Date(b.task.due_at).getTime() : FAR;
        return da - db;
      });
    }
    if (sortBy === 'priority') {
      const rank = { urgent: 0, high: 1, medium: 2, low: 3 };
      return [...rows].sort((a, b) => (rank[a.task.priority] ?? 9) - (rank[b.task.priority] ?? 9));
    }
    return rows;
  }, [taskRows, projectId, status, priority, assignee, tag, sortBy]);

  const hasFilter = Boolean(projectId || status || priority || assignee || tag);

  function clearFilters() {
    setStatus('');
    setPriority('');
    setAssignee('');
    setTag('');
  }

  const activeProject = projectId ? projectsById.get(projectId) : null;

  return (
    <div className="mkt-page" data-page="tasks">
      <section className="task-toolbar">
        <div className="task-toolbar-left">
          <div className="task-view-toggle" role="tablist" aria-label="View">
            <button
              type="button"
              role="tab"
              aria-selected={view === 'list'}
              className={view === 'list' ? 'on' : ''}
              onClick={() => changeView('list')}
            >
              <span aria-hidden className="task-view-glyph">{listGlyph}</span>
              List
            </button>
            <button
              type="button"
              role="tab"
              aria-selected={view === 'board'}
              className={view === 'board' ? 'on' : ''}
              onClick={() => changeView('board')}
            >
              <span aria-hidden className="task-view-glyph">{boardGlyph}</span>
              Board
            </button>
          </div>

          {view === 'board' ? (
            <label className="task-toolbar-field">
              <span>Group by</span>
              <select value={groupBy} onChange={(e) => setGroupBy(e.target.value)}>
                <option value="status">Status</option>
                <option value="project">Project</option>
                <option value="priority">Priority</option>
                <option value="assignee">Assignee</option>
              </select>
            </label>
          ) : null}
        </div>

        <div className="task-toolbar-right">
          <label className="task-toolbar-field">
            <span>Status</span>
            <select value={status} onChange={(e) => setStatus(e.target.value)}>
              <option value="">All</option>
              {STATUS_COLUMNS.map((s) => (
                <option key={s.key} value={s.key}>{s.label}</option>
              ))}
            </select>
          </label>
          <label className="task-toolbar-field">
            <span>Priority</span>
            <select value={priority} onChange={(e) => setPriority(e.target.value)}>
              <option value="">All</option>
              {PRIORITIES.map((p) => <option key={p} value={p}>{p}</option>)}
            </select>
          </label>
          <label className="task-toolbar-field">
            <span>Assignee</span>
            <select value={assignee} onChange={(e) => setAssignee(e.target.value)}>
              <option value="">All</option>
              {agents.map((a) => <option key={a.id} value={a.id}>{a.name}</option>)}
            </select>
          </label>
          {allTags.length ? (
            <label className="task-toolbar-field">
              <span>Tag</span>
              <select value={tag} onChange={(e) => setTag(e.target.value)}>
                <option value="">All</option>
                {allTags.map((t) => <option key={t} value={t}>#{t}</option>)}
              </select>
            </label>
          ) : null}
          <label className="task-toolbar-field">
            <span>Sort</span>
            <select value={sortBy} onChange={(e) => setSortBy(e.target.value)}>
              <option value="updated">Updated</option>
              <option value="due">Due date</option>
              <option value="priority">Priority</option>
            </select>
          </label>
          {hasFilter ? (
            <button type="button" className="task-toolbar-clear" onClick={clearFilters}>
              Clear
            </button>
          ) : null}
        </div>
      </section>

      {activeProject ? (
        <div className="task-scope-banner">
          <span
            className="task-scope-tile"
            style={{ backgroundColor: activeProject.color || '#111318' }}
            aria-hidden
          >
            {(activeProject.name || activeProject.slug).slice(0, 1).toUpperCase()}
          </span>
          <div className="task-scope-text">
            <b>Scoped to {activeProject.name}</b>
            <small>Project filter set via header switcher · {filtered.length} task{filtered.length === 1 ? '' : 's'}</small>
          </div>
        </div>
      ) : null}

      {filtered.length === 0 ? (
        <div className="admin-empty">
          <b>{hasFilter || projectId ? 'No tasks match these filters' : 'No tasks yet'}</b>
          <p>
            {hasFilter || projectId
              ? 'Try a different combination, or clear filters from above.'
              : 'Create one from the top right, or delegate via the Main Agent.'}
          </p>
        </div>
      ) : view === 'list' ? (
        <ListView rows={filtered} agentsById={agentsById} projectsById={projectsById} />
      ) : (
        <BoardView
          rows={filtered}
          agentsById={agentsById}
          projectsById={projectsById}
          groupBy={groupBy}
        />
      )}
    </div>
  );
}

function ListView({ rows, agentsById, projectsById }) {
  return (
    <ul className="task-list">
      {rows.map(({ task, operator }) => (
        <li key={task.id} className={'task-row' + (operator?.needs_action ? ' needs-action' : '')}>
          <Link href={`/tasks/${task.id}`} className="task-row-main">
            <div className="task-row-head">
              <span className="task-row-title">{task.title}</span>
              <span className={`admin-pill ${statusTone(task.status)}`}>{formatStatus(task.status)}</span>
              {operator?.needs_action ? <span className="admin-pill danger">needs action</span> : null}
            </div>
            {task.description ? <p className="task-row-desc">{task.description}</p> : null}
            {operator?.needs_action_reason ? <p className="task-row-alert">{operator.needs_action_reason}</p> : null}
            <TaskMeta task={task} operator={operator} agentsById={agentsById} projectsById={projectsById} />
          </Link>
        </li>
      ))}
    </ul>
  );
}

function BoardView({ rows, agentsById, projectsById, groupBy }) {
  const columns = React.useMemo(() => {
    if (groupBy === 'status') {
      const map = new Map(STATUS_COLUMNS.map((c) => [c.key, { key: c.key, label: c.label, rows: [] }]));
      for (const row of rows) {
        const col = map.get(row.task.status) || map.get('backlog');
        col.rows.push(row);
      }
      return Array.from(map.values()).filter((c) => c.rows.length > 0 || STATUS_KEYS.includes(c.key));
    }
    if (groupBy === 'priority') {
      const map = new Map(PRIORITIES.map((p) => [p, { key: p, label: p, rows: [] }]));
      for (const row of rows) {
        const col = map.get(row.task.priority) || map.get('medium');
        col.rows.push(row);
      }
      return Array.from(map.values());
    }
    if (groupBy === 'assignee') {
      const map = new Map();
      map.set('__unassigned__', { key: '__unassigned__', label: 'Unassigned', rows: [] });
      for (const row of rows) {
        const id = row.task.assignee_agent_id || '__unassigned__';
        if (!map.has(id)) {
          const agent = agentsById.get(id);
          map.set(id, { key: id, label: agent?.name || id, rows: [] });
        }
        map.get(id).rows.push(row);
      }
      return Array.from(map.values()).filter((c) => c.rows.length > 0);
    }
    const map = new Map();
    map.set('__none__', { key: '__none__', label: 'No project', rows: [] });
    for (const row of rows) {
      const pid = row.task.project_id || '__none__';
      if (!map.has(pid)) {
        const project = projectsById.get(pid);
        map.set(pid, { key: pid, label: project?.name || pid, color: project?.color, rows: [] });
      }
      map.get(pid).rows.push(row);
    }
    return Array.from(map.values()).filter((c) => c.rows.length > 0);
  }, [rows, groupBy, agentsById, projectsById]);

  return (
    <div className="task-board" role="list">
      {columns.map((col) => (
        <section key={col.key} className="task-board-col" role="listitem">
          <header className="task-board-col-head">
            {col.color ? (
              <span
                className="task-board-col-dot"
                style={{ backgroundColor: col.color }}
                aria-hidden
              />
            ) : null}
            <h3>{col.label}</h3>
            <span className="task-board-col-count">{col.rows.length}</span>
          </header>
          <ol className="task-board-col-list">
            {col.rows.length === 0 ? (
              <li className="task-board-empty">No tasks</li>
            ) : col.rows.map(({ task, operator }) => (
              <li
                key={task.id}
                className={'task-board-card' + (operator?.needs_action ? ' needs-action' : '')}
              >
                <Link href={`/tasks/${task.id}`} className="task-board-card-link">
                  <div className="task-board-card-head">
                    <span className={`admin-pill ${statusTone(task.status)}`}>{formatStatus(task.status)}</span>
                    <span className={`task-board-prio prio-${task.priority}`}>{task.priority}</span>
                  </div>
                  <p className="task-board-card-title">{task.title}</p>
                  {operator?.needs_action_reason ? (
                    <p className="task-board-card-alert">{operator.needs_action_reason}</p>
                  ) : null}
                  <TaskMeta task={task} operator={operator} agentsById={agentsById} projectsById={projectsById} compact />
                </Link>
              </li>
            ))}
          </ol>
        </section>
      ))}
    </div>
  );
}

function TaskMeta({ task, operator, agentsById, projectsById, compact = false }) {
  const assigneeName = task.assignee_agent_id
    ? (agentsById.get(task.assignee_agent_id)?.name || task.assignee_agent_id)
    : 'unassigned';
  const project = task.project_id ? projectsById.get(task.project_id) : null;
  const runLabel = operator?.active_run_status
    ? `active · ${operator.active_run_status}`
    : operator?.last_run_status
      ? `last · ${operator.last_run_status}`
      : null;
  const due = dueLabel(task.due_at);
  const dueT = dueTone(task.due_at);
  const est = estimateLabel(task.estimate_minutes);
  const tags = Array.isArray(task.tags) ? task.tags.slice(0, compact ? 3 : 5) : [];
  const watchers = Array.isArray(task.watchers) ? task.watchers.length : 0;
  return (
    <div className={compact ? 'task-board-meta' : 'task-row-meta'}>
      {project ? (
        <span className="task-meta-project">
          <i style={{ backgroundColor: project.color || '#111318' }} aria-hidden />
          {project.name}
        </span>
      ) : null}
      {due ? <span className={`task-meta-due tone-${dueT}`}>{dueT === 'overdue' ? '⚠ ' : ''}{due}</span> : null}
      {est ? <span className="task-meta-est">⏱ {est}</span> : null}
      {tags.length ? (
        <span className="task-meta-tags">
          {tags.map((t) => <span key={t} className="task-meta-tag">#{t}</span>)}
        </span>
      ) : null}
      <span>{assigneeName}</span>
      {watchers ? <span className="task-meta-watchers">+{watchers}</span> : null}
      {!compact ? <span>·</span> : null}
      <span>{task.priority}</span>
      {task.recurrence ? <span className="task-meta-recur" title={`Recurs ${task.recurrence}`}>↻</span> : null}
      {runLabel ? (compact ? <span>{runLabel}</span> : <><span>·</span><span>{runLabel}</span></>) : null}
      {!compact ? <span>·</span> : null}
      <span>{shortDate(task.updated_at)}</span>
    </div>
  );
}

const listGlyph = (
  <svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round">
    <path d="M3 4h10M3 8h10M3 12h10" />
  </svg>
);

const boardGlyph = (
  <svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.4">
    <rect x="2.5" y="2.5" width="3.5" height="11" rx="1" />
    <rect x="6.5" y="2.5" width="3.5" height="7" rx="1" />
    <rect x="10.5" y="2.5" width="3.5" height="9" rx="1" />
  </svg>
);
