import { useState, useEffect } from 'react';
import { Link, useNavigate } from 'react-router-dom';
import Layout from '../components/Layout';
import { DashboardBanner } from '../lib/dashboardBanner';
import StatusBadge from '../components/StatusBadge';
import RequestForm from '../components/RequestForm';
import { supabase } from '../lib/supabase';
import { useAuth } from '../context/AuthContext';
import { readPageCache, writePageCache } from '../lib/pageCache';
import { withTimeout } from '../lib/withTimeout';
import { getCurrentVersionForTask, getDeadlineSourceSubmission } from '../lib/taskDeadlines';
import { formatDateOnly, fmtShortDate } from '../lib/dates';
import { createInitialSubmissionForRequest, createTaskForRequest, findOrCreateProject } from '../lib/requestSubmission';
import { sendEmail } from '../lib/email';
import { uploadFilesToRequestInfo, createTaskFolder } from '../lib/filebrowserFolders';
import SortTh from '../components/SortTh';
import { useSortable } from '../hooks/useSortable';
import FilterDropdown from '../components/FilterDropdown';

const ListViewIcon = () => <svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"><line x1="3" y1="4" x2="13" y2="4"/><line x1="3" y1="8" x2="13" y2="8"/><line x1="3" y1="12" x2="13" y2="12"/></svg>;
const GridViewIcon = () => <svg viewBox="0 0 16 16" width="14" height="14" fill="currentColor"><rect x="1" y="1" width="6" height="6" rx="1"/><rect x="9" y="1" width="6" height="6" rx="1"/><rect x="1" y="9" width="6" height="6" rx="1"/><rect x="9" y="9" width="6" height="6" rx="1"/></svg>;

export default function RequestsPage() {
  const { currentUser } = useAuth();
  const navigate = useNavigate();
  const isTeam = currentUser?.role === 'team';
  const isExternal = currentUser?.role === 'external';
  const isClient = currentUser?.role === 'client';

  // ── Shared state ───────────────────────────────────────────────────────
  const [projects, setProjects] = useState([]);
  const [tasks, setTasks] = useState([]);
  const [submissions, setSubmissions] = useState([]);
  const [loading, setLoading] = useState(() => {
    if (isTeam) return !readPageCache('team_requests');
    if (isExternal) return !readPageCache(`ext-requests:${currentUser?.id}`, 3 * 60_000);
    return true;
  });
  const [error, setError] = useState('');
  const [loadError, setLoadError] = useState(false);
  const [activeTab, setActiveTab] = useState('all');
  const [viewMode, setViewMode] = useState(() => localStorage.getItem('requestsViewMode') || 'list');
  const toggleView = () => setViewMode(v => { const n = v === 'list' ? 'grid' : 'list'; localStorage.setItem('requestsViewMode', n); return n; });

  // ── Team-only state ────────────────────────────────────────────────────
  const teamCached = isTeam ? readPageCache('team_requests') : null;
  const [companies, setCompanies] = useState(() => teamCached?.companies || []);
  const [invoices, setInvoices] = useState(() => teamCached?.invoices || []);
  const [invoiceItems, setInvoiceItems] = useState(() => teamCached?.invoiceItems || []);
  const [filterCompany, setFilterCompany] = useState('');
  const [filterUser, setFilterUser] = useState('');
  const { sortKey: reqSortKey, sortDir: reqSortDir, toggle: reqToggle, sort: reqSort } = useSortable('submitted_at', 'desc');
  const { sortKey: extSortKey, sortDir: extSortDir, toggle: extToggle, sort: extSort } = useSortable('submitted_at', 'desc');
  const { sortKey: clientSortKey, sortDir: clientSortDir, toggle: clientToggle, sort: clientSort } = useSortable('submitted_at', 'desc');
  const [showAddForm, setShowAddForm] = useState(false);
  const [addFormKey, setAddFormKey] = useState(0);
  const [addSaving, setAddSaving] = useState(false);
  const [addError, setAddError] = useState('');
  const [addRequestKey, setAddRequestKey] = useState(() => crypto.randomUUID());

  // ── External-only state ────────────────────────────────────────────────
  const extCacheKey = `ext-requests:${currentUser?.id}`;
  const extCached = isExternal ? readPageCache(extCacheKey, 3 * 60_000) : null;
  const [paidTaskIds, setPaidTaskIds] = useState(() => new Set(extCached?.paidTaskIds || []));
  const [filterProject, setFilterProject] = useState('');
  const [filterRequester, setFilterRequester] = useState('');

  // ── Client-only state ──────────────────────────────────────────────────
  const [clientInvoices, setClientInvoices] = useState([]);
  const [clientInvoiceItems, setClientInvoiceItems] = useState([]);

  useEffect(() => {
    if (isTeam) {
      async function loadTeam() {
        try {
          const [{ data: subs }, { data: t }, { data: p }, { data: co }, { data: inv }, { data: itemRows }] = await withTimeout(Promise.all([
            supabase.from('submissions').select('id, task_id, submitted_at, submitted_by, submitted_by_name, is_hot, service_type, deadline, version_number, type').order('submitted_at', { ascending: false }),
            supabase.from('tasks').select('id, title, status, current_version, project_id, assigned_name, assigned_to, invoiced, completed_at'),
            supabase.from('projects').select('id, name, status, company_id'),
            supabase.from('companies').select('id, name'),
            supabase.from('invoices').select('id, status'),
            supabase.from('invoice_items').select('task_id, invoice_id'),
          ]), 12000, 'Requests load');
          setSubmissions(subs || []);
          setTasks(t || []);
          setProjects(p || []);
          setCompanies(co || []);
          setInvoices(inv || []);
          setInvoiceItems(itemRows || []);
          writePageCache('team_requests', { submissions: subs || [], tasks: t || [], projects: p || [], companies: co || [], invoices: inv || [], invoiceItems: itemRows || [] });
        } catch (err) {
          console.error('Requests load failed:', err);
          setLoadError(true);
        } finally {
          setLoading(false);
        }
      }
      if (teamCached) {
        setSubmissions(teamCached.submissions || []);
        setTasks(teamCached.tasks || []);
        setProjects(teamCached.projects || []);
        setCompanies(teamCached.companies || []);
        setInvoices(teamCached.invoices || []);
        setInvoiceItems(teamCached.invoiceItems || []);
        setLoading(false);
      }
      loadTeam();
    } else if (isExternal) {
      async function loadExternal() {
        if (!currentUser?.id) { setLoading(false); return; }
        try {
          const [{ data: projectData }, { data: taskData }, { data: subData }, { data: paidItems }] = await withTimeout(
            Promise.all([
              supabase.from('projects').select('id, name, company_id, company:companies(id, name)').order('created_at', { ascending: false }),
              supabase.from('tasks').select('id, title, status, current_version, project_id, invoiced, completed_at').order('submitted_at', { ascending: false }),
              supabase.from('submissions').select('task_id, submitted_by_name, version_number, deadline, is_hot, service_type, submitted_at').order('submitted_at', { ascending: false }),
              supabase.from('subcontractor_invoice_items').select('task_id, invoice:subcontractor_invoices!inner(status)').eq('subcontractor_invoices.status', 'paid'),
            ]),
            15000, 'External requests load'
          );
          const paid = new Set((paidItems || []).filter(item => item.invoice?.status === 'paid' && item.task_id).map(item => item.task_id));
          setProjects(projectData || []);
          setTasks(taskData || []);
          setSubmissions(subData || []);
          setPaidTaskIds(paid);
          writePageCache(extCacheKey, { projects: projectData || [], tasks: taskData || [], submissions: subData || [], paidTaskIds: [...paid] });
          setError('');
        } catch (err) {
          console.error('External requests load failed:', err);
          setError(err.message || 'Failed to load requests.');
        } finally {
          setLoading(false);
        }
      }
      if (extCached) {
        setProjects(extCached.projects || []);
        setTasks(extCached.tasks || []);
        setSubmissions(extCached.submissions || []);
        setLoading(false);
      } else {
        loadExternal();
      }
    } else if (isClient) {
      async function loadClient() {
        try {
          const { data: mySubs } = await withTimeout(
            supabase.from('submissions').select('task_id, submitted_by_name, version_number, type').eq('submitted_by', currentUser.id).eq('type', 'initial'),
            10000, 'My submissions'
          );
          if (!mySubs || mySubs.length === 0) { setLoading(false); return; }
          const myTaskIds = mySubs.map(s => s.task_id);
          const [{ data: t }, { data: allSubs }, { data: inv }, { data: itemRows }] = await withTimeout(
            Promise.all([
              supabase.from('tasks').select('*, project:projects(id, name, created_at, status, company_id)').in('id', myTaskIds),
              supabase.from('submissions').select('task_id, submitted_by_name, version_number, type, service_type, deadline').in('task_id', myTaskIds).order('version_number'),
              supabase.from('invoices').select('id, status'),
              supabase.from('invoice_items').select('task_id, invoice_id').in('task_id', myTaskIds),
            ]),
            12000, 'My requests data'
          );
          const clientTasks = t || [];
          setTasks(clientTasks);
          setSubmissions(allSubs || []);
          setClientInvoices(inv || []);
          setClientInvoiceItems(itemRows || []);
          const projectMap = {};
          clientTasks.forEach(task => { const p = task.project; if (p && !projectMap[p.id]) projectMap[p.id] = { ...p }; });
          setProjects(Object.values(projectMap));
        } catch (err) {
          console.error('MyRequests load failed:', err);
          setLoadError(true);
        } finally {
          setLoading(false);
        }
      }
      loadClient();
    }
  }, [isTeam, isExternal, isClient, currentUser?.id]); // eslint-disable-line react-hooks/exhaustive-deps

  const handleAddRequest = async (formData, _files, existingProjects) => {
    if (addSaving) return;
    setAddSaving(true); setAddError('');
    try {
      const resolvedProject = await findOrCreateProject(formData.companyId, formData.project.trim(), existingProjects);
      if (!projects.some(p => p.id === resolvedProject.id)) setProjects(prev => [...prev, resolvedProject]);
      const { task } = await createTaskForRequest({ projectId: resolvedProject.id, title: formData.title.trim(), requestKey: addRequestKey });
      if (!task) throw new Error('Failed to create task.');
      const taskCompany = companies?.find(c => c.id === formData.companyId);
      createTaskFolder(taskCompany?.name, resolvedProject.name, formData.title.trim()).catch(() => {});
      const { submission: sub } = await createInitialSubmissionForRequest({
        taskId: task.id, requestKey: addRequestKey, isHot: formData.isHot,
        serviceType: formData.serviceType, deadline: formData.deadline,
        description: formData.description, submittedBy: formData.requestedBy,
        submittedByName: formData.requestedByName,
      });
      if (!sub) throw new Error('Failed to create submission.');
      const [{ data: newSubs }, { data: newTasks }] = await Promise.all([
        supabase.from('submissions').select('id, task_id, submitted_at, submitted_by, submitted_by_name, is_hot, service_type, deadline, version_number, type').order('submitted_at', { ascending: false }),
        supabase.from('tasks').select('id, title, status, current_version, project_id, assigned_name, assigned_to, invoiced, completed_at'),
      ]);
      setSubmissions(newSubs || []); setTasks(newTasks || []);
      setShowAddForm(false); setAddFormKey(k => k + 1); setAddRequestKey(crypto.randomUUID());
    } catch (err) {
      setAddError(err.message);
    } finally {
      setAddSaving(false);
    }
  };

  const handleClientRequest = async (formData, files, existingProjects) => {
    if (addSaving) return;
    setAddSaving(true); setAddError('');
    try {
      const selectedCompany = (currentUser?.companies?.length ? currentUser.companies : (currentUser?.company ? [currentUser.company] : [])).find(c => c.id === formData.companyId);
      const resolvedProject = await findOrCreateProject(formData.companyId, formData.project.trim(), existingProjects);
      const { task } = await createTaskForRequest({ projectId: resolvedProject.id, title: formData.title.trim(), requestKey: addRequestKey });
      if (!task) throw new Error('Failed to create task.');
      createTaskFolder(selectedCompany?.name, resolvedProject.name, formData.title.trim()).catch(() => {});
      const { submission } = await createInitialSubmissionForRequest({
        taskId: task.id, requestKey: addRequestKey, isHot: formData.isHot,
        serviceType: formData.serviceType, deadline: formData.deadline,
        description: formData.description, submittedBy: currentUser.id, submittedByName: currentUser.name,
      });
      if (submission && files.length > 0) {
        for (const file of files) {
          const path = `${task.id}/${Date.now()}_${file.name}`;
          const { data: uploaded, error: uploadError } = await supabase.storage.from('submissions').upload(path, file);
          if (uploadError) { await supabase.from('tasks').delete().eq('id', task.id); throw new Error(`Upload failed: ${uploadError.message}`); }
          if (uploaded) {
            const { error: fileErr } = await supabase.from('submission_files').insert({ submission_id: submission.id, name: file.name, storage_path: path, size: file.size });
            if (fileErr) { await supabase.from('tasks').delete().eq('id', task.id); throw new Error(`File record failed: ${fileErr.message}`); }
          }
        }
        uploadFilesToRequestInfo(files, selectedCompany?.name, resolvedProject.name, formData.title.trim()).catch(() => {});
      }
      sendEmail('new_request', 'hello@fourgebranding.com', {
        clientName: currentUser.name, clientEmail: currentUser.email,
        company: selectedCompany?.name || '', serviceType: formData.serviceType,
        projectName: formData.project, deadline: formData.deadline,
        description: formData.description, taskId: task.id,
      }).catch(() => {});
      const [{ data: newSubs }, { data: newTasks }] = await Promise.all([
        supabase.from('submissions').select('task_id, submitted_by_name, version_number, type').eq('submitted_by', currentUser.id).eq('type', 'initial'),
        supabase.from('tasks').select('id, title, status, current_version, project_id, project:projects(name, company_id), invoiced').order('submitted_at', { ascending: false }),
      ]);
      const myTaskIds = new Set((newSubs || []).map(s => s.task_id));
      const myTasks = (newTasks || []).filter(t => myTaskIds.has(t.id));
      setTasks(myTasks);
      setShowAddForm(false); setAddFormKey(k => k + 1); setAddRequestKey(crypto.randomUUID());
    } catch (err) {
      setAddError(err.message);
    } finally {
      setAddSaving(false);
    }
  };

  if (loading) return <Layout><p style={{ padding: 24, color: 'var(--text-muted)' }}>Loading...</p></Layout>;
  if (loadError) return <Layout><div style={{ padding: 24 }}><p style={{ color: 'var(--text-muted)', marginBottom: 12 }}>Failed to load. Check your connection and try again.</p><button className="btn btn-outline" onClick={() => window.location.reload()}>Retry</button></div></Layout>;

  // ── Team render ────────────────────────────────────────────────────────
  if (isTeam) {
    const requesterNames = [...new Set(submissions.map(s => s.submitted_by_name).filter(Boolean))].sort();
    const latestTaskGroups = tasks.map(task => {
      const taskSubs = submissions.filter(s => s.task_id === task.id);
      const deadlineSource = getDeadlineSourceSubmission(task, taskSubs);
      if (!deadlineSource) return null;
      const currentVersion = getCurrentVersionForTask(task, taskSubs);
      const latestGroup = taskSubs.filter(s => s.version_number === currentVersion);
      return { task, primary: deadlineSource, group: latestGroup };
    }).filter(Boolean);
    const filteredGroups = latestTaskGroups.filter(({ task }) => {
      const project = projects.find(p => p.id === task?.project_id);
      if (filterCompany && project?.company_id !== filterCompany) return false;
      if (filterProject && task?.project_id !== filterProject) return false;
      return true;
    }).sort((a, b) => Math.max(...b.group.map(s => new Date(s.submitted_at).getTime())) - Math.max(...a.group.map(s => new Date(s.submitted_at).getTime())));
    const byStatus = (s) => filteredGroups.filter(({ task }) => task?.status === s);
    const renderRow = ({ task, primary }) => {
      const project = projects.find(p => p.id === task?.project_id);
      const company = companies.find(co => co.id === project?.company_id);
      const serviceType = submissions.find(s => s.task_id === task?.id && s.type === 'initial')?.service_type
        || submissions.find(s => s.task_id === task?.id && s.service_type)?.service_type
        || primary.service_type
        || '—';
      return (
        <tr key={task.id} onClick={() => task && navigate(`/requests/${task.id}`)} style={{ cursor: task ? 'pointer' : 'default' }}>
          <td style={{ fontWeight: 400 }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
              <span>{task?.title || '—'}</span>
              <span style={{ color: 'var(--text-muted)' }}>{`R${String(primary.version_number ?? 0).padStart(2, '0')}`}</span>
              {primary.is_hot ? <span className="badge badge-needs_revision">HOT</span> : null}
            </div>
            <div style={{ fontSize: 12, color: 'var(--text-muted)', marginTop: 2 }}>{project?.name || '—'}</div>
          </td>
          <td style={{ color: 'var(--accent)' }}>{company ? <Link to={`/company/${company.id}`} className="table-link" style={{ color: 'var(--accent)' }} onClick={e => e.stopPropagation()}>{company.name}</Link> : 'No client'}</td>
          <td>{serviceType}</td>
          <td>{fmtShortDate(primary.deadline, 'Not specified')}</td>
          <td style={{ color: 'var(--text-muted)' }}>{fmtShortDate(task?.completed_at)}</td>
          <td><StatusBadge status={task?.status || 'not_started'} /></td>
        </tr>
      );
    };
    const teamTabs = [
      { id: 'all', label: 'All', groups: filteredGroups },
      { id: 'not_started', label: 'Not Started', groups: byStatus('not_started') },
      { id: 'in_progress', label: 'In Progress', groups: byStatus('in_progress') },
      { id: 'on_hold', label: 'On Hold', groups: byStatus('on_hold') },
      { id: 'client_review', label: 'In Review', groups: byStatus('client_review') },
      { id: 'client_approved', label: 'Approved', groups: byStatus('client_approved') },
      { id: 'invoiced', label: 'Invoiced', groups: byStatus('invoiced') },
      { id: 'paid', label: 'Paid', groups: byStatus('paid') },
    ];
    const rawGroups = teamTabs.find(t => t.id === activeTab)?.groups || [];
    const currentGroups = reqSort(rawGroups, ({ task, primary }, key) => {
      const project = projects.find(p => p.id === task?.project_id);
      const company = companies.find(co => co.id === project?.company_id);
      if (key === 'project') return project?.name || '';
      if (key === 'title') return task?.title || '';
      if (key === 'serviceType') return primary?.service_type || '';
      if (key === 'revision') return primary?.version_number ?? 0;
      if (key === 'client') return company?.name || '';
      if (key === 'deadline') return primary?.deadline || '';
      if (key === 'completed_at') return task?.completed_at || '';
      if (key === 'status') return task?.status || '';
      if (key === 'submitted_at') return primary?.submitted_at || '';
      return '';
    });

    const doneStatuses = new Set(['client_approved', 'invoiced', 'paid']);
    const teamActiveCount = latestTaskGroups.filter(({ task }) => !doneStatuses.has(task?.status)).length;
    const teamCompletedCount = latestTaskGroups.filter(({ task }) => doneStatuses.has(task?.status)).length;

    return (
      <Layout>
        <div className="page-header">
          <div className="page-header-left">
            <DashboardBanner />
            <div className="page-title dashboard-greeting">Requests</div>
            <div className="page-subtitle">{teamActiveCount} active &bull; {teamCompletedCount} completed</div>
          </div>
          <button className="btn btn-primary btn-sm" onClick={() => { setShowAddForm(s => !s); setAddError(''); }}>
            + Add Request
          </button>
        </div>

        {showAddForm && (
          <div style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.6)', backdropFilter: 'blur(4px)', zIndex: 1000, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 24 }} onClick={() => { setShowAddForm(false); setAddFormKey(k => k + 1); setAddError(''); }}>
            <div style={{ background: 'var(--card-bg)', borderRadius: 4, padding: 28, width: '100%', maxWidth: 560, border: '1px solid var(--border)', boxShadow: '0 24px 64px rgba(0,0,0,0.5)', maxHeight: '90vh', overflowY: 'auto' }} onClick={e => e.stopPropagation()}>
              <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', marginBottom: 20 }}>
                <div>
                  <div style={{ fontSize: 11, fontWeight: 400, textTransform: 'uppercase', letterSpacing: '0.5px', color: 'var(--text-muted)', marginBottom: 4 }}>New Request</div>
                  <div style={{ fontSize: 22, color: 'var(--text-primary)' }}>Add a request</div>
                </div>
                <button onClick={() => { setShowAddForm(false); setAddFormKey(k => k + 1); setAddError(''); }} style={{ background: 'none', border: 'none', color: 'var(--text-muted)', fontSize: 20, cursor: 'pointer', lineHeight: 1, padding: 4 }}>×</button>
              </div>
              <RequestForm
                key={addFormKey}
                companies={companies}
                currentUser={currentUser}
                showRequester={true}
                onSubmit={handleAddRequest}
                onCancel={() => { setShowAddForm(false); setAddFormKey(k => k + 1); setAddError(''); }}
                saving={addSaving}
                error={addError}
                submitLabel="Add Request"
              />
            </div>
          </div>
        )}

        <div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 16, flexShrink: 0, flexWrap: 'wrap' }}>
              {companies.length > 0 && (
                <select className="filter-select" style={{ width: 120 }} value={filterCompany} onChange={e => { setFilterCompany(e.target.value); setFilterProject(''); }}>
                  <option value="">All Companies</option>
                  {companies.map(co => <option key={co.id} value={co.id}>{co.name}</option>)}
                </select>
              )}
              {filterCompany && (() => { const co_projects = projects.filter(p => p.company_id === filterCompany); return co_projects.length > 0 ? (
                <select className="filter-select" style={{ width: 120 }} value={filterProject} onChange={e => setFilterProject(e.target.value)}>
                  <option value="">All Projects</option>
                  {co_projects.map(p => <option key={p.id} value={p.id}>{p.name}</option>)}
                </select>
              ) : null; })()}
              <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginLeft: 'auto' }}>
                <select className="filter-select" style={{ width: 120 }} value={activeTab} onChange={e => setActiveTab(e.target.value)}>
                  {teamTabs.map(t => <option key={t.id} value={t.id}>{t.label} ({t.groups.length})</option>)}
                </select>
                <button className="btn btn-outline btn-sm" onClick={toggleView} title={viewMode === 'list' ? 'Grid view' : 'List view'} style={{ padding: '5px 9px', lineHeight: 1, display: 'flex', alignItems: 'center' }}>
                  {viewMode === 'list' ? <GridViewIcon /> : <ListViewIcon />}
                </button>
              </div>
            </div>

            {submissions.length === 0 ? (
              <div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 13, color: 'var(--text-muted)' }}>No requests yet.</div>
            ) : filteredGroups.length === 0 ? (
              <div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 13, color: 'var(--text-muted)' }}>No matching requests.</div>
            ) : currentGroups.length === 0 ? (
              <div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 13, color: 'var(--text-muted)' }}>No {teamTabs.find(t => t.id === activeTab)?.label.toLowerCase()} requests.</div>
            ) : viewMode === 'grid' ? (
              <div style={{ flex: 1, overflowY: 'auto' }}>
                <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(240px, 1fr))', gap: 12 }}>
                  {currentGroups.map(({ task, primary }) => {
                    const project = projects.find(p => p.id === task?.project_id);
                    const company = companies.find(co => co.id === project?.company_id);
                    const serviceType = submissions.find(s => s.task_id === task?.id && s.type === 'initial')?.service_type || primary?.service_type || '—';
                    return (
                      <div key={task.id} className="grid-card" onClick={() => navigate(`/requests/${task.id}`)} style={{ padding: '14px 16px', border: '1px solid var(--border)', borderRadius: 6 }}>
                        <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 8, marginBottom: 4 }}>
                          <div style={{ minWidth: 0 }}>
                            <div style={{ fontWeight: 400, fontSize: 13, color: 'var(--text-primary)', marginBottom: 2 }}>{task?.title || '—'}</div>
                            <div style={{ fontSize: 12, color: 'var(--text-muted)' }}>{project?.name || '—'}</div>
                          </div>
                          <StatusBadge status={task?.status || 'not_started'} />
                        </div>
                        {company && <div style={{ fontSize: 12, color: 'var(--accent)', marginBottom: 6 }}>{company.name}</div>}
                        <div style={{ fontSize: 11, color: 'var(--text-muted)', display: 'flex', justifyContent: 'space-between' }}>
                          <span>{serviceType}</span>
                          <span>{fmtShortDate(primary?.deadline)}</span>
                        </div>
                      </div>
                    );
                  })}
                </div>
              </div>
            ) : (
              <div style={{ flex: 1, minHeight: 0, overflowY: 'auto', background: 'var(--card-bg)', borderRadius: 4, border: '1px solid var(--border)' }}>
                <table style={{ tableLayout: 'fixed', width: '100%' }}>
                  <colgroup>
                    <col style={{ width: '28%' }} />
                    <col style={{ width: '25%' }} />
                    <col style={{ width: '15%' }} />
                    <col style={{ width: '10%' }} />
                    <col style={{ width: '10%' }} />
                    <col style={{ width: '12%' }} />
                  </colgroup>
                  <thead>
                    <tr>
                      <SortTh col="title" sortKey={reqSortKey} sortDir={reqSortDir} onSort={reqToggle}>Name</SortTh>
                      <SortTh col="client" sortKey={reqSortKey} sortDir={reqSortDir} onSort={reqToggle}>Client</SortTh>
                      <SortTh col="serviceType" sortKey={reqSortKey} sortDir={reqSortDir} onSort={reqToggle}>Request Type</SortTh>
                      <SortTh col="deadline" sortKey={reqSortKey} sortDir={reqSortDir} onSort={reqToggle}>Deadline</SortTh>
                      <SortTh col="completed_at" sortKey={reqSortKey} sortDir={reqSortDir} onSort={reqToggle}>Approved</SortTh>
                      <SortTh col="status" sortKey={reqSortKey} sortDir={reqSortDir} onSort={reqToggle}>Status</SortTh>
                    </tr>
                  </thead>
                  <tbody>{currentGroups.map(group => renderRow(group))}</tbody>
                </table>
              </div>
            )}
      </Layout>
    );
  }

  // ── External render ────────────────────────────────────────────────────
  if (isExternal) {
    const latestTaskGroupsExt = tasks.map(task => {
      const taskSubs = submissions.filter(s => s.task_id === task.id);
      const deadlineSource = getDeadlineSourceSubmission(task, taskSubs);
      if (!deadlineSource) return null;
      const currentVersion = getCurrentVersionForTask(task, taskSubs);
      const latestGroup = taskSubs.filter(s => s.version_number === currentVersion);
      return { task, primary: deadlineSource, group: latestGroup };
    }).filter(Boolean);
    const projectNames = [...new Map(latestTaskGroupsExt.map(({ task }) => { const p = projects.find(proj => proj.id === task.project_id); return p ? [p.id, p] : null; }).filter(Boolean)).values()];
    const requesterNamesExt = [...new Set(submissions.map(s => s.submitted_by_name).filter(Boolean))].sort();
    const filteredGroupsExt = latestTaskGroupsExt.filter(({ task, group }) => {
      if (filterProject && task.project_id !== filterProject) return false;
      if (filterRequester && !group.some(s => s.submitted_by_name === filterRequester)) return false;
      return true;
    }).sort((a, b) => Math.max(...b.group.map(s => new Date(s.submitted_at).getTime())) - Math.max(...a.group.map(s => new Date(s.submitted_at).getTime())));
    const byStatusExt = (s) => filteredGroupsExt.filter(({ task }) => task?.status === s);
    const extTabs = [
      { id: 'all', label: 'All', groups: filteredGroupsExt },
      { id: 'not_started', label: 'Not Started', groups: byStatusExt('not_started') },
      { id: 'in_progress', label: 'In Progress', groups: byStatusExt('in_progress') },
      { id: 'on_hold', label: 'On Hold', groups: byStatusExt('on_hold') },
      { id: 'client_review', label: 'In Review', groups: byStatusExt('client_review') },
      { id: 'client_approved', label: 'Approved', groups: byStatusExt('client_approved') },
      { id: 'invoiced', label: 'Invoiced', groups: byStatusExt('invoiced') },
      { id: 'paid', label: 'Paid', groups: byStatusExt('paid') },
    ];
    const rawExtGroups = extTabs.find(t => t.id === activeTab)?.groups || [];
    const currentExtGroups = extSort(rawExtGroups, ({ task, primary }, key) => {
      const project = projects.find(p => p.id === task?.project_id);
      if (key === 'title') return task?.title || '';
      if (key === 'serviceType') return submissions.find(s => s.task_id === task?.id && s.service_type)?.service_type || primary?.service_type || '';
      if (key === 'revision') return primary?.version_number ?? 0;
      if (key === 'client') return project?.company?.name || '';
      if (key === 'deadline') return primary?.deadline || '';
      if (key === 'completed_at') return task?.completed_at || '';
      if (key === 'status') return task?.status || '';
      if (key === 'submitted_at') return primary?.submitted_at || '';
      return '';
    });
    const renderExtRow = ({ task, primary }) => {
      const project = projects.find(p => p.id === task?.project_id);
      const extServiceType = submissions.find(s => s.task_id === task?.id && s.service_type)?.service_type || primary.service_type || '—';
      return (
        <tr key={task.id} onClick={() => navigate(`/requests/${task.id}`)} style={{ cursor: 'pointer' }}>
          <td style={{ fontWeight: 400 }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
              <span>{task?.title || '—'}</span>
              <span style={{ color: 'var(--text-muted)' }}>{`R${String(primary.version_number ?? 0).padStart(2, '0')}`}</span>
              {primary.is_hot ? <span className="badge badge-needs_revision">HOT</span> : null}
            </div>
            <div style={{ fontSize: 12, color: 'var(--text-muted)', marginTop: 2 }}>{project?.name || '—'}</div>
          </td>
          <td style={{ color: 'var(--accent)' }}>{project?.company?.name || '—'}</td>
          <td>{extServiceType}</td>
          <td>{fmtShortDate(primary.deadline, 'Not specified')}</td>
          <td style={{ color: 'var(--text-muted)' }}>{fmtShortDate(task?.completed_at)}</td>
          <td><StatusBadge status={task?.status || 'not_started'} /></td>
        </tr>
      );
    };

    const doneStatusesExt = new Set(['client_approved', 'invoiced', 'paid']);
    const extActiveCount = latestTaskGroupsExt.filter(({ task }) => !doneStatusesExt.has(task?.status)).length;
    const extCompletedCount = latestTaskGroupsExt.filter(({ task }) => doneStatusesExt.has(task?.status)).length;

    return (
      <Layout>
        <div className="page-header">
          <div className="page-header-left">
            <DashboardBanner />
            <div className="page-title dashboard-greeting">Requests</div>
            <div className="page-subtitle">{extActiveCount} active &bull; {extCompletedCount} completed</div>
          </div>
        </div>

        <div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 16, flexShrink: 0, flexWrap: 'wrap' }}>
          {projectNames.length > 0 && (
            <select className="filter-select" style={{ width: 120 }} value={filterProject} onChange={e => setFilterProject(e.target.value)}>
              <option value="">All Projects</option>
              {projectNames.map(p => <option key={p.id} value={p.id}>{p.name}</option>)}
            </select>
          )}
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginLeft: 'auto' }}>
            <select className="filter-select" style={{ width: 120 }} value={activeTab} onChange={e => setActiveTab(e.target.value)}>
              {extTabs.map(t => <option key={t.id} value={t.id}>{t.label} ({t.groups.length})</option>)}
            </select>
            <button className="btn btn-outline btn-sm" onClick={toggleView} title={viewMode === 'list' ? 'Grid view' : 'List view'} style={{ padding: '5px 9px', lineHeight: 1, display: 'flex', alignItems: 'center' }}>
              {viewMode === 'list' ? <GridViewIcon /> : <ListViewIcon />}
            </button>
          </div>
        </div>

        {submissions.length === 0 ? (
          <div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 13, color: 'var(--text-muted)' }}>No requests yet.</div>
        ) : filteredGroupsExt.length === 0 ? (
          <div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 13, color: 'var(--text-muted)' }}>No matching requests.</div>
        ) : currentExtGroups.length === 0 ? (
          <div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 13, color: 'var(--text-muted)' }}>No {extTabs.find(t => t.id === activeTab)?.label.toLowerCase()} requests.</div>
        ) : viewMode === 'grid' ? (
          <div style={{ flex: 1, overflowY: 'auto' }}>
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(240px, 1fr))', gap: 12 }}>
              {currentExtGroups.map(({ task, primary }) => {
                const project = projects.find(p => p.id === task?.project_id);
                const extServiceType = submissions.find(s => s.task_id === task?.id && s.service_type)?.service_type || primary?.service_type || '—';
                return (
                  <div key={task.id} className="grid-card" onClick={() => navigate(`/requests/${task.id}`)} style={{ padding: '14px 16px', border: '1px solid var(--border)', borderRadius: 6 }}>
                    <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 8, marginBottom: 4 }}>
                      <div style={{ minWidth: 0 }}>
                        <div style={{ fontWeight: 400, fontSize: 13, color: 'var(--text-primary)', marginBottom: 2 }}>{task?.title || '—'}</div>
                        <div style={{ fontSize: 12, color: 'var(--text-muted)' }}>{project?.name || '—'}</div>
                      </div>
                      <StatusBadge status={task?.status || 'not_started'} />
                    </div>
                    {project?.company?.name && <div style={{ fontSize: 12, color: 'var(--accent)', marginBottom: 6 }}>{project.company.name}</div>}
                    <div style={{ fontSize: 11, color: 'var(--text-muted)', display: 'flex', justifyContent: 'space-between' }}>
                      <span>{extServiceType}</span>
                      <span>{fmtShortDate(primary?.deadline)}</span>
                    </div>
                  </div>
                );
              })}
            </div>
          </div>
        ) : (
          <div style={{ flex: 1, minHeight: 0, overflowY: 'auto', background: 'var(--card-bg)', borderRadius: 4, border: '1px solid var(--border)' }}>
            <table style={{ tableLayout: 'fixed', width: '100%' }}>
              <colgroup>
                <col style={{ width: '28%' }} />
                <col style={{ width: '25%' }} />
                <col style={{ width: '15%' }} />
                <col style={{ width: '10%' }} />
                <col style={{ width: '10%' }} />
                <col style={{ width: '12%' }} />
              </colgroup>
              <thead>
                <tr>
                  <SortTh col="title" sortKey={extSortKey} sortDir={extSortDir} onSort={extToggle}>Name</SortTh>
                  <SortTh col="client" sortKey={extSortKey} sortDir={extSortDir} onSort={extToggle}>Client</SortTh>
                  <SortTh col="serviceType" sortKey={extSortKey} sortDir={extSortDir} onSort={extToggle}>Request Type</SortTh>
                  <SortTh col="deadline" sortKey={extSortKey} sortDir={extSortDir} onSort={extToggle}>Deadline</SortTh>
                  <SortTh col="completed_at" sortKey={extSortKey} sortDir={extSortDir} onSort={extToggle}>Approved</SortTh>
                  <SortTh col="status" sortKey={extSortKey} sortDir={extSortDir} onSort={extToggle}>Status</SortTh>
                </tr>
              </thead>
              <tbody>{currentExtGroups.map(group => renderExtRow(group))}</tbody>
            </table>
          </div>
        )}
        {error && <div style={{ color: 'var(--danger)', marginTop: 16, fontSize: 13 }}>{error}</div>}
      </Layout>
    );
  }

  // ── Client render ──────────────────────────────────────────────────────
  const clientCompanies = isClient
    ? (currentUser?.companies?.length ? currentUser.companies : (currentUser?.company ? [currentUser.company] : [])).slice().sort((a, b) => a.name.localeCompare(b.name))
    : [];
  const clientRequesterNames = [...new Set(submissions.filter(s => s.type === 'initial').map(s => s.submitted_by_name).filter(Boolean))].sort();
  const clientFilteredTasks = tasks.filter(task => {
    if (filterCompany && task.project?.company_id !== filterCompany) return false;
    if (filterProject && task.project?.id !== filterProject) return false;
    return true;
  });
  const byStatusClientFiltered = (s) => clientFilteredTasks.filter(t => t.status === s);
  const clientTabs = [
    { id: 'all', label: 'All', tasks: clientFilteredTasks },
    { id: 'not_started', label: 'Not Started', tasks: byStatusClientFiltered('not_started') },
    { id: 'in_progress', label: 'In Progress', tasks: byStatusClientFiltered('in_progress') },
    { id: 'on_hold', label: 'On Hold', tasks: byStatusClientFiltered('on_hold') },
    { id: 'client_review', label: 'In Review', tasks: byStatusClientFiltered('client_review') },
    { id: 'client_approved', label: 'Approved', tasks: byStatusClientFiltered('client_approved') },
    { id: 'invoiced', label: 'Invoiced', tasks: byStatusClientFiltered('invoiced') },
    { id: 'paid', label: 'Paid', tasks: byStatusClientFiltered('paid') },
  ];
  const rawClientTasks = clientTabs.find(t => t.id === activeTab)?.tasks || [];
  const currentClientTasks = clientSort(rawClientTasks, (task, key) => {
    if (key === 'title') return task?.title || '';
    if (key === 'serviceType') return submissions.find(s => s.task_id === task?.id && s.type === 'initial')?.service_type || '';
    if (key === 'revision') return task?.current_version ?? 0;
    if (key === 'client') return (clientCompanies.find(c => c.id === task.project?.company_id))?.name || '';
    if (key === 'deadline') return submissions.find(s => s.task_id === task?.id && s.type === 'initial')?.deadline || '';
    if (key === 'completed_at') return task?.completed_at || '';
    if (key === 'status') return task?.status || '';
    if (key === 'submitted_at') return task?.submitted_at || '';
    return '';
  });

  return (
    <Layout>
      <div className="page-header" style={{ flexShrink: 0 }}>
        <div className="page-header-left">
          <DashboardBanner />
          <div className="page-title dashboard-greeting">Requests</div>
          <div className="page-subtitle">{clientFilteredTasks.filter(t => !['client_approved','invoiced','paid'].includes(t.status)).length} active &bull; {clientFilteredTasks.filter(t => ['client_approved','invoiced','paid'].includes(t.status)).length} completed</div>
        </div>
        <button className="btn btn-primary btn-sm" onClick={() => { setShowAddForm(s => !s); setAddError(''); }}>
          + New Request
        </button>
      </div>

      {showAddForm && (
        <div style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.6)', backdropFilter: 'blur(4px)', zIndex: 1000, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 24 }} onClick={() => { setShowAddForm(false); setAddFormKey(k => k + 1); setAddError(''); }}>
          <div style={{ background: 'var(--card-bg)', borderRadius: 4, padding: 28, width: '100%', maxWidth: 560, border: '1px solid var(--border)', boxShadow: '0 24px 64px rgba(0,0,0,0.5)', maxHeight: '90vh', overflowY: 'auto' }} onClick={e => e.stopPropagation()}>
            <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', marginBottom: 20 }}>
              <div>
                <div style={{ fontSize: 11, fontWeight: 400, textTransform: 'uppercase', letterSpacing: '0.5px', color: 'var(--text-muted)', marginBottom: 4 }}>New Request</div>
                <div style={{ fontSize: 22, color: 'var(--text-primary)' }}>Submit a request</div>
              </div>
              <button onClick={() => { setShowAddForm(false); setAddFormKey(k => k + 1); setAddError(''); }} style={{ background: 'none', border: 'none', color: 'var(--text-muted)', fontSize: 20, cursor: 'pointer', lineHeight: 1, padding: 4 }}>×</button>
            </div>
            <RequestForm
              key={addFormKey}
              companies={clientCompanies}
              initialCompanyId={clientCompanies[0]?.id || ''}
              showRequester={false}
              onSubmit={handleClientRequest}
              onCancel={() => { setShowAddForm(false); setAddFormKey(k => k + 1); setAddError(''); }}
              saving={addSaving}
              error={addError}
              submitLabel="Submit Request"
            />
          </div>
        </div>
      )}

      <div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 16, flexShrink: 0, flexWrap: 'wrap' }}>
            {clientCompanies.length > 1 && (
              <select className="filter-select" style={{ width: 120 }} value={filterCompany} onChange={e => { setFilterCompany(e.target.value); setFilterProject(''); }}>
                <option value="">All Companies</option>
                {clientCompanies.map(c => <option key={c.id} value={c.id}>{c.name}</option>)}
              </select>
            )}
            {filterCompany && (() => { const co_projects = projects.filter(p => p.company_id === filterCompany); return co_projects.length > 0 ? (
              <select className="filter-select" style={{ width: 120 }} value={filterProject} onChange={e => setFilterProject(e.target.value)}>
                <option value="">All Projects</option>
                {co_projects.map(p => <option key={p.id} value={p.id}>{p.name}</option>)}
              </select>
            ) : null; })()}
            <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginLeft: 'auto' }}>
              <select className="filter-select" style={{ width: 120 }} value={activeTab} onChange={e => setActiveTab(e.target.value)}>
                {clientTabs.map(t => <option key={t.id} value={t.id}>{t.label} ({t.tasks.length})</option>)}
              </select>
              <button className="btn btn-outline btn-sm" onClick={toggleView} title={viewMode === 'list' ? 'Grid view' : 'List view'} style={{ padding: '5px 9px', lineHeight: 1, display: 'flex', alignItems: 'center' }}>
                {viewMode === 'list' ? <GridViewIcon /> : <ListViewIcon />}
              </button>
            </div>
          </div>

          {tasks.length === 0 ? (
            <div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 13, color: 'var(--text-muted)' }}>No requests yet.</div>
          ) : currentClientTasks.length === 0 ? (
            <div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 13, color: 'var(--text-muted)' }}>No {clientTabs.find(t => t.id === activeTab)?.label.toLowerCase()} requests.</div>
          ) : viewMode === 'grid' ? (
            <div style={{ flex: 1, overflowY: 'auto' }}>
              <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(240px, 1fr))', gap: 12 }}>
                {currentClientTasks.map(task => {
                  const clientSub = submissions.find(s => s.task_id === task.id && s.type === 'initial');
                  const clientCo = clientCompanies.find(c => c.id === task.project?.company_id);
                  return (
                    <div key={task.id} className="grid-card" onClick={() => navigate(`/requests/${task.id}`)} style={{ padding: '14px 16px', border: '1px solid var(--border)', borderRadius: 6 }}>
                      <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 8, marginBottom: 4 }}>
                        <div style={{ minWidth: 0 }}>
                          <div style={{ fontWeight: 400, fontSize: 13, color: 'var(--text-primary)', marginBottom: 2 }}>{task.title}</div>
                          <div style={{ fontSize: 12, color: 'var(--text-muted)' }}>{task.project?.name || '—'}</div>
                        </div>
                        <StatusBadge status={task.status} />
                      </div>
                      {clientCo && <div style={{ fontSize: 12, color: 'var(--accent)', marginBottom: 6 }}>{clientCo.name}</div>}
                      <div style={{ fontSize: 11, color: 'var(--text-muted)', display: 'flex', justifyContent: 'space-between' }}>
                        <span>{clientSub?.service_type || '—'}</span>
                        <span>{fmtShortDate(clientSub?.deadline)}</span>
                      </div>
                    </div>
                  );
                })}
              </div>
            </div>
          ) : (
            <div style={{ flex: 1, minHeight: 0, overflowY: 'auto', background: 'var(--card-bg)', borderRadius: 4, border: '1px solid var(--border)' }}>
              <table style={{ tableLayout: 'fixed', width: '100%' }}>
                <colgroup>
                  <col style={{ width: '28%' }} />
                  <col style={{ width: '25%' }} />
                  <col style={{ width: '15%' }} />
                  <col style={{ width: '10%' }} />
                  <col style={{ width: '10%' }} />
                  <col style={{ width: '12%' }} />
                </colgroup>
                <thead>
                  <tr>
                    <SortTh col="title" sortKey={clientSortKey} sortDir={clientSortDir} onSort={clientToggle}>Name</SortTh>
                    <SortTh col="client" sortKey={clientSortKey} sortDir={clientSortDir} onSort={clientToggle}>Client</SortTh>
                    <SortTh col="serviceType" sortKey={clientSortKey} sortDir={clientSortDir} onSort={clientToggle}>Request Type</SortTh>
                    <SortTh col="deadline" sortKey={clientSortKey} sortDir={clientSortDir} onSort={clientToggle}>Deadline</SortTh>
                    <SortTh col="completed_at" sortKey={clientSortKey} sortDir={clientSortDir} onSort={clientToggle}>Approved</SortTh>
                    <SortTh col="status" sortKey={clientSortKey} sortDir={clientSortDir} onSort={clientToggle}>Status</SortTh>
                  </tr>
                </thead>
                <tbody>
                  {currentClientTasks.map(task => {
                    const clientSub = submissions.find(s => s.task_id === task.id && s.type === 'initial');
                    const clientCo = clientCompanies.find(c => c.id === task.project?.company_id);
                    return (
                    <tr key={task.id} onClick={() => navigate(`/requests/${task.id}`)} style={{ cursor: 'pointer' }}>
                      <td style={{ fontWeight: 400 }}>
                        <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
                          <span>{task.title}</span>
                          <span style={{ color: 'var(--text-muted)' }}>{`R${String(task.current_version || 0).padStart(2, '0')}`}</span>
                        </div>
                        <div style={{ fontSize: 12, color: 'var(--text-muted)', marginTop: 2 }}>{task.project?.name || '—'}</div>
                      </td>
                      <td style={{ color: 'var(--accent)' }}>{clientCo?.name || '—'}</td>
                      <td>{clientSub?.service_type || '—'}</td>
                      <td>{fmtShortDate(clientSub?.deadline)}</td>
                      <td style={{ color: 'var(--text-muted)' }}>{fmtShortDate(task.completed_at)}</td>
                      <td><StatusBadge status={task.status} /></td>
                    </tr>
                    );
                  })}
                </tbody>
              </table>
            </div>
          )}
    </Layout>
  );
}
