/* Greydigi — AI Recruiting dashboard. App state owns jobs/candidates/interviews. */
const { useState, useMemo, useEffect } = React;
const G = window.GreydigiComponents;
const { Avatar, Badge, Button, CandidateRow, FilterPill, StatCard, SkillBar, Tag, DecisionBanner } = G;

/* ---------------- Top navigation ---------------- */
function TopNav({ jobs, currentJobId, onPickJob }) {
  const [jobOpen, setJobOpen] = useState(false);
  const current = jobs.find((j) => j.id === currentJobId) || jobs[0];
  return (
    <header className="nav">
      <div className="nav-logo">
        <img className="logo-img" src="/greydigi-logo.png" alt="Greydigi" />
        <div>
          <div className="logo-name">Greydigi</div>
          <div className="logo-sub">AI Recruiting</div>
        </div>
      </div>

      <div className="nav-search">
        <div className="search-box">
          <Icon name="search" size={16} className="i-faint" />
          <input placeholder="Search candidates, jobs, skills…" />
          <kbd className="kbd"><Icon name="command" size={10} />K</kbd>
        </div>
      </div>

      <div className="nav-right">
        <div className="job-wrap">
          <button className="job-select" onClick={() => setJobOpen((v) => !v)}>
            <Icon name="briefcase" size={15} className="i-faint" />
            <span className="truncate">{current ? current.title : 'No job'}</span>
            <Icon name="chevronDown" size={14} className="i-faint" style={{ transform: jobOpen ? 'rotate(180deg)' : 'none', transition: 'transform .15s' }} />
          </button>
          {jobOpen && (
            <>
              <div className="menu-overlay" onMouseDown={() => setJobOpen(false)} />
              <div className="menu job-menu">
                <div className="job-menu-label">Switch job</div>
                {jobs.filter((j) => j.status === 'open').map((j) => (
                  <button key={j.id} className={'menu-item' + (j.id === currentJobId ? ' active' : '')} onClick={() => { onPickJob(j.id); setJobOpen(false); }}>
                    <span className="job-menu-item">
                      <span className="job-menu-title">{j.title}</span>
                      <span className="job-menu-sub">{j.stage} · {j.loc}</span>
                    </span>
                    {j.id === currentJobId && <Icon name="check" size={14} />}
                  </button>
                ))}
              </div>
            </>
          )}
        </div>
        <button className="icon-btn" aria-label="Notifications">
          <Icon name="bell" size={18} />
          <span className="dot" />
        </button>
        <Avatar initials="JD" size="md" color="charcoal" />
      </div>
    </header>
  );
}

/* ---------------- Sidebar ---------------- */
function Sidebar({ tab, onTab, counts }) {
  const NAV = [
    { id: 'dashboard', icon: 'dashboard', label: 'Dashboard' },
    { id: 'candidates', icon: 'users', label: 'Candidates', count: counts.candidates },
    { id: 'jobs', icon: 'briefcase', label: 'Jobs', count: counts.jobs },
    { id: 'pipeline', icon: 'pipeline', label: 'Pipeline' },
    { id: 'interviews', icon: 'calendar', label: 'Interviews', count: counts.interviews },
    { id: 'analytics', icon: 'analytics', label: 'Analytics' },
  ];
  return (
    <aside className="sidebar">
      <div className="side-label">Workspace</div>
      {NAV.map((n) => (
        <button key={n.id} className={'nav-item' + (n.id === tab ? ' active' : '')} onClick={() => onTab(n.id)}>
          <Icon name={n.icon} size={18} />
          <span className="label">{n.label}</span>
          {n.count != null && <span className="count">{n.count}</span>}
        </button>
      ))}
      <div className="side-spacer">
        <button className={'nav-item' + (tab === 'settings' ? ' active' : '')} onClick={() => onTab('settings')}>
          <Icon name="settings" size={18} />
          <span className="label">Settings</span>
        </button>
      </div>
    </aside>
  );
}

/* ---------------- Candidate list ---------------- */
const SORTS = ['ATS score', 'Skills match', 'Experience', 'Most recent', 'Name (A–Z)'];
const REC_LABEL = {
  shortlisted: { label: 'Proceed', variant: 'success' },
  borderline: { label: 'Proceed with Caution', variant: 'warning' },
  rejected: { label: 'Reject', variant: 'error' },
};

/* must/preferred coverage meter shown on each card */
function ReqMeter({ label, n, total }) {
  const full = total > 0 && n === total;
  return (
    <span className={'req' + (full ? ' req-full' : '')}>
      <span className="req-k">{label}</span>
      <span className="req-dots">
        {Array.from({ length: total }).map((_, i) => (
          <span key={i} className={'req-dot' + (i < n ? ' on' : '')} />
        ))}
      </span>
      <span className="req-v">{n}/{total}</span>
    </span>
  );
}

function ListPanel({ job, candidates, selected, onSelect }) {
  const [query, setQuery] = useState('');
  const [sort, setSort] = useState('ATS score');
  const [sortOpen, setSortOpen] = useState(false);
  const [decision, setDecision] = useState('all');

  const counts = useMemo(() => {
    const c = { all: candidates.length, shortlisted: 0, borderline: 0, rejected: 0 };
    candidates.forEach((p) => { c[p.decision]++; });
    return c;
  }, [candidates]);

  const list = useMemo(() => {
    const q = query.trim().toLowerCase();
    let out = candidates.filter((p) => {
      if (decision !== 'all' && p.decision !== decision) return false;
      if (q) {
        const hay = `${p.name} ${p.headline} ${p.company} ${p.location} ${p.strengths.join(' ')}`.toLowerCase();
        if (!hay.includes(q)) return false;
      }
      return true;
    });
    const by = {
      'ATS score': (a, b) => b.ats - a.ats || a.name.localeCompare(b.name),
      'Skills match': (a, b) => b.skills_pct - a.skills_pct || a.name.localeCompare(b.name),
      'Experience': (a, b) => b.years - a.years || a.name.localeCompare(b.name),
      'Most recent': (a, b) => b.appliedDate.localeCompare(a.appliedDate) || a.name.localeCompare(b.name),
      'Name (A–Z)': (a, b) => a.name.localeCompare(b.name),
    }[sort];
    return [...out].sort(by);
  }, [query, sort, decision, candidates]);

  const FILTERS = [
    { id: 'all', label: 'All', count: counts.all },
    { id: 'shortlisted', label: 'Shortlisted', count: counts.shortlisted },
    { id: 'borderline', label: 'Borderline', count: counts.borderline },
    { id: 'rejected', label: 'Rejected', count: counts.rejected },
  ];

  return (
    <section className="list-panel">
      <div className="list-head">
        <div className="list-title-row">
          <div className="list-title">
            <h2>Candidates</h2>
            <span className="count-chip">{list.length}</span>
          </div>
          <div className="sort-wrap">
            <button className="sort-btn" onClick={() => setSortOpen((v) => !v)}>
              <Icon name="sort" size={14} className="i-faint" />
              {sort}
              <Icon name="chevronDown" size={14} className="i-faint" style={{ transform: sortOpen ? 'rotate(180deg)' : 'none', transition: 'transform .15s' }} />
            </button>
            {sortOpen && (
              <>
                <div className="menu-overlay" onMouseDown={() => setSortOpen(false)} />
                <div className="menu">
                  {SORTS.map((s) => (
                    <button key={s} className={'menu-item' + (s === sort ? ' active' : '')} onClick={() => { setSort(s); setSortOpen(false); }}>
                      {s}{s === sort && <Icon name="check" size={14} />}
                    </button>
                  ))}
                </div>
              </>
            )}
          </div>
        </div>

        <div className="list-search">
          <Icon name="search" size={15} className="i-faint" />
          <input value={query} onChange={(e) => setQuery(e.target.value)} placeholder="Filter this list…" />
        </div>

        <div className="filter-row">
          {FILTERS.map((f) => (
            <FilterPill key={f.id} label={f.label} count={f.count} active={decision === f.id} onClick={() => setDecision(f.id)} />
          ))}
        </div>
      </div>

      <div className="list-scroll">
        <div className="list-stack">
          {list.map((p, i) => {
            const rec = REC_LABEL[p.decision];
            const mc = matchCounts(p, job);
            return (
              <div
                key={p.id}
                className="cand-card row-fade"
                data-active={selected === p.id}
                style={{ animationDelay: `${i * 28}ms` }}
                onClick={() => onSelect(p.id)}
              >
                <CandidateRow candidate={p} active={selected === p.id} />
                <div className="row-footer">
                  <div className="row-footer-top">
                    <Badge label={rec.label} variant={rec.variant} />
                    <span className="row-applied">Applied {p.applied}</span>
                  </div>
                  <div className="row-reqs">
                    <ReqMeter label="Must-have" n={mc.must} total={mc.mustTotal} />
                    <ReqMeter label="Preferred" n={mc.pref} total={mc.prefTotal} />
                  </div>
                </div>
              </div>
            );
          })}
          {list.length === 0 && (
            <div className="empty">
              <div className="ring"><Icon name="userSearch" size={20} /></div>
              <div className="t">No candidates yet</div>
              <div className="s">This job has no applicants matching your filters. Share the apply link from the Jobs tab.</div>
            </div>
          )}
        </div>
      </div>
    </section>
  );
}

/* ---------------- App ---------------- */
function App() {
  const [jobs, setJobs] = useState(JOBS);
  const [candidates, setCandidates] = useState(CANDIDATES);
  const [interviews, setInterviews] = useState(INTERVIEWS);
  const [currentJobId, setCurrentJobId] = useState('j1');
  const [tab, setTab] = useState('candidates');
  const [selected, setSelected] = useState('c1');
  const [compareOpen, setCompareOpen] = useState(false);

  const job = jobs.find((j) => j.id === currentJobId) || jobs[0] || null;
  const jobCandidates = useMemo(() => candidates.filter((c) => job && c.jobId === job.id), [candidates, job]);
  const jobInterviews = useMemo(() => interviews.filter((iv) => job && iv.jobId === job.id), [interviews, job]);
  const person = jobCandidates.find((c) => c.id === selected) || null;

  // keep a valid selection when the job (and its candidate set) changes
  useEffect(() => {
    if (!jobCandidates.some((c) => c.id === selected)) {
      setSelected(jobCandidates.length ? jobCandidates[0].id : null);
    }
  }, [currentJobId, jobCandidates.length]);

  const actions = {
    pickJob: (id) => { setCurrentJobId(id); setTab('candidates'); },
    gotoJob: (id) => { setCurrentJobId(id); },
    setStage: (id, stage) => setJobs((js) => js.map((j) => j.id === id ? { ...j, stage, status: 'open' } : j)),
    closeJob: (id) => setJobs((js) => js.map((j) => j.id === id ? { ...j, status: 'closed', stage: 'Hired' } : j)),
    reopenJob: (id) => setJobs((js) => js.map((j) => j.id === id ? { ...j, status: 'open', stage: 'Sourcing' } : j)),
    deleteJob: (id) => {
      setJobs((js) => {
        const left = js.filter((j) => j.id !== id);
        if (id === currentJobId) setCurrentJobId(left.length ? left[0].id : null);
        return left;
      });
      setCandidates((cs) => cs.filter((c) => c.jobId !== id));
      setInterviews((iv) => iv.filter((x) => x.jobId !== id));
    },
    addJob: (data) => {
      const id = 'j' + (Date.now() % 100000);
      const nj = {
        id, title: data.title, roleNoun: data.title, dept: data.dept || 'New', loc: data.loc || 'Remote',
        type: data.type || 'Full-time', description: data.description || '',
        mustHave: data.mustHave, preferred: data.preferred, niceToHave: data.niceToHave || [],
        stage: 'Sourcing', status: 'open', opened: '2026-06-25',
      };
      setJobs((js) => [nj, ...js]);
      setCurrentJobId(id);
      return nj;
    },
    addApplicant: (jobObj, form) => {
      const c = genCandidate(jobObj, Math.floor(Math.random() * 9000) + 100, Date.now() % 1000);
      const merged = {
        ...c,
        name: form.name || c.name,
        initials: form.name ? initialsOf(form.name) : c.initials,
        company: form.company || c.company,
        location: form.location || c.location,
        years: form.years != null ? form.years : c.years,
        applied: 'Jun 25', appliedDate: '2026-06-25',
      };
      setCandidates((cs) => [...cs, merged]);
      return merged;
    },
    rejectCandidate: (id) => setCandidates((cs) => cs.map((c) => c.id === id ? { ...c, decision: 'rejected', risk: c.risk === 'Low' ? 'Medium' : c.risk } : c)),
    scheduleInterview: (cand, slot) => {
      const iv = {
        id: 'iv' + Date.now(), candidateId: cand.id, jobId: cand.jobId,
        date: slot.date, start: slot.start, end: slot.end,
        kind: 'Interview · ' + cand.headline, mode: slot.mode || 'Video', panel: ['JD', 'RK'],
      };
      setInterviews((list) => [...list, iv]);
      return iv;
    },
  };

  const openCandidate = (id, jobId) => {
    if (jobId && jobId !== currentJobId) setCurrentJobId(jobId);
    setSelected(id);
    setTab('candidates');
  };

  let view;
  if (!job) {
    view = (
      <div className="view-scroll"><div className="view-inner"><div className="empty" style={{ paddingTop: 80 }}>
        <div className="ring"><Icon name="briefcase" size={20} /></div>
        <div className="t">No jobs yet</div>
        <div className="s">Create a job from the Jobs tab to start sourcing candidates.</div>
        <div style={{ marginTop: 16 }}><Button label="Go to Jobs" variant="primary" onClick={() => setTab('jobs')} /></div>
      </div></div></div>
    );
  } else if (tab === 'candidates') {
    view = (
      <main className="main">
        <ListPanel job={job} candidates={jobCandidates} selected={selected} onSelect={(id) => setSelected((s) => (s === id ? null : id))} />
        <DetailPanel person={person} job={job} onCompare={() => setCompareOpen(true)}
          onReject={() => actions.rejectCandidate(person.id)}
          onSchedule={(slot) => actions.scheduleInterview(person, slot)}
          onGoInterviews={() => setTab('interviews')} />
      </main>
    );
  } else if (tab === 'dashboard') view = <DashboardView job={job} candidates={jobCandidates} interviews={jobInterviews} onOpenCandidates={() => setTab('candidates')} onOpenCandidate={openCandidate} goTab={setTab} />;
  else if (tab === 'jobs') view = <JobsView jobs={jobs} currentJobId={currentJobId} candidates={candidates} interviews={interviews} actions={actions} />;
  else if (tab === 'pipeline') view = <PipelineView job={job} candidates={jobCandidates} onOpenCandidate={openCandidate} />;
  else if (tab === 'interviews') view = <InterviewsView job={job} candidates={candidates} interviews={jobInterviews} onOpenCandidate={openCandidate} />;
  else if (tab === 'analytics') view = <AnalyticsView job={job} candidates={jobCandidates} interviews={jobInterviews} />;
  else if (tab === 'settings') view = <SettingsView />;

  const counts = { candidates: jobCandidates.length, jobs: jobs.length, interviews: jobInterviews.length };

  return (
    <div className="app">
      <TopNav jobs={jobs} currentJobId={currentJobId} onPickJob={actions.pickJob} />
      <div className="body-row">
        <Sidebar tab={tab} onTab={setTab} counts={counts} />
        {view}
      </div>
      <Copilot person={tab === 'candidates' ? person : null} pool={jobCandidates} job={job} />
      <CompareModal open={compareOpen} initialId={selected} pool={jobCandidates} job={job} onClose={() => setCompareOpen(false)} />
    </div>
  );
}

Object.assign(window, { REC_LABEL });
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
