import { revalidatePath } from 'next/cache';
import { redirect } from 'next/navigation';
import { AdminShell, EmptyState, StatCard, StatusPill } from '@/app/components/admin/admin-page.jsx';
import { getOrgChart, reportingSnapshot, updateAgentOrg } from '@/lib/delegation.js';
import { listAgents } from '@/lib/runtime.js';

export const dynamic = 'force-dynamic';
export const runtime = 'nodejs';

const ROLE_LABELS = {
  executive: 'Executive',
  manager: 'Manager',
  team_lead: 'Team Lead',
  individual_contributor: 'Contributor',
};

const ROLE_TONES = {
  executive: 'mars',
  manager: 'ready',
  team_lead: 'warn',
  individual_contributor: 'neutral',
};

function initials(name = '') {
  return name
    .split(/\s+/)
    .map(part => part[0])
    .filter(Boolean)
    .slice(0, 2)
    .join('')
    .toUpperCase() || '·';
}

function inferRole(node) {
  if (node.role && ROLE_LABELS[node.role]) return node.role;
  const reportCount = node.reports?.length || 0;
  if (reportCount >= 4) return 'executive';
  if (reportCount >= 2) return 'manager';
  if (reportCount === 1) return 'team_lead';
  return 'individual_contributor';
}

async function updateOrgAction(formData) {
  'use server';
  const agentId = String(formData.get('agent_id') || '').trim();
  if (!agentId) return;
  const reportsToRaw = String(formData.get('reports_to') || '').trim();
  const patch = {
    reports_to: reportsToRaw === '' ? null : reportsToRaw,
  };
  const role = String(formData.get('role') || '').trim();
  if (role) patch.role = role;
  const title = String(formData.get('title') || '').trim();
  if (title || formData.has('title')) patch.title = title || null;
  try {
    updateAgentOrg(agentId, patch);
  } catch (error) {
    // Acyclic guard or unknown agent — silently ignore for now; revalidate so the form resets.
    console.warn('updateAgentOrg failed', error?.message);
  }
  revalidatePath('/org');
  revalidatePath('/agents');
  redirect('/org');
}

function OrgCard({ node, workloadById }) {
  const role = inferRole(node);
  const roleLabel = ROLE_LABELS[role];
  const roleTone = ROLE_TONES[role];
  const reportCount = node.reports?.length || 0;
  const workload = workloadById.get(node.id);
  const activeTasks = Number(workload?.active_tasks || 0);
  const blockedTasks = Number(workload?.blocked_tasks || 0);
  const completedTasks = Number(workload?.completed_tasks || 0);
  const status = node.status || 'created';
  const statusTone = status === 'heartbeat ok' ? 'ready' : status === 'terminated' ? 'danger' : 'neutral';

  return (
    <article className={`org-card org-card--${role}`} data-reports={reportCount > 0 ? 'has' : 'none'}>
      <div className="org-card-head">
        <div className="org-card-avatar" aria-hidden="true">{initials(node.name)}</div>
        <div className="org-card-identity">
          <div className="org-card-name">{node.name}</div>
          <div className="org-card-title">{node.title || node.mission?.slice(0, 64) || 'No title set'}</div>
        </div>
      </div>
      <div className="org-card-meta">
        <StatusPill tone={roleTone}>{roleLabel}</StatusPill>
        <StatusPill tone={statusTone}>{status}</StatusPill>
        {reportCount > 0 ? <StatusPill tone="neutral">{reportCount} report{reportCount === 1 ? '' : 's'}</StatusPill> : null}
      </div>
      <dl className="org-card-stats">
        <div><dt>Active</dt><dd>{activeTasks}</dd></div>
        <div><dt>Blocked</dt><dd className={blockedTasks ? 'is-warn' : ''}>{blockedTasks}</dd></div>
        <div><dt>Done</dt><dd>{completedTasks}</dd></div>
      </dl>
    </article>
  );
}

function OrgBranch({ node, workloadById }) {
  const hasReports = (node.reports || []).length > 0;
  return (
    <li className="org-branch">
      <OrgCard node={node} workloadById={workloadById} />
      {hasReports ? (
        <ul className="org-children">
          {node.reports.map(child => (
            <OrgBranch key={child.id} node={child} workloadById={workloadById} />
          ))}
        </ul>
      ) : null}
    </li>
  );
}

export default function OrgPage() {
  const org = getOrgChart();
  const reporting = reportingSnapshot();
  const allAgents = listAgents();
  const workloadById = new Map((reporting.workload || []).map(item => [item.agent_id, item]));
  const totalLeaders = allAgents.filter(a => allAgents.some(other => other.reports_to === a.id)).length;
  const orphanCount = allAgents.filter(a => !a.reports_to && a.id).length;

  return (
    <AdminShell
      title="Agent chart"
      description="Company-style structure for your agent workforce. Set managers, define roles, and see workload at a glance."
    >
      <section className="admin-stats">
        <StatCard label="Headcount" value={reporting.totals.active_agents} />
        <StatCard label="Leaders" value={totalLeaders} />
        <StatCard label="Root nodes" value={orphanCount} />
        <StatCard label="Active tasks" value={reporting.totals.active_tasks} />
      </section>

      <section className="admin-panel">
        <div className="admin-panel-head">
          <span>Agent chart</span>
          <small>Top-down hierarchy. Each card shows role, status, and current workload.</small>
        </div>
        {org.length ? (
          <div className="org-chart-scroll">
            <ul className="org-chart">
              {org.map(node => (
                <OrgBranch key={node.id} node={node} workloadById={workloadById} />
              ))}
            </ul>
          </div>
        ) : (
          <EmptyState title="No agents yet">
            Create an agent on the Agents page, then come back here to assign managers.
          </EmptyState>
        )}
      </section>

      <section className="admin-grid reports-layout">
        <div className="admin-panel">
          <div className="admin-panel-head">
            <span>Reporting lines</span>
            <small>Re-parent any agent. Cycles are blocked automatically.</small>
          </div>
          {allAgents.length ? (
            <div className="admin-card-list compact">
              {allAgents.map(agent => {
                const manager = agent.reports_to ? allAgents.find(a => a.id === agent.reports_to) : null;
                const candidates = allAgents.filter(a => a.id !== agent.id);
                const role = agent.role && ROLE_LABELS[agent.role] ? agent.role : 'individual_contributor';
                return (
                  <form
                    key={agent.id}
                    action={updateOrgAction}
                    className="org-reporting-row"
                  >
                    <input type="hidden" name="agent_id" value={agent.id} />
                    <div className="org-reporting-identity">
                      <div className="org-card-avatar small" aria-hidden="true">{initials(agent.name)}</div>
                      <div>
                        <div className="org-reporting-name">{agent.name}</div>
                        <div className="org-reporting-sub">
                          {manager ? `Reports to ${manager.name}` : 'Top of chain'}
                        </div>
                      </div>
                    </div>
                    <div className="org-reporting-fields">
                      <label className="org-reporting-field">
                        <span>Title</span>
                        <input
                          type="text"
                          name="title"
                          defaultValue={agent.title || ''}
                          placeholder="e.g. Marketing Manager"
                        />
                      </label>
                      <label className="org-reporting-field">
                        <span>Role</span>
                        <select name="role" defaultValue={role}>
                          {Object.entries(ROLE_LABELS).map(([value, label]) => (
                            <option key={value} value={value}>{label}</option>
                          ))}
                        </select>
                      </label>
                      <label className="org-reporting-field">
                        <span>Manager</span>
                        <select name="reports_to" defaultValue={agent.reports_to || ''}>
                          <option value="">— None (top of chain)</option>
                          {candidates.map(candidate => (
                            <option key={candidate.id} value={candidate.id}>{candidate.name}</option>
                          ))}
                        </select>
                      </label>
                      <button className="admin-button" type="submit">Save</button>
                    </div>
                  </form>
                );
              })}
            </div>
          ) : (
            <EmptyState title="No agents yet">Create agents to start building your org.</EmptyState>
          )}
        </div>

        <div className="admin-panel">
          <div className="admin-panel-head">
            <span>Workload by agent</span>
            <small>Derived from active tasks.</small>
          </div>
          {reporting.workload.length ? (
            <div className="admin-card-list compact">
              {reporting.workload.map(item => (
                <div key={item.agent_id} className="admin-record compact">
                  <div className="admin-record-top">
                    <b>{item.agent_name || item.agent_id}</b>
                    <StatusPill tone={item.blocked_tasks ? 'danger' : item.active_tasks ? 'ready' : 'neutral'}>
                      {item.active_tasks} active
                    </StatusPill>
                  </div>
                  <p>{item.total_tasks} total · {item.blocked_tasks} blocked · {item.completed_tasks} complete</p>
                </div>
              ))}
            </div>
          ) : (
            <EmptyState title="No workload data">Assign tasks to see workload distribution.</EmptyState>
          )}
        </div>
      </section>
    </AdminShell>
  );
}
