<script setup lang="ts">
type TabId = "communications" | "documents";
type CalendarView = "day" | "week" | "month" | "year" | "agenda";
type SortMode = "name" | "lastContact";
type PeopleLeftMode = "contacts" | "calendar";
type PeopleSortMode = "name" | "lastContact" | "company" | "country";

type FeedCard = {
  id: string;
  at: string;
  contact: string;
  text: string;
  proposal: {
    title: string;
    details: string[];
    key: "create_followup" | "open_comm" | "call" | "draft_message" | "run_summary" | "prepare_question";
  };
  decision: "pending" | "accepted" | "rejected";
  decisionNote?: string;
};

type Contact = {
  id: string;
  name: string;
  avatar: string;
  company: string;
  country: string;
  location: string;
  channels: string[];
  lastContactAt: string;
  description: string;
};

type CalendarEvent = {
  id: string;
  title: string;
  start: string;
  end: string;
  contact: string;
  note: string;
};

type CommItem = {
  id: string;
  at: string;
  contact: string;
  channel: "Telegram" | "WhatsApp" | "Instagram" | "Phone" | "Email";
  kind: "message" | "call";
  direction: "in" | "out";
  text: string;
  duration?: string;
  transcript?: string[];
};

type CommPin = {
  id: string;
  contact: string;
  text: string;
};

type Deal = {
  id: string;
  contact: string;
  title: string;
  company: string;
  stage: string;
  amount: string;
  nextStep: string;
  summary: string;
};

type WorkspaceDocument = {
  id: string;
  title: string;
  type: "Regulation" | "Playbook" | "Policy" | "Template";
  owner: string;
  scope: string;
  updatedAt: string;
  summary: string;
  body: string;
};

const tabs: { id: TabId; label: string }[] = [
  { id: "communications", label: "Workspace" },
  { id: "documents", label: "Documents" },
];

const selectedTab = ref<TabId>("communications");

function dayKey(date: Date) {
  const y = date.getFullYear();
  const m = String(date.getMonth() + 1).padStart(2, "0");
  const d = String(date.getDate()).padStart(2, "0");
  return `${y}-${m}-${d}`;
}

function formatDay(iso: string) {
  return new Intl.DateTimeFormat("en-GB", {
    day: "2-digit",
    month: "short",
    year: "numeric",
  }).format(new Date(iso));
}

function formatTime(iso: string) {
  return new Intl.DateTimeFormat("en-GB", {
    hour: "2-digit",
    minute: "2-digit",
  }).format(new Date(iso));
}

function formatThreadTime(iso: string) {
  return new Intl.DateTimeFormat("en-GB", {
    hour: "2-digit",
    minute: "2-digit",
    hour12: false,
  })
    .format(new Date(iso))
    .replace(":", ".");
}

function formatStamp(iso: string) {
  return new Intl.DateTimeFormat("en-GB", {
    day: "2-digit",
    month: "short",
    hour: "2-digit",
    minute: "2-digit",
  }).format(new Date(iso));
}

function atOffset(days: number, hour: number, minute: number) {
  const d = new Date();
  d.setDate(d.getDate() + days);
  d.setHours(hour, minute, 0, 0);
  return d.toISOString();
}

function inMinutes(minutes: number) {
  const d = new Date();
  d.setMinutes(d.getMinutes() + minutes, 0, 0);
  return d.toISOString();
}

function endAfter(startIso: string, minutes: number) {
  const d = new Date(startIso);
  d.setMinutes(d.getMinutes() + minutes);
  return d.toISOString();
}

const feedCards = ref<FeedCard[]>([
  {
    id: "f1",
    at: atOffset(0, 9, 35),
    contact: "Anna Meyer",
    text: "I analyzed Anna Meyer's latest activity: after a demo, the decision window is usually open for 1-2 hours. I suggest scheduling a follow-up immediately to keep momentum.",
    proposal: {
      title: "Add event to calendar",
      details: [
        "Contact: Anna Meyer",
        "Start: 30 minutes from now",
        "Duration: 30 minutes",
      ],
      key: "create_followup",
    },
    decision: "pending",
  },
  {
    id: "f2",
    at: atOffset(0, 10, 8),
    contact: "Murat Ali",
    text: "I found that Murat Ali gave 3 quick replies in a row over the last hour. I suggest moving to a short call now while engagement is high.",
    proposal: {
      title: "Start a call and open chat",
      details: [
        "Contact: Murat Ali",
        "Channel: Phone",
        "After action: open the communication thread for this contact",
      ],
      key: "call",
    },
    decision: "pending",
  },
]);

const contacts = ref<Contact[]>([
  {
    id: "c1",
    name: "Anna Meyer",
    avatar: "https://randomuser.me/api/portraits/women/44.jpg",
    company: "Nordline GmbH",
    country: "Germany",
    location: "Berlin",
    channels: ["Telegram", "Phone", "Email"],
    lastContactAt: atOffset(-0, 10, 20),
    description: "Decision owner for procurement. Prefers short, concrete updates with clear deadlines.\n\nBest pattern: one clear question per message, then one explicit next step.\n\nRisk: if timeline question is delayed, decision date keeps slipping.",
  },
  {
    id: "c2",
    name: "Murat Ali",
    avatar: "https://randomuser.me/api/portraits/men/32.jpg",
    company: "Connect FZCO",
    country: "UAE",
    location: "Dubai",
    channels: ["WhatsApp", "Instagram", "Phone", "Email"],
    lastContactAt: atOffset(-1, 18, 10),
    description: "High activity in chat, fast response cycle.\n\nNeeds legal path clarity and explicit owner from his side.\n\nBest move: in next call, lock legal owner and target signature date.",
  },
  {
    id: "c3",
    name: "Ilya Petroff",
    avatar: "https://randomuser.me/api/portraits/men/18.jpg",
    company: "Volta Tech",
    country: "Armenia",
    location: "Yerevan",
    channels: ["Email", "Phone"],
    lastContactAt: atOffset(-1, 11, 12),
    description: "Early-stage lead. Interested, but wants structured onboarding before commercial details.\n\nBest move: send concise onboarding plan + 2 time slots for intro session.",
  },
  {
    id: "c4",
    name: "Carlos Rivera",
    avatar: "https://randomuser.me/api/portraits/men/65.jpg",
    company: "BluePort",
    country: "Spain",
    location: "Barcelona",
    channels: ["WhatsApp", "Email"],
    lastContactAt: atOffset(-3, 14, 35),
    description: "Pilot interest for two teams. Focus on rollout timeline and ownership per team.\n\nBest move: propose phased pilot with weekly checkpoints.",
  },
  {
    id: "c5",
    name: "Daria Ivanova",
    avatar: "https://randomuser.me/api/portraits/women/22.jpg",
    company: "Skyline Trade",
    country: "Kazakhstan",
    location: "Almaty",
    channels: ["Telegram", "Phone"],
    lastContactAt: atOffset(-4, 16, 10),
    description: "Commercial discussion is blocked by ROI framing.\n\nBest move: provide short ROI model with three measurable outcomes.",
  },
  {
    id: "c6",
    name: "Ethan Moore",
    avatar: "https://randomuser.me/api/portraits/men/76.jpg",
    company: "NorthBridge",
    country: "USA",
    location: "Austin",
    channels: ["Email", "Phone"],
    lastContactAt: atOffset(-5, 12, 45),
    description: "Prefers stable weekly cadence and structured updates.\n\nBest move: fixed weekly summary + one priority ask per cycle.",
  },
]);

const calendarEvents = ref<CalendarEvent[]>([
  {
    id: "e1",
    title: "Anna follow-up",
    start: inMinutes(12),
    end: endAfter(inMinutes(12), 30),
    contact: "Anna Meyer",
    note: "Confirm decision date and next owner.",
  },
  {
    id: "e2",
    title: "Murat contract call",
    start: atOffset(2, 16, 30),
    end: endAfter(atOffset(2, 16, 30), 30),
    contact: "Murat Ali",
    note: "Lock legal owner and signing target.",
  },
  {
    id: "e3",
    title: "Ilya discovery",
    start: atOffset(3, 11, 0),
    end: endAfter(atOffset(3, 11, 0), 30),
    contact: "Ilya Petroff",
    note: "Qualify onboarding readiness.",
  },
  {
    id: "e4",
    title: "Internal sync",
    start: atOffset(0, 9, 0),
    end: endAfter(atOffset(0, 9, 0), 30),
    contact: "Team",
    note: "Align next actions across accounts.",
  },
  {
    id: "e5",
    title: "BluePort intro",
    start: atOffset(4, 13, 0),
    end: endAfter(atOffset(4, 13, 0), 30),
    contact: "Carlos Rivera",
    note: "Check pilot scope and timeline.",
  },
]);

const commItems = ref<CommItem[]>([
  {
    id: "m1",
    at: atOffset(0, 9, 20),
    contact: "Anna Meyer",
    channel: "Telegram",
    kind: "message",
    direction: "in",
    text: "Can you share final pricing today?",
  },
  {
    id: "m2",
    at: atOffset(0, 9, 22),
    contact: "Anna Meyer",
    channel: "Telegram",
    kind: "message",
    direction: "out",
    text: "Yes, sending after demo.",
  },
  {
    id: "m3",
    at: atOffset(0, 10, 0),
    contact: "Anna Meyer",
    channel: "Phone",
    kind: "call",
    direction: "out",
    text: "Quick sync call",
    duration: "14m",
    transcript: [
      "Anna: We can review pricing today, but I need one clear next step.",
      "You: Agreed. I will send the final version right after this call.",
      "Anna: Perfect. Add a follow-up tomorrow morning.",
    ],
  },
  {
    id: "m4",
    at: atOffset(-1, 15, 5),
    contact: "Murat Ali",
    channel: "WhatsApp",
    kind: "message",
    direction: "in",
    text: "Need to shift call by one day.",
  },
  {
    id: "m5",
    at: atOffset(-1, 15, 8),
    contact: "Murat Ali",
    channel: "WhatsApp",
    kind: "message",
    direction: "out",
    text: "Works. Let us do 12:00 tomorrow.",
  },
  {
    id: "m6",
    at: atOffset(-1, 18, 10),
    contact: "Murat Ali",
    channel: "Phone",
    kind: "call",
    direction: "in",
    text: "Contract call",
    duration: "9m",
    transcript: [
      "Murat: We can move forward if legal owner is confirmed today.",
      "You: Understood. I will lock owner and send the timeline.",
      "Murat: Then we target signature this week.",
    ],
  },
  {
    id: "m9",
    at: atOffset(-1, 13, 40),
    contact: "Murat Ali",
    channel: "Instagram",
    kind: "message",
    direction: "in",
    text: "Sent details in DM, can we align tomorrow?",
  },
  {
    id: "m7",
    at: atOffset(-1, 11, 12),
    contact: "Ilya Petroff",
    channel: "Email",
    kind: "message",
    direction: "in",
    text: "Interested in pilot, what are next steps?",
  },
  {
    id: "m8",
    at: atOffset(-1, 12, 0),
    contact: "Ilya Petroff",
    channel: "Phone",
    kind: "call",
    direction: "out",
    text: "Missed callback",
    duration: "-",
    transcript: [
      "No full transcript available. Call was not connected.",
    ],
  },
]);

const commPins = ref<CommPin[]>([
  {
    id: "cp-1",
    contact: "Anna Meyer",
    text: "First lock the decision date, then send the final offer.",
  },
  {
    id: "cp-2",
    contact: "Anna Meyer",
    text: "A short follow-up is needed no later than 30 minutes after the demo.",
  },
  {
    id: "cp-3",
    contact: "Murat Ali",
    text: "In every update, confirm the legal owner on the client side.",
  },
  {
    id: "cp-4",
    contact: "Ilya Petroff",
    text: "Work through a structured onboarding plan, not pricing first.",
  },
]);

const deals = ref<Deal[]>([
  {
    id: "d1",
    contact: "Anna Meyer",
    title: "Nordline pilot",
    company: "Nordline GmbH",
    stage: "Negotiation",
    amount: "$28,000",
    nextStep: "Send post-demo offer within 30 minutes",
    summary: "Active thread, fast feedback, high close probability this week.",
  },
  {
    id: "d2",
    contact: "Murat Ali",
    title: "Connect annual",
    company: "Connect FZCO",
    stage: "Legal review",
    amount: "$74,000",
    nextStep: "Lock legal owner and expected sign date",
    summary: "Strong engagement in chat and calls, pending legal alignment.",
  },
  {
    id: "d3",
    contact: "Ilya Petroff",
    title: "Volta onboarding",
    company: "Volta Tech",
    stage: "Discovery",
    amount: "$12,000",
    nextStep: "Offer two onboarding slots for tomorrow",
    summary: "Early stage interest, needs concise onboarding plan.",
  },
]);

const documents = ref<WorkspaceDocument[]>([
  {
    id: "doc-1",
    title: "Outbound cadence v1",
    type: "Regulation",
    owner: "Revenue Ops",
    scope: "All B2B accounts",
    updatedAt: atOffset(-1, 10, 0),
    summary: "Unified sequence for first touch, follow-up, and qualification.",
    body: "## Goal\nMove a new contact to the first qualified call within 5 business days.\n\n## Base sequence\n- Day 0: first message in the primary channel.\n- Day 1: short follow-up with one clear ask.\n- Day 3: second follow-up + alternate channel.\n- Day 5: final ping and move to \"later\".\n\n## Rules\n- Always keep one explicit next step in each message.\n- Avoid long text walls.\n- After each reply, update context in the contact card.",
  },
  {
    id: "doc-2",
    title: "Discovery call playbook",
    type: "Playbook",
    owner: "Sales Lead",
    scope: "Discovery calls",
    updatedAt: atOffset(-2, 12, 15),
    summary: "Call structure, mandatory questions, and outcome logging format.",
    body: "## Structure\n1. Context check (2 min)\n2. Current pain (8 min)\n3. Success criteria (6 min)\n4. Next step lock (4 min)\n\n## Mandatory outcomes\n- Confirmed business owner\n- Confirmed decision timeline\n- Confirmed next meeting date\n\n## Notes format\nAlways log: pain, impact, owner, ETA, risks.",
  },
  {
    id: "doc-3",
    title: "AI assistant operating policy",
    type: "Policy",
    owner: "Founders",
    scope: "AI recommendations and automations",
    updatedAt: atOffset(-3, 9, 40),
    summary: "What actions AI can suggest and what requires explicit approval.",
    body: "## Allowed without approval\n- Draft message suggestions\n- Calendar proposal suggestions\n- Conversation summaries\n\n## Requires explicit approval\n- Sending a message to an external contact\n- Creating a calendar event\n- Changing deal stage\n\n## Logging\nEvery AI action must leave a short trace in the feed.",
  },
  {
    id: "doc-4",
    title: "Post-call follow-up template",
    type: "Template",
    owner: "Enablement",
    scope: "Any completed client call",
    updatedAt: atOffset(-4, 16, 20),
    summary: "Template for short post-call follow-up with aligned actions.",
    body: "## Message template\nThanks for the call. Summary below:\n- What we aligned on\n- What remains open\n- Owner per action\n- Exact date for next sync\n\n## Quality bar\nThe client should understand the next step within 10 seconds.",
  },
]);

const pilotMessages = ref([
  { id: "p1", role: "assistant", text: "I monitor calendar, contacts, and communications in one flow." },
  { id: "p2", role: "user", text: "What is critical to do today?" },
  { id: "p3", role: "assistant", text: "First Anna after demo, then Murat on legal owner." },
]);
const pilotInput = ref("");

function sendPilotMessage() {
  const text = pilotInput.value.trim();
  if (!text) return;

  pilotMessages.value.push({ id: `p-${Date.now()}`, role: "user", text });
  pilotMessages.value.push({
    id: `p-${Date.now() + 1}`,
    role: "assistant",
    text: "Got it. Added to context and will use it in the next recommendations.",
  });
  pilotInput.value = "";
}

const calendarView = ref<CalendarView>("month");
const calendarCursor = ref(new Date(new Date().getFullYear(), new Date().getMonth(), 1));
const selectedDateKey = ref(dayKey(new Date()));

const sortedEvents = computed(() => [...calendarEvents.value].sort((a, b) => a.start.localeCompare(b.start)));

const eventsByDate = computed(() => {
  const map = new Map<string, CalendarEvent[]>();

  for (const event of sortedEvents.value) {
    const key = event.start.slice(0, 10);
    if (!map.has(key)) {
      map.set(key, []);
    }
    map.get(key)?.push(event);
  }

  return map;
});

function getEventsByDate(key: string) {
  return eventsByDate.value.get(key) ?? [];
}

const monthLabel = computed(() =>
  new Intl.DateTimeFormat("en-US", { month: "long", year: "numeric" }).format(calendarCursor.value),
);

const calendarViewOptions: { value: CalendarView; label: string }[] = [
  { value: "day", label: "Day" },
  { value: "week", label: "Week" },
  { value: "month", label: "Month" },
  { value: "year", label: "Year" },
  { value: "agenda", label: "Agenda" },
];

const monthCells = computed(() => {
  const year = calendarCursor.value.getFullYear();
  const month = calendarCursor.value.getMonth();
  const first = new Date(year, month, 1);
  const start = new Date(year, month, 1 - first.getDay());

  return Array.from({ length: 42 }, (_, index) => {
    const d = new Date(start);
    d.setDate(start.getDate() + index);
    const key = dayKey(d);

    return {
      key,
      day: d.getDate(),
      inMonth: d.getMonth() === month,
      events: getEventsByDate(key),
    };
  });
});

const weekDays = computed(() => {
  const base = new Date(`${selectedDateKey.value}T00:00:00`);
  const mondayOffset = (base.getDay() + 6) % 7;
  const monday = new Date(base);
  monday.setDate(base.getDate() - mondayOffset);

  return Array.from({ length: 7 }, (_, index) => {
    const d = new Date(monday);
    d.setDate(monday.getDate() + index);
    const key = dayKey(d);

    return {
      key,
      label: new Intl.DateTimeFormat("en-US", { weekday: "short" }).format(d),
      day: d.getDate(),
      events: getEventsByDate(key),
    };
  });
});

const calendarPeriodLabel = computed(() => {
  if (calendarView.value === "month") {
    return monthLabel.value;
  }

  if (calendarView.value === "year") {
    return String(calendarCursor.value.getFullYear());
  }

  if (calendarView.value === "week") {
    const first = weekDays.value[0];
    const last = weekDays.value[weekDays.value.length - 1];
    if (!first || !last) return "";
    return `${formatDay(`${first.key}T00:00:00`)} - ${formatDay(`${last.key}T00:00:00`)}`;
  }

  if (calendarView.value === "day") {
    return formatDay(`${selectedDateKey.value}T00:00:00`);
  }

  return `Agenda · ${monthLabel.value}`;
});

const yearMonths = computed(() => {
  const year = calendarCursor.value.getFullYear();
  return Array.from({ length: 12 }, (_, monthIndex) => {
    const monthStart = new Date(year, monthIndex, 1);
    const monthEnd = new Date(year, monthIndex + 1, 1);
    const items = sortedEvents.value.filter((event) => {
      const d = new Date(event.start);
      return d >= monthStart && d < monthEnd;
    });

    return {
      monthIndex,
      label: new Intl.DateTimeFormat("en-US", { month: "long" }).format(monthStart),
      count: items.length,
      first: items[0],
    };
  });
});

const selectedDayEvents = computed(() => getEventsByDate(selectedDateKey.value));

function shiftCalendar(step: number) {
  if (calendarView.value === "year") {
    const next = new Date(calendarCursor.value);
    next.setFullYear(next.getFullYear() + step);
    calendarCursor.value = new Date(next.getFullYear(), next.getMonth(), 1);
    const selected = new Date(`${selectedDateKey.value}T00:00:00`);
    selected.setFullYear(selected.getFullYear() + step);
    selectedDateKey.value = dayKey(selected);
    return;
  }

  if (calendarView.value === "month" || calendarView.value === "agenda") {
    const next = new Date(calendarCursor.value);
    next.setMonth(next.getMonth() + step);
    calendarCursor.value = new Date(next.getFullYear(), next.getMonth(), 1);
    return;
  }

  const current = new Date(`${selectedDateKey.value}T00:00:00`);
  const days = calendarView.value === "week" ? 7 : 1;
  current.setDate(current.getDate() + days * step);

  selectedDateKey.value = dayKey(current);
  calendarCursor.value = new Date(current.getFullYear(), current.getMonth(), 1);
}

function setToday() {
  const now = new Date();
  selectedDateKey.value = dayKey(now);
  calendarCursor.value = new Date(now.getFullYear(), now.getMonth(), 1);
}

function pickDate(key: string) {
  selectedDateKey.value = key;
  const d = new Date(`${key}T00:00:00`);
  calendarCursor.value = new Date(d.getFullYear(), d.getMonth(), 1);
}

function openYearMonth(monthIndex: number) {
  const year = calendarCursor.value.getFullYear();
  calendarCursor.value = new Date(year, monthIndex, 1);
  selectedDateKey.value = dayKey(new Date(year, monthIndex, 1));
  calendarView.value = "month";
}

const contactSearch = ref("");
const selectedCountry = ref("All");
const selectedLocation = ref("All");
const selectedCompany = ref("All");
const selectedChannel = ref("All");
const sortMode = ref<SortMode>("name");

const countries = computed(() => ["All", ...new Set(contacts.value.map((c) => c.country))].sort());

const locationScopeContacts = computed(() =>
  selectedCountry.value === "All"
    ? contacts.value
    : contacts.value.filter((contact) => contact.country === selectedCountry.value),
);

const locations = computed(() => ["All", ...new Set(locationScopeContacts.value.map((c) => c.location))].sort());

const companyScopeContacts = computed(() =>
  selectedLocation.value === "All"
    ? locationScopeContacts.value
    : locationScopeContacts.value.filter((contact) => contact.location === selectedLocation.value),
);

const companies = computed(() => ["All", ...new Set(companyScopeContacts.value.map((c) => c.company))].sort());
const channels = computed(() => ["All", ...new Set(contacts.value.flatMap((c) => c.channels))].sort());

watch(selectedCountry, () => {
  selectedLocation.value = "All";
  selectedCompany.value = "All";
});

watch(selectedLocation, () => {
  selectedCompany.value = "All";
});

function resetContactFilters() {
  contactSearch.value = "";
  selectedCountry.value = "All";
  selectedLocation.value = "All";
  selectedCompany.value = "All";
  selectedChannel.value = "All";
  sortMode.value = "name";
}

const filteredContacts = computed(() => {
  const query = contactSearch.value.trim().toLowerCase();
  const data = contacts.value.filter((contact) => {
    if (selectedCountry.value !== "All" && contact.country !== selectedCountry.value) return false;
    if (selectedLocation.value !== "All" && contact.location !== selectedLocation.value) return false;
    if (selectedCompany.value !== "All" && contact.company !== selectedCompany.value) return false;
    if (selectedChannel.value !== "All" && !contact.channels.includes(selectedChannel.value)) return false;
    if (query) {
      const haystack = [contact.name, contact.company, contact.country, contact.location, contact.description, contact.channels.join(" ")]
        .join(" ")
        .toLowerCase();
      if (!haystack.includes(query)) return false;
    }
    return true;
  });

  return data.sort((a, b) => {
    if (sortMode.value === "lastContact") {
      return b.lastContactAt.localeCompare(a.lastContactAt);
    }
    return a.name.localeCompare(b.name);
  });
});

const groupedContacts = computed(() => {
  if (sortMode.value === "lastContact") {
    return [["Recent", filteredContacts.value]] as [string, Contact[]][];
  }

  const map = new Map<string, Contact[]>();

  for (const contact of filteredContacts.value) {
    const key = contact.name[0].toUpperCase();
    if (!map.has(key)) {
      map.set(key, []);
    }
    map.get(key)?.push(contact);
  }

  return [...map.entries()].sort((a, b) => a[0].localeCompare(b[0]));
});

const selectedContactId = ref(contacts.value[0]?.id ?? "");

watchEffect(() => {
  if (!filteredContacts.value.length) {
    selectedContactId.value = "";
    return;
  }
  if (!filteredContacts.value.some((item) => item.id === selectedContactId.value)) {
    selectedContactId.value = filteredContacts.value[0].id;
  }
});

const selectedContact = computed(() => contacts.value.find((item) => item.id === selectedContactId.value));
const selectedContactEvents = computed(() => {
  if (!selectedContact.value) return [];
  const nowIso = new Date().toISOString();
  const events = sortedEvents.value.filter((event) => event.contact === selectedContact.value?.name);
  const upcoming = events.filter((event) => event.end >= nowIso);
  const past = events.filter((event) => event.end < nowIso).reverse();

  return [...upcoming, ...past].slice(0, 8);
});

const selectedContactRecentMessages = computed(() => {
  if (!selectedContact.value) return [];
  return commItems.value
    .filter((item) => item.contact === selectedContact.value?.name && item.kind === "message")
    .sort((a, b) => b.at.localeCompare(a.at))
    .slice(0, 8);
});

const documentSearch = ref("");
const selectedDocumentType = ref<"All" | WorkspaceDocument["type"]>("All");

const documentTypes = computed(() =>
  ["All", ...new Set(documents.value.map((item) => item.type))] as ("All" | WorkspaceDocument["type"])[],
);

const filteredDocuments = computed(() => {
  const query = documentSearch.value.trim().toLowerCase();

  return documents.value
    .filter((item) => {
      if (selectedDocumentType.value !== "All" && item.type !== selectedDocumentType.value) return false;
      if (!query) return true;
      const haystack = [item.title, item.summary, item.owner, item.scope, item.body].join(" ").toLowerCase();
      return haystack.includes(query);
    })
    .sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
});

const selectedDocumentId = ref(documents.value[0]?.id ?? "");

watchEffect(() => {
  if (!filteredDocuments.value.length) {
    selectedDocumentId.value = "";
    return;
  }

  if (!filteredDocuments.value.some((item) => item.id === selectedDocumentId.value)) {
    selectedDocumentId.value = filteredDocuments.value[0].id;
  }
});

const selectedDocument = computed(() => documents.value.find((item) => item.id === selectedDocumentId.value));

const peopleLeftMode = ref<PeopleLeftMode>("contacts");
const peopleListMode = ref<"contacts" | "deals">("contacts");
const peopleSearch = ref("");
const peopleSortMode = ref<PeopleSortMode>("lastContact");
const selectedDealId = ref(deals.value[0]?.id ?? "");

const commThreads = computed(() => {
  const sorted = [...commItems.value].sort((a, b) => a.at.localeCompare(b.at));
  const map = new Map<string, CommItem[]>();

  for (const item of sorted) {
    if (!map.has(item.contact)) {
      map.set(item.contact, []);
    }
    map.get(item.contact)?.push(item);
  }

  return contacts.value
    .map((contact) => {
      const items = map.get(contact.name) ?? [];
      const last = items[items.length - 1];
      const channels = [...new Set([...contact.channels, ...items.map((item) => item.channel)])] as CommItem["channel"][];

      return {
        id: contact.id,
        contact: contact.name,
        avatar: contact.avatar,
        company: contact.company,
        country: contact.country,
        location: contact.location,
        channels,
        lastAt: last?.at ?? contact.lastContactAt,
        lastText: last?.text ?? "No messages yet",
        items,
      };
    })
    .sort((a, b) => b.lastAt.localeCompare(a.lastAt));
});

const peopleContactList = computed(() => {
  const query = peopleSearch.value.trim().toLowerCase();
  const list = commThreads.value.filter((item) => {
    if (!query) return true;
    const haystack = [item.contact, item.company, item.country, item.location].join(" ").toLowerCase();
    return haystack.includes(query);
  });

  return list.sort((a, b) => {
    if (peopleSortMode.value === "name") return a.contact.localeCompare(b.contact);
    if (peopleSortMode.value === "company") return a.company.localeCompare(b.company);
    if (peopleSortMode.value === "country") return a.country.localeCompare(b.country);
    return b.lastAt.localeCompare(a.lastAt);
  });
});

const peopleDealList = computed(() => {
  const query = peopleSearch.value.trim().toLowerCase();
  const list = deals.value.filter((deal) => {
    if (!query) return true;
    const haystack = [deal.title, deal.company, deal.stage, deal.amount, deal.nextStep, deal.summary, deal.contact]
      .join(" ")
      .toLowerCase();
    return haystack.includes(query);
  });

  return list.sort((a, b) => a.title.localeCompare(b.title));
});

const selectedCommThreadId = ref("");

watchEffect(() => {
  if (!commThreads.value.length) {
    selectedCommThreadId.value = "";
    return;
  }

  if (!commThreads.value.some((thread) => thread.id === selectedCommThreadId.value)) {
    selectedCommThreadId.value = commThreads.value[0].id;
  }
});

const selectedCommThread = computed(() =>
  commThreads.value.find((thread) => thread.id === selectedCommThreadId.value),
);

const selectedCommChannel = ref<"All" | CommItem["channel"]>("All");
const showCommPinsOverlay = ref(false);
const selectedPinnedIndex = ref(0);

watch(selectedCommThreadId, () => {
  selectedCommChannel.value = "All";
  showCommPinsOverlay.value = false;
  selectedPinnedIndex.value = 0;
});

const commChannelTabs = computed(() => {
  if (!selectedCommThread.value) return ["All"] as ("All" | CommItem["channel"])[];
  return ["All", ...selectedCommThread.value.channels] as ("All" | CommItem["channel"])[];
});

const visibleThreadItems = computed(() => {
  if (!selectedCommThread.value) return [];
  if (selectedCommChannel.value === "All") return selectedCommThread.value.items;
  return selectedCommThread.value.items.filter((item) => item.channel === selectedCommChannel.value);
});

const selectedThreadRecommendation = computed(() => {
  if (!selectedCommThread.value) return null;
  const cards = feedCards.value
    .filter((card) => card.contact === selectedCommThread.value?.contact)
    .sort((a, b) => a.at.localeCompare(b.at));
  return cards[cards.length - 1] ?? null;
});

const threadStreamItems = computed(() => {
  const messageRows = visibleThreadItems.value.map((item) => ({
    id: `comm-${item.id}`,
    at: item.at,
    kind: item.kind,
    item,
  })).sort((a, b) => a.at.localeCompare(b.at));

  if (selectedCommChannel.value !== "All") {
    return messageRows;
  }

  const centeredRows: Array<
    | {
      id: string;
      at: string;
      kind: "eventAlert";
      event: CalendarEvent;
    }
    | {
      id: string;
      at: string;
      kind: "recommendation";
      card: FeedCard;
    }
  > = [];

  if (selectedCommUrgentEvent.value) {
    centeredRows.push({
      id: `event-alert-${selectedCommUrgentEvent.value.id}`,
      at: selectedCommUrgentEvent.value.start,
      kind: "eventAlert",
      event: selectedCommUrgentEvent.value,
    });
  }

  if (selectedThreadRecommendation.value) {
    centeredRows.push({
      id: `rec-${selectedThreadRecommendation.value.id}`,
      at: selectedThreadRecommendation.value.at,
      kind: "recommendation",
      card: selectedThreadRecommendation.value,
    });
  }

  return [...messageRows, ...centeredRows];
});

const selectedCommPins = computed(() => {
  if (!selectedCommThread.value) return [];
  return commPins.value.filter((item) => item.contact === selectedCommThread.value?.contact);
});

const selectedCommEvents = computed(() => {
  if (!selectedCommThread.value) return [];
  const now = new Date();

  return sortedEvents.value
    .filter((event) => event.contact === selectedCommThread.value?.contact)
    .filter((event) => new Date(event.end) >= now)
    .slice(0, 6);
});

const selectedCommUrgentEvent = computed(() => {
  if (!selectedCommThread.value) return null;
  const now = Date.now();
  const inFifteenMinutes = now + 15 * 60 * 1000;

  const event = sortedEvents.value
    .filter((item) => item.contact === selectedCommThread.value?.contact)
    .filter((item) => {
      const start = new Date(item.start).getTime();
      return start >= now && start <= inFifteenMinutes;
    })
    .sort((a, b) => a.start.localeCompare(b.start))[0];

  return event ?? null;
});

const selectedCommPinnedStream = computed(() => {
  const pins = selectedCommPins.value.map((pin) => ({
    id: `pin-${pin.id}`,
    kind: "pin" as const,
    text: pin.text,
  }));

  const events = selectedCommEvents.value.map((event) => ({
    id: `event-${event.id}`,
    kind: "event" as const,
    event,
  }));

  return [...pins, ...events];
});

const currentPinnedItem = computed(() => {
  if (!selectedCommPinnedStream.value.length) return null;
  const index = Math.max(0, Math.min(selectedPinnedIndex.value, selectedCommPinnedStream.value.length - 1));
  return selectedCommPinnedStream.value[index];
});

const selectedWorkspaceContact = computed(() => {
  if (selectedContact.value) return selectedContact.value;
  if (!selectedCommThread.value) return null;
  return contacts.value.find((contact) => contact.name === selectedCommThread.value?.contact) ?? null;
});

const selectedWorkspaceDeal = computed(() => {
  if (selectedWorkspaceContact.value) {
    const linked = deals.value.find((deal) => deal.contact === selectedWorkspaceContact.value?.name);
    if (linked) return linked;
  }

  return deals.value.find((deal) => deal.id === selectedDealId.value) ?? null;
});

const openCallTranscripts = ref<Record<string, boolean>>({});

function shiftPinned(direction: -1 | 1) {
  if (!selectedCommPinnedStream.value.length) return;
  const total = selectedCommPinnedStream.value.length;
  selectedPinnedIndex.value = (selectedPinnedIndex.value + direction + total) % total;
}

function toggleCallTranscript(itemId: string) {
  openCallTranscripts.value[itemId] = !openCallTranscripts.value[itemId];
}

function isCallTranscriptOpen(itemId: string) {
  return Boolean(openCallTranscripts.value[itemId]);
}

function threadTone(thread: { contact: string; items: CommItem[] }) {
  const now = Date.now();
  const oneDay = 24 * 60 * 60 * 1000;
  const hasEvent = sortedEvents.value.some((event) => {
    if (event.contact !== thread.contact) return false;
    const start = new Date(event.start).getTime();
    const end = new Date(event.end).getTime();
    return end <= now || start - now <= oneDay;
  });
  if (hasEvent) return "event";

  const hasRecommendation = feedCards.value.some((card) => card.contact === thread.contact && card.decision === "pending");
  if (hasRecommendation) return "recommendation";

  const last = thread.items[thread.items.length - 1];
  if (!last) return "neutral";
  if (last.direction === "in") return "message";
  return "neutral";
}

function openEventFromCommunication(event: CalendarEvent) {
  showCommPinsOverlay.value = false;
  selectedTab.value = "communications";
  peopleLeftMode.value = "calendar";
  pickDate(event.start.slice(0, 10));
}

function channelIcon(channel: "All" | CommItem["channel"]) {
  if (channel === "All") return "all";
  if (channel === "Telegram") return "telegram";
  if (channel === "WhatsApp") return "whatsapp";
  if (channel === "Instagram") return "instagram";
  if (channel === "Email") return "email";
  return "phone";
}

function makeId(prefix: string) {
  return `${prefix}-${Date.now()}-${Math.floor(Math.random() * 1000)}`;
}

function pushPilotNote(text: string) {
  pilotMessages.value.push({ id: makeId("p"), role: "assistant", text });
}

function openCommunicationThread(contact: string) {
  selectedTab.value = "communications";
  peopleLeftMode.value = "contacts";
  const linkedContact = contacts.value.find((item) => item.name === contact);
  if (linkedContact) {
    selectedContactId.value = linkedContact.id;
  }
  const linkedDeal = deals.value.find((deal) => deal.contact === contact);
  if (linkedDeal) {
    selectedDealId.value = linkedDeal.id;
  }
  const thread = commThreads.value.find((item) => item.contact === contact);
  if (thread) {
    selectedCommThreadId.value = thread.id;
  }
}

function openDealThread(deal: Deal) {
  selectedDealId.value = deal.id;
  openCommunicationThread(deal.contact);
}

function openThreadFromCalendarItem(event: CalendarEvent) {
  openCommunicationThread(event.contact);
  selectedCommChannel.value = "All";
}

function openEventFromContact(event: CalendarEvent) {
  selectedTab.value = "communications";
  peopleLeftMode.value = "calendar";
  pickDate(event.start.slice(0, 10));
}

function openMessageFromContact(channel: CommItem["channel"]) {
  if (!selectedContact.value) return;
  openCommunicationThread(selectedContact.value.name);
  selectedCommChannel.value = channel;
}

function executeFeedAction(key: FeedCard["proposal"]["key"]) {
  if (key === "create_followup") {
    const start = new Date();
    start.setMinutes(start.getMinutes() + 30);
    start.setSeconds(0, 0);
    const end = new Date(start);
    end.setMinutes(end.getMinutes() + 30);

    calendarEvents.value.unshift({
      id: makeId("e"),
      title: "Follow-up: Anna",
      start: start.toISOString(),
      end: end.toISOString(),
      contact: "Anna Meyer",
      note: "Created from feed action.",
    });

    selectedDateKey.value = dayKey(start);
    calendarCursor.value = new Date(start.getFullYear(), start.getMonth(), 1);
    selectedTab.value = "communications";
    peopleLeftMode.value = "calendar";
    return `Event created: Follow-up: Anna · ${formatDay(start.toISOString())} ${formatTime(start.toISOString())}`;
  }

  if (key === "open_comm") {
    openCommunicationThread("Murat Ali");
    return "Opened Murat Ali communication thread.";
  }

  if (key === "call") {
    commItems.value.push({
      id: makeId("m"),
      at: new Date().toISOString(),
      contact: "Murat Ali",
      channel: "Phone",
      kind: "call",
      direction: "out",
      text: "Call started from feed",
      duration: "00:00",
    });
    openCommunicationThread("Murat Ali");
    return "Call event created and Murat Ali chat opened.";
  }

  if (key === "draft_message") {
    commItems.value.push({
      id: makeId("m"),
      at: new Date().toISOString(),
      contact: "Ilya Petroff",
      channel: "Email",
      kind: "message",
      direction: "out",
      text: "Draft: onboarding plan + two slots for tomorrow.",
    });
    openCommunicationThread("Ilya Petroff");
    return "Draft message added to Ilya Petroff communications.";
  }

  if (key === "run_summary") {
    return "Call summary prepared: 5 next steps sent to Pilot.";
  }

  if (key === "prepare_question") {
    commItems.value.push({
      id: makeId("m"),
      at: new Date().toISOString(),
      contact: "Anna Meyer",
      channel: "Telegram",
      kind: "message",
      direction: "out",
      text: "Draft: can you confirm your decision date for this cycle?",
    });
    openCommunicationThread("Anna Meyer");
    return "Question about decision date added to Anna Meyer chat.";
  }

  return "Action completed.";
}

function decideFeedCard(card: FeedCard, decision: "accepted" | "rejected") {
  card.decision = decision;
  if (decision === "rejected") {
    card.decisionNote = "Rejected. Nothing created.";
    pushPilotNote(`[${card.contact}] recommendation rejected: ${card.proposal.title}`);
    return;
  }

  const result = executeFeedAction(card.proposal.key);
  card.decisionNote = result;
  pushPilotNote(`[${card.contact}] ${result}`);
}

</script>

<template>
  <div class="min-h-screen p-3 md:p-5">
    <div class="grid gap-3 lg:grid-cols-12 lg:gap-4">
      <aside class="card min-h-0 border border-base-300 bg-base-100 shadow-sm lg:col-span-3 lg:sticky lg:top-5 lg:h-[calc(100vh-2.5rem)]">
        <div class="card-body h-full min-h-0 p-3 md:p-4">
          <div class="mb-2">
            <h2 class="text-sm font-semibold uppercase tracking-wide text-base-content/70">Pilot</h2>
          </div>

          <div class="min-h-0 flex-1 space-y-2 overflow-y-auto rounded-xl border border-base-300 p-2">
            <div
              v-for="message in pilotMessages"
              :key="message.id"
              class="chat"
              :class="message.role === 'assistant' ? 'chat-start' : 'chat-end'"
            >
              <div class="chat-bubble text-sm" :class="message.role === 'assistant' ? 'chat-bubble-neutral' : ''">
                {{ message.text }}
              </div>
            </div>
          </div>

          <div class="mt-2 flex gap-2">
            <input
              v-model="pilotInput"
              type="text"
              class="input input-bordered input-sm w-full"
              placeholder="Write a message..."
              @keyup.enter="sendPilotMessage"
            >
            <button class="btn btn-sm" @click="sendPilotMessage">Send</button>
          </div>
        </div>
      </aside>

      <main class="card border border-base-300 bg-base-100 shadow-sm lg:col-span-9">
        <div class="card-body flex flex-col p-3 pb-20 md:p-4 md:pb-24">
          <div class="flex-1">
            <section v-if="selectedTab === 'communications' && peopleLeftMode === 'calendar'" class="space-y-3">
            <div class="mb-1 flex justify-end">
              <div class="join">
                <button class="btn btn-sm join-item btn-ghost" @click="peopleLeftMode = 'contacts'">Contacts</button>
                <button class="btn btn-sm join-item btn-primary" @click="peopleLeftMode = 'calendar'">Calendar</button>
              </div>
            </div>
            <div class="grid grid-cols-[auto_1fr_auto] items-center gap-2">
              <div class="flex items-center gap-1">
                <button class="btn btn-xs" @click="setToday">Today</button>
                <button class="btn btn-xs btn-ghost" @click="shiftCalendar(-1)">←</button>
                <button class="btn btn-xs btn-ghost" @click="shiftCalendar(1)">→</button>
              </div>

              <div class="text-center text-sm font-medium">
                {{ calendarPeriodLabel }}
              </div>

              <div class="justify-self-end">
                <select v-model="calendarView" class="select select-bordered select-xs w-36">
                  <option
                    v-for="option in calendarViewOptions"
                    :key="`calendar-view-${option.value}`"
                    :value="option.value"
                  >
                    {{ option.label }}
                  </option>
                </select>
              </div>
            </div>

            <div v-if="calendarView === 'month'" class="space-y-1">
              <div class="grid grid-cols-7 gap-1 text-center text-xs font-semibold text-base-content/60">
                <span>Sun</span>
                <span>Mon</span>
                <span>Tue</span>
                <span>Wed</span>
                <span>Thu</span>
                <span>Fri</span>
                <span>Sat</span>
              </div>

              <div class="grid grid-cols-7 gap-1">
                <button
                  v-for="cell in monthCells"
                  :key="cell.key"
                  class="min-h-24 rounded-lg border p-1 text-left"
                  :class="[
                    cell.inMonth ? 'border-base-300 bg-base-100' : 'border-base-200 bg-base-200/40 text-base-content/40',
                    selectedDateKey === cell.key ? 'border-primary bg-primary/5' : '',
                  ]"
                  @click="pickDate(cell.key)"
                >
                  <p class="mb-1 text-xs font-semibold">{{ cell.day }}</p>
                  <p v-for="event in cell.events.slice(0, 2)" :key="event.id" class="truncate text-[10px] text-base-content/70">
                    {{ formatTime(event.start) }} {{ event.title }}
                  </p>
                </button>
              </div>
            </div>

            <div v-else-if="calendarView === 'week'" class="space-y-2">
              <article
                v-for="day in weekDays"
                :key="day.key"
                class="rounded-xl border border-base-300 p-3"
                :class="selectedDateKey === day.key ? 'border-primary bg-primary/5' : ''"
                @click="pickDate(day.key)"
              >
                <p class="mb-2 text-sm font-semibold">{{ day.label }} {{ day.day }}</p>
                <div class="space-y-1">
                  <p v-for="event in day.events" :key="event.id" class="rounded bg-base-200 px-2 py-1 text-xs">
                    {{ formatTime(event.start) }} - {{ event.title }} ({{ event.contact }})
                  </p>
                  <p v-if="day.events.length === 0" class="text-xs text-base-content/50">No events</p>
                </div>
              </article>
            </div>

            <div v-else-if="calendarView === 'day'" class="space-y-2">
              <article v-for="event in selectedDayEvents" :key="event.id" class="rounded-xl border border-base-300 p-3">
                <p class="font-medium">{{ event.title }}</p>
                <p class="text-xs text-base-content/60">{{ event.contact }}</p>
                <p class="text-xs text-base-content/60">{{ formatTime(event.start) }} - {{ formatTime(event.end) }}</p>
                <p class="mt-1 text-sm text-base-content/80">{{ event.note }}</p>
              </article>
              <p v-if="selectedDayEvents.length === 0" class="text-sm text-base-content/60">No events on this day.</p>
            </div>

            <div v-else-if="calendarView === 'year'" class="grid gap-2 sm:grid-cols-2 xl:grid-cols-3">
              <button
                v-for="item in yearMonths"
                :key="`year-month-${item.monthIndex}`"
                class="rounded-xl border border-base-300 p-3 text-left transition hover:border-primary/50 hover:bg-primary/5"
                @click="openYearMonth(item.monthIndex)"
              >
                <p class="font-medium">{{ item.label }}</p>
                <p class="text-xs text-base-content/60">{{ item.count }} events</p>
                <p v-if="item.first" class="mt-1 text-xs text-base-content/70">
                  {{ formatDay(item.first.start) }} · {{ item.first.title }}
                </p>
              </button>
            </div>

            <div v-else class="space-y-2">
              <article v-for="event in sortedEvents" :key="event.id" class="rounded-xl border border-base-300 p-3">
                <p class="font-medium">{{ event.title }}</p>
                <p class="text-xs text-base-content/60">{{ event.contact }}</p>
                <p class="text-xs text-base-content/60">{{ formatDay(event.start) }} · {{ formatTime(event.start) }} - {{ formatTime(event.end) }}</p>
                <p class="mt-1 text-sm text-base-content/80">{{ event.note }}</p>
              </article>
            </div>
            </section>

            <section v-else-if="selectedTab === 'communications' && false" class="space-y-3">
            <div class="mb-1 flex justify-end">
              <div class="join">
                <button class="btn btn-sm join-item btn-primary" @click="peopleLeftMode = 'contacts'">Contacts</button>
                <button class="btn btn-sm join-item btn-ghost" @click="peopleLeftMode = 'calendar'">Calendar</button>
              </div>
            </div>
            <div class="rounded-xl border border-base-300 p-3">
              <div class="flex flex-wrap items-center gap-2">
                <input
                  v-model="contactSearch"
                  type="text"
                  class="input input-bordered input-md w-full flex-1"
                  placeholder="Search contacts..."
                >

                <select v-model="sortMode" class="select select-bordered select-sm w-40">
                  <option value="name">Sort: Name</option>
                  <option value="lastContact">Sort: Last contact</option>
                </select>

                <div class="dropdown dropdown-end">
                  <button tabindex="0" class="btn btn-sm btn-ghost btn-square" title="Filters">
                    <svg viewBox="0 0 24 24" class="h-4 w-4 fill-current">
                      <path d="M3 5h18v2H3zm4 6h10v2H7zm3 6h4v2h-4z" />
                    </svg>
                  </button>
                  <div tabindex="0" class="dropdown-content z-20 mt-2 w-72 rounded-xl border border-base-300 bg-base-100 p-3 shadow-lg">
                    <div class="grid gap-2">
                      <label class="form-control">
                        <span class="label-text text-xs uppercase tracking-wide text-base-content/60">Country</span>
                        <select v-model="selectedCountry" class="select select-bordered select-sm">
                          <option v-for="country in countries" :key="`country-${country}`" :value="country">{{ country }}</option>
                        </select>
                      </label>

                      <label class="form-control">
                        <span class="label-text text-xs uppercase tracking-wide text-base-content/60">Location</span>
                        <select v-model="selectedLocation" class="select select-bordered select-sm">
                          <option v-for="location in locations" :key="`location-${location}`" :value="location">{{ location }}</option>
                        </select>
                      </label>

                      <label class="form-control">
                        <span class="label-text text-xs uppercase tracking-wide text-base-content/60">Company</span>
                        <select v-model="selectedCompany" class="select select-bordered select-sm">
                          <option v-for="company in companies" :key="`company-${company}`" :value="company">{{ company }}</option>
                        </select>
                      </label>

                      <label class="form-control">
                        <span class="label-text text-xs uppercase tracking-wide text-base-content/60">Channel</span>
                        <select v-model="selectedChannel" class="select select-bordered select-sm">
                          <option v-for="channel in channels" :key="`channel-${channel}`" :value="channel">{{ channel }}</option>
                        </select>
                      </label>
                    </div>

                    <div class="mt-3 flex justify-end">
                      <button class="btn btn-ghost btn-sm" @click="resetContactFilters">Reset filters</button>
                    </div>
                  </div>
                </div>
              </div>
            </div>

            <div class="grid gap-3 md:grid-cols-12">
              <aside class="min-h-0 rounded-xl border border-base-300 md:col-span-4">
                <div class="min-h-0 space-y-3 overflow-y-auto p-2">
                  <article v-for="group in groupedContacts" :key="group[0]" class="space-y-2">
                    <div class="sticky top-0 z-10 rounded-lg bg-base-200 px-3 py-1 text-sm font-semibold">{{ group[0] }}</div>

                    <button
                      v-for="contact in group[1]"
                      :key="contact.id"
                      class="w-full rounded-xl border border-base-300 p-3 text-left transition hover:bg-base-200/60"
                      :class="selectedContactId === contact.id ? 'border-primary bg-primary/5' : ''"
                      @click="selectedContactId = contact.id"
                    >
                      <p class="font-medium">{{ contact.name }}</p>
                      <p class="text-xs text-base-content/60">{{ contact.company }} · {{ contact.location }}, {{ contact.country }}</p>
                      <p class="mt-1 text-[11px] text-base-content/55">Last contact · {{ formatStamp(contact.lastContactAt) }}</p>
                    </button>
                  </article>
                </div>
              </aside>

              <article class="min-h-0 rounded-xl border border-base-300 md:col-span-8">
                <div v-if="selectedContact" class="p-3 md:p-4">
                  <div class="border-b border-base-300 pb-2">
                    <p class="font-medium">{{ selectedContact.name }}</p>
                    <p class="text-xs text-base-content/60">
                      {{ selectedContact.company }} · {{ selectedContact.location }}, {{ selectedContact.country }}
                    </p>
                    <p class="mt-1 text-xs text-base-content/55">Last contact · {{ formatStamp(selectedContact.lastContactAt) }}</p>
                  </div>

                  <div class="mt-3">
                    <ContactCollaborativeEditor
                      :key="`contact-editor-${selectedContact.id}`"
                      v-model="selectedContact.description"
                      :room="`crm-contact-${selectedContact.id}`"
                      placeholder="Describe contact context and next steps..."
                    />
                  </div>

                  <div class="mt-4 grid gap-3 xl:grid-cols-2">
                    <section class="rounded-xl border border-base-300 p-3">
                      <div class="mb-2 flex items-center justify-between gap-2">
                        <p class="text-sm font-semibold">Upcoming events</p>
                      </div>
                      <div class="space-y-2">
                        <button
                          v-for="event in selectedContactEvents"
                          :key="`contact-event-${event.id}`"
                          class="w-full rounded-lg border border-base-300 px-3 py-2 text-left transition hover:bg-base-200/50"
                          @click="openEventFromContact(event)"
                        >
                          <p class="text-sm font-medium">{{ event.title }}</p>
                          <p class="text-xs text-base-content/65">
                            {{ formatDay(event.start) }} · {{ formatTime(event.start) }} - {{ formatTime(event.end) }}
                          </p>
                          <p class="mt-1 text-xs text-base-content/80">{{ event.note }}</p>
                        </button>
                        <p v-if="selectedContactEvents.length === 0" class="text-xs text-base-content/55">
                          No linked events yet.
                        </p>
                      </div>
                    </section>

                    <section class="rounded-xl border border-base-300 p-3">
                      <div class="mb-2 flex items-center justify-between gap-2">
                        <p class="text-sm font-semibold">Recent messages</p>
                        <button class="btn btn-ghost btn-xs" @click="openCommunicationThread(selectedContact.name)">Open chat</button>
                      </div>
                      <div class="space-y-2">
                        <button
                          v-for="item in selectedContactRecentMessages"
                          :key="`contact-message-${item.id}`"
                          class="w-full rounded-lg border border-base-300 px-3 py-2 text-left transition hover:bg-base-200/50"
                          @click="openMessageFromContact(item.channel)"
                        >
                          <p class="text-sm text-base-content/90">{{ item.text }}</p>
                          <p class="mt-1 text-xs text-base-content/60">
                            <span class="mr-1 inline-flex h-4 w-4 items-center justify-center align-middle">
                              <svg v-if="channelIcon(item.channel) === 'telegram'" viewBox="0 0 24 24" class="h-3.5 w-3.5 fill-current">
                                <path d="M9.04 15.51 8.7 20.27c.49 0 .7-.21.96-.46l2.3-2.2 4.77 3.49c.88.49 1.5.23 1.74-.81l3.15-14.77.01-.01c.29-1.35-.49-1.88-1.35-1.56L1.74 11.08c-1.28.5-1.26 1.22-.22 1.54l4.74 1.48L17.3 7.03c.52-.34 1-.15.61.19" />
                              </svg>
                              <svg v-else-if="channelIcon(item.channel) === 'whatsapp'" viewBox="0 0 24 24" class="h-3.5 w-3.5 fill-current">
                                <path d="M20 3.99A9.94 9.94 0 0 0 12.01 1C6.49 1 2 5.49 2 11c0 1.76.46 3.49 1.33 5.03L2 23l7.17-1.88A9.95 9.95 0 0 0 12 21h.01c5.51 0 9.99-4.49 9.99-10.01 0-2.67-1.04-5.18-2.99-7m-7.99 15.32h-.01a8.3 8.3 0 0 1-4.23-1.16l-.3-.18-4.26 1.12 1.14-4.15-.2-.32a8.28 8.28 0 0 1-1.27-4.4c0-4.58 3.73-8.31 8.32-8.31a8.27 8.27 0 0 1 5.88 2.44 8.25 8.25 0 0 1 2.43 5.87c0 4.59-3.73 8.32-8.31 8.32m4.56-6.23c-.25-.12-1.49-.74-1.73-.82-.23-.09-.4-.12-.57.12s-.66.82-.81.99-.3.18-.55.06a6.7 6.7 0 0 1-1.97-1.21 7.43 7.43 0 0 1-1.38-1.71c-.14-.24-.01-.37.1-.49.11-.11.24-.3.36-.45.12-.14.16-.24.25-.39.08-.18.05-.3-.02-.42-.07-.12-.56-1.35-.77-1.85-.2-.48-.41-.41-.57-.42h-.48c-.16 0-.42.06-.64.3-.22.24-.84.82-.84 2s.86 2.31.98 2.48c.12.16 1.69 2.57 4.09 3.6.57.24 1.01.38 1.36.48.58.18 1.11.15 1.52.09.46-.06 1.49-.61 1.7-1.19.21-.58.21-1.09.15-1.19-.06-.11-.23-.17-.48-.3" />
                              </svg>
                              <svg v-else-if="channelIcon(item.channel) === 'instagram'" viewBox="0 0 24 24" class="h-3.5 w-3.5 fill-current">
                                <path d="M7 2h10a5 5 0 0 1 5 5v10a5 5 0 0 1-5 5H7a5 5 0 0 1-5-5V7a5 5 0 0 1 5-5m10 2H7a3 3 0 0 0-3 3v10a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V7a3 3 0 0 0-3-3m-5 3.5A4.5 4.5 0 1 1 7.5 12 4.5 4.5 0 0 1 12 7.5m0 2A2.5 2.5 0 1 0 14.5 12 2.5 2.5 0 0 0 12 9.5m4.8-3.2a1.2 1.2 0 1 1-1.2 1.2 1.2 1.2 0 0 1 1.2-1.2" />
                              </svg>
                              <svg v-else-if="channelIcon(item.channel) === 'email'" viewBox="0 0 24 24" class="h-3.5 w-3.5 fill-current">
                                <path d="M20 4H4a2 2 0 0 0-2 2v.4l10 5.6 10-5.6V6a2 2 0 0 0-2-2m0 4.2-7.4 4.14a1.25 1.25 0 0 1-1.2 0L4 8.2V18a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2z" />
                              </svg>
                              <svg v-else viewBox="0 0 24 24" class="h-3.5 w-3.5 fill-current">
                                <path d="M6.62 10.79a15.47 15.47 0 0 0 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1C10.07 21 3 13.93 3 5c0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.24.2 2.45.57 3.57.11.35.03.74-.25 1.02z" />
                              </svg>
                            </span>
                            <span>{{ formatStamp(item.at) }}</span>
                          </p>
                        </button>
                        <p v-if="selectedContactRecentMessages.length === 0" class="text-xs text-base-content/55">
                          No messages yet.
                        </p>
                      </div>
                    </section>
                  </div>
                </div>

                <div v-else class="flex h-full items-center justify-center text-sm text-base-content/60">
                  No contact selected.
                </div>
              </article>
            </div>
            </section>

            <section v-else-if="selectedTab === 'communications' && peopleLeftMode === 'contacts'" class="space-y-3">
            <div class="mb-1 flex justify-end">
              <div class="join">
                <button class="btn btn-sm join-item btn-primary" @click="peopleLeftMode = 'contacts'">Contacts</button>
                <button class="btn btn-sm join-item btn-ghost" @click="peopleLeftMode = 'calendar'">Calendar</button>
              </div>
            </div>
            <div class="grid gap-3 md:grid-cols-[220px_minmax(0,1fr)_320px]">
              <aside class="min-h-0 rounded-xl border border-base-300">
                <div class="sticky top-0 z-20 border-b border-base-300 bg-base-100 p-2">
                  <div class="mb-2 flex items-center gap-1">
                    <button
                      class="btn btn-xs flex-1"
                      :class="peopleListMode === 'contacts' ? 'btn-primary' : 'btn-ghost'"
                      @click="peopleListMode = 'contacts'"
                    >
                      Contacts
                    </button>
                    <button
                      class="btn btn-xs flex-1"
                      :class="peopleListMode === 'deals' ? 'btn-primary' : 'btn-ghost'"
                      @click="peopleListMode = 'deals'"
                    >
                      Deals
                    </button>
                  </div>
                  <input
                    v-model="peopleSearch"
                    type="text"
                    class="input input-bordered input-sm w-full"
                    :placeholder="peopleListMode === 'contacts' ? 'Search contacts' : 'Search deals'"
                  >
                </div>

                <div class="min-h-0 space-y-1.5 overflow-y-auto p-2">
                  <button
                    v-if="peopleListMode === 'contacts'"
                    v-for="thread in peopleContactList"
                    :key="thread.id"
                    class="w-full rounded-xl border border-base-300 px-2 py-2 text-left transition hover:bg-base-200/60"
                    :class="selectedCommThreadId === thread.id ? 'border-primary bg-primary/5' : ''"
                    @click="openCommunicationThread(thread.contact)"
                  >
                    <div class="flex items-start gap-2">
                      <div class="avatar shrink-0">
                        <div class="h-8 w-8 rounded-full ring-1 ring-base-300/70">
                          <img :src="thread.avatar" :alt="thread.contact">
                        </div>
                      </div>

                      <div class="min-w-0 flex-1">
                        <div class="flex items-start justify-between gap-2">
                          <p class="truncate text-xs font-semibold">{{ thread.contact }}</p>
                          <span class="shrink-0 text-[10px] text-base-content/55">{{ formatThreadTime(thread.lastAt) }}</span>
                        </div>
                        <div class="mt-0.5 flex items-center gap-2">
                          <p class="min-w-0 flex-1 truncate text-[11px] text-base-content/75">{{ thread.lastText }}</p>
                          <span
                            class="inline-block h-2 w-2 rounded-full"
                            :class="
                              threadTone(thread) === 'event'
                                ? 'bg-red-500'
                                : threadTone(thread) === 'recommendation'
                                  ? 'bg-violet-500'
                                  : threadTone(thread) === 'message'
                                    ? 'bg-blue-500'
                                    : 'bg-base-300'
                            "
                          />
                        </div>
                      </div>
                    </div>
                  </button>

                  <button
                    v-if="peopleListMode === 'deals'"
                    v-for="deal in peopleDealList"
                    :key="deal.id"
                    class="w-full rounded-xl border border-base-300 px-2 py-2 text-left transition hover:bg-base-200/60"
                    :class="selectedDealId === deal.id ? 'border-primary bg-primary/5' : ''"
                    @click="openDealThread(deal)"
                  >
                    <div class="flex items-start justify-between gap-2">
                      <p class="truncate text-xs font-semibold">{{ deal.title }}</p>
                      <span class="shrink-0 text-[10px] text-base-content/55">{{ deal.amount }}</span>
                    </div>
                    <p class="mt-0.5 truncate text-[11px] text-base-content/75">{{ deal.company }} · {{ deal.stage }}</p>
                    <p class="mt-0.5 truncate text-[11px] text-base-content/60">{{ deal.nextStep }}</p>
                  </button>

                  <p v-if="peopleListMode === 'contacts' && peopleContactList.length === 0" class="px-1 py-2 text-xs text-base-content/55">
                    No contacts found.
                  </p>
                  <p v-if="peopleListMode === 'deals' && peopleDealList.length === 0" class="px-1 py-2 text-xs text-base-content/55">
                    No deals found.
                  </p>
                </div>
              </aside>

              <article class="min-h-0 rounded-xl border border-base-300">
                <div v-if="false" class="p-3">
                  <div class="grid grid-cols-[auto_1fr_auto] items-center gap-2">
                    <div class="flex items-center gap-1">
                      <button class="btn btn-xs" @click="setToday">Today</button>
                      <button class="btn btn-xs btn-ghost" @click="shiftCalendar(-1)">←</button>
                      <button class="btn btn-xs btn-ghost" @click="shiftCalendar(1)">→</button>
                    </div>

                    <div class="text-center text-sm font-medium">
                      {{ calendarPeriodLabel }}
                    </div>

                    <div class="justify-self-end">
                      <select v-model="calendarView" class="select select-bordered select-xs w-36">
                        <option
                          v-for="option in calendarViewOptions"
                          :key="`workspace-right-calendar-view-${option.value}`"
                          :value="option.value"
                        >
                          {{ option.label }}
                        </option>
                      </select>
                    </div>
                  </div>

                  <div v-if="calendarView === 'month'" class="mt-3 space-y-1">
                    <div class="grid grid-cols-7 gap-1 text-center text-xs font-semibold text-base-content/60">
                      <span>Sun</span>
                      <span>Mon</span>
                      <span>Tue</span>
                      <span>Wed</span>
                      <span>Thu</span>
                      <span>Fri</span>
                      <span>Sat</span>
                    </div>

                    <div class="grid grid-cols-7 gap-1">
                      <button
                        v-for="cell in monthCells"
                        :key="`workspace-right-month-${cell.key}`"
                        class="min-h-24 rounded-lg border p-1 text-left"
                        :class="[
                          cell.inMonth ? 'border-base-300 bg-base-100' : 'border-base-200 bg-base-200/40 text-base-content/40',
                          selectedDateKey === cell.key ? 'border-primary bg-primary/5' : '',
                        ]"
                        @click="pickDate(cell.key)"
                      >
                        <p class="mb-1 text-xs font-semibold">{{ cell.day }}</p>
                        <button
                          v-for="event in cell.events.slice(0, 2)"
                          :key="`workspace-right-month-event-${event.id}`"
                          class="block w-full truncate text-left text-[10px] text-base-content/70 hover:underline"
                          @click.stop="openThreadFromCalendarItem(event)"
                        >
                          {{ formatTime(event.start) }} {{ event.title }}
                        </button>
                      </button>
                    </div>
                  </div>

                  <div v-else-if="calendarView === 'week'" class="mt-3 space-y-2">
                    <article
                      v-for="day in weekDays"
                      :key="`workspace-right-week-${day.key}`"
                      class="rounded-xl border border-base-300 p-3"
                      :class="selectedDateKey === day.key ? 'border-primary bg-primary/5' : ''"
                      @click="pickDate(day.key)"
                    >
                      <p class="mb-2 text-sm font-semibold">{{ day.label }} {{ day.day }}</p>
                      <div class="space-y-1">
                        <button
                          v-for="event in day.events"
                          :key="`workspace-right-week-event-${event.id}`"
                          class="block w-full rounded bg-base-200 px-2 py-1 text-left text-xs hover:bg-base-300/80"
                          @click.stop="openThreadFromCalendarItem(event)"
                        >
                          {{ formatTime(event.start) }} - {{ event.title }} ({{ event.contact }})
                        </button>
                        <p v-if="day.events.length === 0" class="text-xs text-base-content/50">No events</p>
                      </div>
                    </article>
                  </div>

                  <div v-else-if="calendarView === 'day'" class="mt-3 space-y-2">
                    <button
                      v-for="event in selectedDayEvents"
                      :key="`workspace-right-day-event-${event.id}`"
                      class="block w-full rounded-xl border border-base-300 p-3 text-left hover:bg-base-200/60"
                      @click="openThreadFromCalendarItem(event)"
                    >
                      <p class="font-medium">{{ event.title }}</p>
                      <p class="text-xs text-base-content/60">{{ event.contact }}</p>
                      <p class="text-xs text-base-content/60">{{ formatTime(event.start) }} - {{ formatTime(event.end) }}</p>
                      <p class="mt-1 text-sm text-base-content/80">{{ event.note }}</p>
                    </button>
                    <p v-if="selectedDayEvents.length === 0" class="text-sm text-base-content/60">No events on this day.</p>
                  </div>

                  <div v-else-if="calendarView === 'year'" class="mt-3 grid gap-2 sm:grid-cols-2 xl:grid-cols-3">
                    <button
                      v-for="item in yearMonths"
                      :key="`workspace-right-year-${item.monthIndex}`"
                      class="rounded-xl border border-base-300 p-3 text-left transition hover:border-primary/50 hover:bg-primary/5"
                      @click="openYearMonth(item.monthIndex)"
                    >
                      <p class="font-medium">{{ item.label }}</p>
                      <p class="text-xs text-base-content/60">{{ item.count }} events</p>
                      <p v-if="item.first" class="mt-1 text-xs text-base-content/70">
                        {{ formatDay(item.first.start) }} · {{ item.first.title }}
                      </p>
                    </button>
                  </div>

                  <div v-else class="mt-3 space-y-2">
                    <button
                      v-for="event in sortedEvents"
                      :key="`workspace-right-agenda-${event.id}`"
                      class="block w-full rounded-xl border border-base-300 p-3 text-left hover:bg-base-200/60"
                      @click="openThreadFromCalendarItem(event)"
                    >
                      <p class="font-medium">{{ event.title }}</p>
                      <p class="text-xs text-base-content/60">{{ event.contact }}</p>
                      <p class="text-xs text-base-content/60">{{ formatDay(event.start) }} · {{ formatTime(event.start) }} - {{ formatTime(event.end) }}</p>
                      <p class="mt-1 text-sm text-base-content/80">{{ event.note }}</p>
                    </button>
                  </div>
                </div>

                <div v-else-if="selectedCommThread" class="relative flex flex-col p-3">
                  <div class="mb-3 flex items-start justify-between gap-2 border-b border-base-300 pb-2">
                    <div>
                      <p class="font-medium">{{ selectedCommThread.contact }}</p>
                      <p class="text-xs text-base-content/60">{{ selectedCommThread.channels.join(" · ") }}</p>
                    </div>
                    <button class="btn btn-xs btn-outline">Call</button>
                  </div>

                  <div class="mb-3 flex items-center justify-between gap-2">
                    <div class="flex flex-wrap gap-2">
                      <button
                        v-for="channel in commChannelTabs"
                        :key="`comm-tab-${channel}`"
                        class="btn btn-xs btn-square"
                        :class="selectedCommChannel === channel ? 'btn-primary' : 'btn-ghost'"
                        :title="channel"
                        @click="selectedCommChannel = channel"
                      >
                        <svg v-if="channelIcon(channel) === 'all'" viewBox="0 0 24 24" class="h-4 w-4 fill-current">
                          <circle cx="7" cy="7" r="2.2" />
                          <circle cx="17" cy="7" r="2.2" />
                          <circle cx="7" cy="17" r="2.2" />
                          <circle cx="17" cy="17" r="2.2" />
                        </svg>
                        <svg v-else-if="channelIcon(channel) === 'telegram'" viewBox="0 0 24 24" class="h-4 w-4 fill-current">
                          <path d="M9.04 15.51 8.7 20.27c.49 0 .7-.21.96-.46l2.3-2.2 4.77 3.49c.88.49 1.5.23 1.74-.81l3.15-14.77.01-.01c.29-1.35-.49-1.88-1.35-1.56L1.74 11.08c-1.28.5-1.26 1.22-.22 1.54l4.74 1.48L17.3 7.03c.52-.34 1-.15.61.19" />
                        </svg>
                        <svg v-else-if="channelIcon(channel) === 'whatsapp'" viewBox="0 0 24 24" class="h-4 w-4 fill-current">
                          <path d="M20 3.99A9.94 9.94 0 0 0 12.01 1C6.49 1 2 5.49 2 11c0 1.76.46 3.49 1.33 5.03L2 23l7.17-1.88A9.95 9.95 0 0 0 12 21h.01c5.51 0 9.99-4.49 9.99-10.01 0-2.67-1.04-5.18-2.99-7m-7.99 15.32h-.01a8.3 8.3 0 0 1-4.23-1.16l-.3-.18-4.26 1.12 1.14-4.15-.2-.32a8.28 8.28 0 0 1-1.27-4.4c0-4.58 3.73-8.31 8.32-8.31a8.27 8.27 0 0 1 5.88 2.44 8.25 8.25 0 0 1 2.43 5.87c0 4.59-3.73 8.32-8.31 8.32m4.56-6.23c-.25-.12-1.49-.74-1.73-.82-.23-.09-.4-.12-.57.12s-.66.82-.81.99-.3.18-.55.06a6.7 6.7 0 0 1-1.97-1.21 7.43 7.43 0 0 1-1.38-1.71c-.14-.24-.01-.37.1-.49.11-.11.24-.3.36-.45.12-.14.16-.24.25-.39.08-.18.05-.3-.02-.42-.07-.12-.56-1.35-.77-1.85-.2-.48-.41-.41-.57-.42h-.48c-.16 0-.42.06-.64.3-.22.24-.84.82-.84 2s.86 2.31.98 2.48c.12.16 1.69 2.57 4.09 3.6.57.24 1.01.38 1.36.48.58.18 1.11.15 1.52.09.46-.06 1.49-.61 1.7-1.19.21-.58.21-1.09.15-1.19-.06-.11-.23-.17-.48-.3" />
                        </svg>
                        <svg v-else-if="channelIcon(channel) === 'instagram'" viewBox="0 0 24 24" class="h-4 w-4 fill-current">
                          <path d="M7 2h10a5 5 0 0 1 5 5v10a5 5 0 0 1-5 5H7a5 5 0 0 1-5-5V7a5 5 0 0 1 5-5m10 2H7a3 3 0 0 0-3 3v10a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V7a3 3 0 0 0-3-3m-5 3.5A4.5 4.5 0 1 1 7.5 12 4.5 4.5 0 0 1 12 7.5m0 2A2.5 2.5 0 1 0 14.5 12 2.5 2.5 0 0 0 12 9.5m4.8-3.2a1.2 1.2 0 1 1-1.2 1.2 1.2 1.2 0 0 1 1.2-1.2" />
                        </svg>
                        <svg v-else-if="channelIcon(channel) === 'email'" viewBox="0 0 24 24" class="h-4 w-4 fill-current">
                          <path d="M20 4H4a2 2 0 0 0-2 2v.4l10 5.6 10-5.6V6a2 2 0 0 0-2-2m0 4.2-7.4 4.14a1.25 1.25 0 0 1-1.2 0L4 8.2V18a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2z" />
                        </svg>
                        <svg v-else viewBox="0 0 24 24" class="h-4 w-4 fill-current">
                          <path d="M6.62 10.79a15.47 15.47 0 0 0 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1C10.07 21 3 13.93 3 5c0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.24.2 2.45.57 3.57.11.35.03.74-.25 1.02z" />
                        </svg>
                      </button>
                    </div>

                    <div class="flex min-w-0 items-center gap-1 rounded-lg border border-base-300 bg-base-100 px-1 py-1">
                      <button class="btn btn-ghost btn-xs btn-square" title="Previous pinned" @click="shiftPinned(-1)">↑</button>

                      <div class="min-w-0 px-1 text-xs">
                        <p v-if="currentPinnedItem?.kind === 'pin'" class="truncate text-base-content/85">
                          {{ currentPinnedItem.text }}
                        </p>
                        <p v-else-if="currentPinnedItem?.kind === 'event'" class="truncate text-base-content/85">
                          {{ currentPinnedItem.event.title }}
                        </p>
                        <p v-else class="truncate text-base-content/50">No pinned yet</p>
                      </div>

                      <button class="btn btn-ghost btn-xs btn-square" title="Next pinned" @click="shiftPinned(1)">↓</button>
                      <button class="btn btn-ghost btn-xs btn-square" title="Pinned and events" @click="showCommPinsOverlay = !showCommPinsOverlay">⋯</button>
                      <button class="btn btn-ghost btn-xs" @click="showCommPinsOverlay = !showCommPinsOverlay">Expand</button>
                    </div>
                  </div>

                  <div
                    v-if="showCommPinsOverlay"
                    class="absolute inset-0 z-20 bg-base-100/55 backdrop-blur-[1px]"
                    @click="showCommPinsOverlay = false"
                  >
                    <aside
                      class="absolute right-3 top-16 w-[340px] rounded-xl border border-base-300 bg-base-100 shadow-xl"
                      @click.stop
                    >
                      <div class="flex items-center justify-between border-b border-base-300 px-3 py-2">
                        <p class="text-xs font-semibold uppercase tracking-wide text-base-content/60">Pinned</p>
                        <button class="btn btn-ghost btn-xs btn-square" @click="showCommPinsOverlay = false">×</button>
                      </div>

                      <div class="max-h-[66vh] space-y-1 overflow-y-auto p-2">
                        <article
                          v-for="(item, index) in selectedCommPinnedStream"
                          :key="item.id"
                          class="rounded-lg border border-base-300 px-2.5 py-2"
                          :class="selectedPinnedIndex === index ? 'border-primary bg-primary/5' : ''"
                          @click="selectedPinnedIndex = index"
                        >
                          <template v-if="item.kind === 'pin'">
                            <p class="text-[11px] uppercase tracking-wide text-base-content/55">Note</p>
                            <p class="mt-1 text-xs leading-relaxed text-base-content/85">{{ item.text }}</p>
                          </template>
                          <template v-else>
                            <p class="text-[11px] uppercase tracking-wide text-base-content/55">Event</p>
                            <button class="mt-1 w-full text-left" @click="openEventFromCommunication(item.event)">
                              <p class="text-sm font-medium">{{ item.event.title }}</p>
                              <p class="text-xs text-base-content/65">
                                {{ formatDay(item.event.start) }} · {{ formatTime(item.event.start) }}
                              </p>
                            </button>
                          </template>
                        </article>

                        <p v-if="selectedCommPinnedStream.length === 0" class="px-1 py-2 text-xs text-base-content/55">
                          No pinned notes or events.
                        </p>
                      </div>
                    </aside>
                  </div>

                  <div class="space-y-2 pr-1">
                    <div v-for="entry in threadStreamItems" :key="entry.id">
                      <div v-if="entry.kind === 'call'" class="flex justify-center">
                        <div class="call-wave-card w-full max-w-[460px] rounded-2xl border border-base-300 px-4 py-3 text-center">
                          <div class="mb-2 flex items-center justify-center gap-2">
                            <button class="btn btn-xs btn-outline" @click="toggleCallTranscript(entry.item.id)">
                              <svg viewBox="0 0 24 24" class="h-3.5 w-3.5 fill-current">
                                <path d="M8 5v14l11-7z" />
                              </svg>
                            </button>
                            <span class="text-xs text-base-content/70">Transcript</span>
                          </div>
                          <div class="wave-bars mb-2">
                            <span v-for="n in 12" :key="`wave-${entry.item.id}-${n}`" :style="{ animationDelay: `${n * 0.08}s` }" />
                          </div>
                          <p class="mt-1 text-xs text-base-content/60">
                            <span>{{ entry.item.direction === "out" ? "↗" : "↙" }}</span>
                            <span class="mx-1">·</span>
                            <span>{{ formatStamp(entry.item.at) }}</span>
                            <span v-if="entry.item.duration"> · {{ entry.item.duration }}</span>
                          </p>
                          <div v-if="isCallTranscriptOpen(entry.item.id)" class="mt-2 rounded-xl border border-base-300 bg-base-100/70 p-2 text-left">
                            <p
                              v-for="(line, idx) in (entry.item.transcript ?? [entry.item.text])"
                              :key="`transcript-${entry.item.id}-${idx}`"
                              class="text-xs leading-relaxed text-base-content/80"
                            >
                              {{ line }}
                            </p>
                          </div>
                        </div>
                      </div>

                      <div v-else-if="entry.kind === 'eventAlert'" class="flex justify-center">
                        <article class="w-full max-w-[460px] rounded-xl border border-error/45 bg-error/10 p-3 text-center">
                          <p class="text-[11px] font-semibold uppercase tracking-wide text-error/80">Event in 15 minutes</p>
                          <p class="mt-1 text-sm font-semibold text-base-content">{{ entry.event.title }}</p>
                          <p class="mt-1 text-xs text-base-content/75">{{ formatTime(entry.event.start) }} · {{ entry.event.contact }}</p>
                          <button class="btn btn-xs btn-outline mt-2" @click="openEventFromCommunication(entry.event)">Open calendar</button>
                        </article>
                      </div>

                      <div v-else-if="entry.kind === 'recommendation'" class="flex justify-center">
                        <article class="w-full max-w-[460px] rounded-xl border border-base-300 bg-base-100 p-3">
                          <p class="text-sm">{{ entry.card.text }}</p>

                          <div class="mt-2 rounded-lg border border-base-300 bg-base-200/30 p-2">
                            <p class="text-xs font-semibold uppercase tracking-wide text-base-content/70">{{ entry.card.proposal.title }}</p>
                            <p
                              v-for="line in entry.card.proposal.details"
                              :key="`${entry.card.id}-${line}`"
                              class="mt-1 text-xs text-base-content/80"
                            >
                              {{ line }}
                            </p>
                          </div>

                          <div v-if="entry.card.decision === 'pending'" class="mt-2 flex gap-2">
                            <button class="btn btn-xs flex-1" @click="decideFeedCard(entry.card, 'accepted')">Yes</button>
                            <button class="btn btn-xs btn-outline flex-1" @click="decideFeedCard(entry.card, 'rejected')">No</button>
                          </div>
                          <p v-else class="mt-2 text-xs text-base-content/70">{{ entry.card.decisionNote }}</p>
                        </article>
                      </div>

                      <div
                        v-else
                        class="flex"
                        :class="entry.item.direction === 'out' ? 'justify-end' : 'justify-start'"
                      >
                        <div class="max-w-[88%] rounded-xl border border-base-300 p-3" :class="entry.item.direction === 'out' ? 'bg-base-200' : 'bg-base-100'">
                          <p class="text-sm">{{ entry.item.text }}</p>
                          <p class="mt-1 text-xs text-base-content/60">
                            <span class="mr-1 inline-flex h-4 w-4 items-center justify-center align-middle">
                              <svg v-if="channelIcon(entry.item.channel) === 'telegram'" viewBox="0 0 24 24" class="h-3.5 w-3.5 fill-current">
                                <path d="M9.04 15.51 8.7 20.27c.49 0 .7-.21.96-.46l2.3-2.2 4.77 3.49c.88.49 1.5.23 1.74-.81l3.15-14.77.01-.01c.29-1.35-.49-1.88-1.35-1.56L1.74 11.08c-1.28.5-1.26 1.22-.22 1.54l4.74 1.48L17.3 7.03c.52-.34 1-.15.61.19" />
                              </svg>
                              <svg v-else-if="channelIcon(entry.item.channel) === 'whatsapp'" viewBox="0 0 24 24" class="h-3.5 w-3.5 fill-current">
                                <path d="M20 3.99A9.94 9.94 0 0 0 12.01 1C6.49 1 2 5.49 2 11c0 1.76.46 3.49 1.33 5.03L2 23l7.17-1.88A9.95 9.95 0 0 0 12 21h.01c5.51 0 9.99-4.49 9.99-10.01 0-2.67-1.04-5.18-2.99-7m-7.99 15.32h-.01a8.3 8.3 0 0 1-4.23-1.16l-.3-.18-4.26 1.12 1.14-4.15-.2-.32a8.28 8.28 0 0 1-1.27-4.4c0-4.58 3.73-8.31 8.32-8.31a8.27 8.27 0 0 1 5.88 2.44 8.25 8.25 0 0 1 2.43 5.87c0 4.59-3.73 8.32-8.31 8.32m4.56-6.23c-.25-.12-1.49-.74-1.73-.82-.23-.09-.4-.12-.57.12s-.66.82-.81.99-.3.18-.55.06a6.7 6.7 0 0 1-1.97-1.21 7.43 7.43 0 0 1-1.38-1.71c-.14-.24-.01-.37.1-.49.11-.11.24-.3.36-.45.12-.14.16-.24.25-.39.08-.18.05-.3-.02-.42-.07-.12-.56-1.35-.77-1.85-.2-.48-.41-.41-.57-.42h-.48c-.16 0-.42.06-.64.3-.22.24-.84.82-.84 2s.86 2.31.98 2.48c.12.16 1.69 2.57 4.09 3.6.57.24 1.01.38 1.36.48.58.18 1.11.15 1.52.09.46-.06 1.49-.61 1.7-1.19.21-.58.21-1.09.15-1.19-.06-.11-.23-.17-.48-.3" />
                              </svg>
                              <svg v-else-if="channelIcon(entry.item.channel) === 'instagram'" viewBox="0 0 24 24" class="h-3.5 w-3.5 fill-current">
                                <path d="M7 2h10a5 5 0 0 1 5 5v10a5 5 0 0 1-5 5H7a5 5 0 0 1-5-5V7a5 5 0 0 1 5-5m10 2H7a3 3 0 0 0-3 3v10a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V7a3 3 0 0 0-3-3m-5 3.5A4.5 4.5 0 1 1 7.5 12 4.5 4.5 0 0 1 12 7.5m0 2A2.5 2.5 0 1 0 14.5 12 2.5 2.5 0 0 0 12 9.5m4.8-3.2a1.2 1.2 0 1 1-1.2 1.2 1.2 1.2 0 0 1 1.2-1.2" />
                              </svg>
                              <svg v-else-if="channelIcon(entry.item.channel) === 'email'" viewBox="0 0 24 24" class="h-3.5 w-3.5 fill-current">
                                <path d="M20 4H4a2 2 0 0 0-2 2v.4l10 5.6 10-5.6V6a2 2 0 0 0-2-2m0 4.2-7.4 4.14a1.25 1.25 0 0 1-1.2 0L4 8.2V18a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2z" />
                              </svg>
                              <svg v-else viewBox="0 0 24 24" class="h-3.5 w-3.5 fill-current">
                                <path d="M6.62 10.79a15.47 15.47 0 0 0 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1C10.07 21 3 13.93 3 5c0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.24.2 2.45.57 3.57.11.35.03.74-.25 1.02z" />
                              </svg>
                            </span>
                            <span>{{ formatStamp(entry.item.at) }}</span>
                          </p>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>

                <div v-else class="flex h-full items-center justify-center text-sm text-base-content/60">
                  No communication history.
                </div>
              </article>

              <aside class="min-h-0 rounded-xl border border-base-300">
                <div v-if="selectedWorkspaceContact" class="h-full p-3">
                  <div class="border-b border-base-300 pb-2">
                    <p class="font-medium">{{ selectedWorkspaceContact.name }}</p>
                    <p class="text-xs text-base-content/60">
                      {{ selectedWorkspaceContact.company }} · {{ selectedWorkspaceContact.location }}, {{ selectedWorkspaceContact.country }}
                    </p>
                    <p class="mt-1 text-xs text-base-content/55">
                      Last contact · {{ formatStamp(selectedWorkspaceContact.lastContactAt) }}
                    </p>
                  </div>

                  <div v-if="selectedWorkspaceDeal" class="mt-3 rounded-xl border border-base-300 bg-base-200/30 p-2.5">
                    <p class="text-[10px] font-semibold uppercase tracking-wide text-base-content/55">Deal</p>
                    <p class="mt-1 text-sm font-medium">{{ selectedWorkspaceDeal.title }}</p>
                    <p class="mt-1 text-[11px] text-base-content/65">{{ selectedWorkspaceDeal.company }} · {{ selectedWorkspaceDeal.stage }}</p>
                    <p class="mt-1 text-[11px] text-base-content/80">{{ selectedWorkspaceDeal.nextStep }}</p>
                  </div>

                  <div class="mt-3">
                    <p class="mb-2 text-xs font-semibold uppercase tracking-wide text-base-content/60">Summary</p>
                    <ContactCollaborativeEditor
                      :key="`contact-summary-${selectedWorkspaceContact.id}`"
                      v-model="selectedWorkspaceContact.description"
                      :room="`crm-contact-${selectedWorkspaceContact.id}`"
                      placeholder="Contact summary..."
                    />
                  </div>
                </div>

                <div v-else class="flex h-full items-center justify-center text-sm text-base-content/60">
                  No contact selected.
                </div>
              </aside>
            </div>
            </section>

            <section v-else-if="selectedTab === 'documents'" class="space-y-3">
            <div class="rounded-xl border border-base-300 p-3">
              <div class="grid gap-2 md:grid-cols-[1fr_220px]">
                <label class="form-control">
                  <span class="label-text text-xs uppercase tracking-wide text-base-content/60">Search docs</span>
                  <input
                    v-model="documentSearch"
                    type="text"
                    class="input input-bordered input-sm"
                    placeholder="Title, owner, scope, content"
                  >
                </label>

                <label class="form-control">
                  <span class="label-text text-xs uppercase tracking-wide text-base-content/60">Type</span>
                  <select v-model="selectedDocumentType" class="select select-bordered select-sm">
                    <option v-for="item in documentTypes" :key="`doc-type-${item}`" :value="item">{{ item }}</option>
                  </select>
                </label>
              </div>
            </div>

            <div class="grid gap-3 md:grid-cols-12">
              <aside class="min-h-0 rounded-xl border border-base-300 md:col-span-4">
                <div class="min-h-0 space-y-2 overflow-y-auto p-2">
                  <button
                    v-for="doc in filteredDocuments"
                    :key="doc.id"
                    class="w-full rounded-xl border border-base-300 p-3 text-left transition hover:bg-base-200/60"
                    :class="selectedDocumentId === doc.id ? 'border-primary bg-primary/5' : ''"
                    @click="selectedDocumentId = doc.id"
                  >
                    <p class="font-medium">{{ doc.title }}</p>
                    <p class="mt-1 text-xs text-base-content/60">{{ doc.type }} · {{ doc.owner }}</p>
                    <p class="mt-1 line-clamp-2 text-xs text-base-content/75">{{ doc.summary }}</p>
                    <p class="mt-1 text-xs text-base-content/55">Updated {{ formatStamp(doc.updatedAt) }}</p>
                  </button>
                </div>
              </aside>

              <article class="min-h-0 rounded-xl border border-base-300 md:col-span-8">
                <div v-if="selectedDocument" class="p-3 md:p-4">
                  <div class="border-b border-base-300 pb-2">
                    <p class="font-medium">{{ selectedDocument.title }}</p>
                    <p class="text-xs text-base-content/60">
                      {{ selectedDocument.type }} · {{ selectedDocument.scope }} · {{ selectedDocument.owner }}
                    </p>
                    <p class="mt-1 text-sm text-base-content/80">{{ selectedDocument.summary }}</p>
                  </div>

                  <div class="mt-3">
                    <ContactCollaborativeEditor
                      :key="`doc-editor-${selectedDocument.id}`"
                      v-model="selectedDocument.body"
                      :room="`crm-doc-${selectedDocument.id}`"
                      placeholder="Describe policy, steps, rules, and exceptions..."
                    />
                  </div>
                </div>

                <div v-else class="flex h-full items-center justify-center text-sm text-base-content/60">
                  No document selected.
                </div>
              </article>
            </div>
            </section>

          </div>

        </div>
      </main>
    </div>

    <nav class="dock-fixed pointer-events-none fixed left-1/2 z-40 -translate-x-1/2">
      <div class="dock-nav pointer-events-auto inline-flex items-center gap-1 rounded-2xl border border-base-300 px-2 py-1.5">
        <button
          v-for="tab in tabs"
          :key="`dock-${tab.id}`"
          class="btn btn-ghost btn-sm btn-square"
          :class="selectedTab === tab.id ? 'btn-primary' : ''"
          :title="tab.label"
          @click="selectedTab = tab.id"
        >
          <svg v-if="tab.id === 'communications'" viewBox="0 0 24 24" class="h-4 w-4 fill-current">
            <path d="M20 2H4a2 2 0 0 0-2 2v18l4-4h14a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2" />
          </svg>
          <svg v-else-if="tab.id === 'documents'" viewBox="0 0 24 24" class="h-4 w-4 fill-current">
            <path d="M6 2h9l5 5v15a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2m8 1.5V8h4.5z" />
          </svg>
          <svg v-else viewBox="0 0 24 24" class="h-4 w-4 fill-current">
            <path d="M3 3h18v4H3zm0 7h12v4H3zm0 7h18v4H3z" />
          </svg>
        </button>
      </div>
    </nav>
  </div>
</template>

<style scoped>
.feed-chart-wrap {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 12px;
  background:
    radial-gradient(circle at 20% 20%, rgba(30, 107, 255, 0.12), transparent 45%),
    radial-gradient(circle at 80% 80%, rgba(30, 107, 255, 0.08), transparent 45%),
    #f6f9ff;
  border-bottom: 1px solid rgba(30, 107, 255, 0.15);
}

.dock-nav {
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.94), rgba(255, 255, 255, 0.86));
  backdrop-filter: blur(8px);
  box-shadow: 0 8px 24px rgba(15, 23, 42, 0.1);
}

.dock-fixed {
  bottom: calc(0.75rem + env(safe-area-inset-bottom));
}

.feed-chart-bars {
  display: flex;
  align-items: flex-end;
  gap: 10px;
  width: 100%;
  max-width: 280px;
  height: 100%;
}

.feed-chart-bars span {
  flex: 1 1 0;
  border-radius: 999px 999px 6px 6px;
  background: linear-gradient(180deg, rgba(30, 107, 255, 0.9), rgba(30, 107, 255, 0.35));
}

.feed-chart-pie {
  width: min(140px, 70%);
  aspect-ratio: 1;
  border-radius: 999px;
  background: conic-gradient(
    rgba(30, 107, 255, 0.92) 0 42%,
    rgba(30, 107, 255, 0.55) 42% 73%,
    rgba(30, 107, 255, 0.25) 73% 100%
  );
  box-shadow: 0 8px 24px rgba(30, 107, 255, 0.2);
}

.call-wave-card {
  background:
    radial-gradient(circle at 50% 0%, rgba(59, 130, 246, 0.14), transparent 50%),
    linear-gradient(180deg, rgba(59, 130, 246, 0.05), transparent);
}

.wave-bars {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: 4px;
  height: 30px;
}

.wave-bars span {
  width: 4px;
  height: 18%;
  border-radius: 999px;
  background: rgba(30, 107, 255, 0.75);
  animation: wave-pulse 1.2s ease-in-out infinite;
}

@keyframes wave-pulse {
  0%, 100% {
    height: 20%;
    opacity: 0.45;
  }
  50% {
    height: 100%;
    opacity: 1;
  }
}
</style>
