/* Mock data: extends the provided JSON dataset with a few extra rows so lists/kanban feel populated.
   All identifiers and base records taken from uploads/businessteam_frontend_dataset.json. */

const ORG = {
  id: "org-business-team-demo",
  name: "BusinessTeam",
  workspace: "Demo Workspace",
};

const CURRENT_USER = {
  id: "guy-lansing-0030809",
  name: "Guy Lansing",
  initials: "GL",
  role: "Admin",
  email: "guy.lansing@nelc.es",
  linkedinConnected: true,
};

const USERS = [
  { ...CURRENT_USER, title: "VP Sales",                 team: "Revenue",          phone: "+34 600 12 34 56" },
  { id: "sales-lead-demo", name: "Sales Lead",     initials: "SL", role: "Sales Manager", email: "sales.lead@example.com",      linkedinConnected: false, title: "Senior Sales Manager",     team: "Revenue",        phone: "+34 600 22 33 44" },
  { id: "amelie-nadeau",   name: "Amélie Nadeau",  initials: "AN", role: "AE",            email: "amelie@businessteam.example", title: "Senior Account Executive", team: "Enterprise Sales", phone: "+33 6 14 28 99 02" },
  { id: "rohan-kapoor",    name: "Rohan Kapoor",   initials: "RK", role: "SDR",           email: "rohan@businessteam.example",  title: "Sales Development Rep",    team: "Outbound",         phone: "+44 7700 900 113" },
];

const NAV = [
  { id: "dashboard",     label: "Dashboard",     icon: "layout-dashboard" },
  { id: "accounts",      label: "Accounts",      icon: "building" },
  { id: "contacts",      label: "Contacts",      icon: "users" },
  { id: "conversations", label: "Conversations", icon: "messages" },
  { id: "opportunities", label: "Pipeline",      icon: "kanban" },
  { id: "calendar",      label: "Calendar",      icon: "calendar" },
  { id: "tasks",         label: "Tasks",         icon: "check-square" },
  { id: "content",       label: "Content",       icon: "library" },
  { id: "knowledge",     label: "Knowledge",     icon: "book" },
  { id: "automation",    label: "Automation",    icon: "send" },
  { id: "admin",         label: "Admin",         icon: "settings" },
];

const COMPANIES = [];

/* ─── Procedural extension: ~140 additional target accounts so the list is
   long enough to demo infinite-scroll. Same shape as the curated entries
   above; deterministic per-id so re-renders are stable. ─────────────────── */
const CONTACTS = [];

/* ─── Procedural extension: ~140 additional contacts spread across the
   extended company set so the contacts list demos infinite-scroll + filters
   too. Same shape as the curated entries. ─────────────────────────────── */
/* Conversations */
const CONVERSATIONS = [];

/* Pipeline opportunities */
const OPPORTUNITIES = [];

const OPPORTUNITY_STAGES = [
  { id: "research",       label: "Research",       tone: "neutral" },
  { id: "contacted",      label: "Contacted",      tone: "blue" },
  { id: "meeting_booked", label: "Meeting booked", tone: "violet" },
  { id: "discovery",      label: "Discovery",      tone: "warm" },
  { id: "proposal",       label: "Proposal",       tone: "warm" },
  { id: "negotiation",    label: "Negotiation",    tone: "warm" },
  { id: "won",            label: "Won",            tone: "green" },
];

/* Tasks */
const TASKS = [];

/* Calendar */
const CALENDAR_EVENTS = [];

/* Content library */
const CONTENT = [];

const CHANNEL_META = {
  linkedin:    { icon: "linkedin",       label: "LinkedIn",     color: "blue" },
  email:       { icon: "mail",           label: "Email",        color: "warm" },
  sms:         { icon: "message-circle", label: "SMS",          color: "green" },
  whatsapp:    { icon: "message-circle", label: "WhatsApp",     color: "green" },
  manual_note: { icon: "edit",           label: "Note",         color: "warm" },
  calendar:    { icon: "calendar",       label: "Calendar",     color: "violet" },
};

const SENIORITY_LABEL = {
  owner: "Owner", c_level: "C-level", vp: "VP", director: "Director",
  head: "Head", manager: "Manager", individual_contributor: "IC", unknown: "—",
};

const DEPT_LABEL = {
  human_resources: "Human Resources", finance: "Finance", marketing: "Marketing",
  sales: "Sales", engineering: "Engineering", operations: "Operations",
  legal: "Legal", procurement: "Procurement", customer_success: "Customer Success",
  product: "Product", business_owner: "Business owner", unknown: "—",
};

const LIFECYCLE_LABEL = {
  sourced: "Sourced", target: "Target", engaged: "Engaged",
  opportunity: "Opportunity", customer: "Customer", expansion: "Expansion",
};

/* ─── API → app shape adapter ─────────────────────────────────────────
   The internal /companies endpoint returns a much richer payload than our
   legacy mock — score breakdowns, locations, language footprint, etc.
   We adapt each record into the shape the existing pages expect, while
   preserving the full raw record under `.api` so detail views can surface
   the new fields without forcing a rewrite of every consumer.

   Sample payload sits at uploads/call-companies-test.json; api-companies.js
   ships it as window.API_COMPANIES_RAW.
   ─────────────────────────────────────────────────────────────────── */

/* Map executive_english_target_tier → lifecycleStage so the existing
   lifecycle pill/groupings keep working. The tier *is* the relevant signal
   for this dataset (sales-priority for the Executive English product). */
const TIER_TO_LIFECYCLE = {
  strong_target: "opportunity",
  medium_target: "engaged",
  potential:     "target",
  low_priority:  "sourced",
  very_low:      "sourced",
};
const TIER_LABEL = {
  strong_target: "Strong target",
  medium_target: "Medium target",
  potential:     "Potential",
  low_priority:  "Low priority",
  very_low:      "Very low",
};
const TIER_TONE = {
  strong_target: "green",
  medium_target: "violet",
  potential:     "blue",
  low_priority:  "warm",
  very_low:      "neutral",
};

/* Convert messy/loose employee_range strings into the bucket labels used
   by the legacy column filters. */
function normalizeEmployeeRange(s) {
  if (!s) return "—";
  const t = s.replace(/\s+/g, "").replace(/–/g, "-").toLowerCase();
  if (t === "1-50" || t === "0-50" || t === "<50")      return "<50";
  if (t === "51-200" || t === "50-200")                 return "51-200";
  if (t === "201-500")                                  return "201-500";
  if (t === "501-1000" || t === "501-1k")               return "501–1k";
  if (t === "1001-5000" || t === "1k-5k")               return "1k-5k";
  if (t === "5001-10000" || t === "5k-10k")             return "5k-10k";
  if (t === "10001+" || t === "10000+" || t === "10k+") return "10k+";
  return s;
}

/* Country name lookups for two-letter codes (covers everything in the sample
   payload — add more as data widens). Falls back to the raw code. */
const COUNTRY_NAMES = {
  ES: "Spain", PT: "Portugal", FR: "France", DE: "Germany", IT: "Italy",
  GB: "United Kingdom", UK: "United Kingdom", IE: "Ireland", NL: "Netherlands",
  BE: "Belgium", LU: "Luxembourg", CH: "Switzerland", AT: "Austria",
  DK: "Denmark", SE: "Sweden", NO: "Norway", FI: "Finland",
  PL: "Poland", CZ: "Czech Republic", HU: "Hungary", RO: "Romania",
  BG: "Bulgaria", GR: "Greece", US: "United States", CA: "Canada",
  MX: "Mexico", BR: "Brazil", AR: "Argentina", CL: "Chile", CO: "Colombia",
  PE: "Peru", AU: "Australia", NZ: "New Zealand", JP: "Japan", CN: "China",
  IN: "India", SG: "Singapore",
};
function countryName(code) { return COUNTRY_NAMES[code] || code; }

function adaptApiCompany(api) {
  const tier = api.executive_english_target_tier || "low_priority";
  /* The endpoint's executive_english_target_score is 0–10; surface it as 0–100
     so it can drive the existing 0–100 ScoreRing component. */
  const priorityScore = Math.round((api.executive_english_target_score || 0) * 10);
  const intentScore   = Math.round((api.executive_english_need_score   || 0) * 10);
  const fitScore      = Math.round((api.internationalization_score      || 0) * 10);
  /* Relationship score isn't in the API yet — derive a placeholder so the
     existing UI components don't show NaN. */
  const relationshipScore = Math.min(100, Math.round((api.follower_count || 0) / 1500));

  const tags = ["target-account"];
  if (api.related_to_spain) tags.push("spain");
  if (api.regional_tld)     tags.push("regional-tld");
  if (api.operatingCountryCount > 5) tags.push("multinational");

  return {
    /* legacy fields ── consumed by lists, kanban, contact-link, etc. */
    id:            String(api.company_id),
    name:          api.company_name,
    domain:        api.domain,
    logoUrl:       api.logo_url,
    description:   api.description || api.tagline || "",
    industry:      api.industry || (api.industries && api.industries[0]) || "—",
    employeeCount: api.employee_count || 0,
    employeeRange: normalizeEmployeeRange(api.employee_range),
    yearFounded:   api.year_founded,
    hqCity:        api.hq_city || "—",
    hqCountry:     countryName(api.hq_country),
    gtmPriority:   api.gtm_priority === "very_low" ? "low" : (api.gtm_priority || "low"),
    tags,
    technologies:  [],
    competitors:   [],
    specialties:   (api.specialties || "").split(",").map(s => s.trim()).filter(Boolean),
    abm: {
      lifecycleStage: TIER_TO_LIFECYCLE[tier] || "sourced",
      fitScore, intentScore, relationshipScore, priorityScore,
      openOpportunitiesCount: 0,
      stakeholdersCount: 0,
      connectedStakeholdersCount: 0,
      lastEngagementAt: null,
      nextBestAction: api.executive_english_sales_reason
        || "Review account profile and start outbound.",
    },
    owner: "guy-lansing-0030809",
    /* rich raw payload — surfaced by the detail page when present */
    api,
  };
}

/* Merge the API sample data in at the top of COMPANIES so the new records
   are the first thing the user sees. The function is idempotent (dedupes
   by id) so boot-api.jsx can re-run it after a live /companies fetch. */
function mergeApiCompanies() {
  const raw = (window.API_COMPANIES_RAW && window.API_COMPANIES_RAW.data) || [];
  if (!raw.length) return 0;
  const adapted = raw.map(adaptApiCompany);
  const incomingIds = new Set(adapted.map(c => c.id));
  for (let i = COMPANIES.length - 1; i >= 0; i--) {
    if (incomingIds.has(COMPANIES[i].id)) COMPANIES.splice(i, 1);
  }
  COMPANIES.unshift(...adapted);
  return adapted.length;
}
/* Backfill helper — adapts ONLY the new records and appends to the end
   of the COMPANIES list. Keeps the original first-page records pinned
   at the top so progressive pagination doesn't visibly reshuffle. */
function appendApiCompanies(newRecords) {
  if (!Array.isArray(newRecords) || !newRecords.length) return 0;
  const adapted = newRecords.map(adaptApiCompany);
  const incomingIds = new Set(adapted.map(c => c.id));
  for (let i = COMPANIES.length - 1; i >= 0; i--) {
    if (incomingIds.has(COMPANIES[i].id)) COMPANIES.splice(i, 1);
  }
  COMPANIES.push(...adapted);
  return adapted.length;
}
/* Run once at boot against whatever static seed shipped with the bundle. */
mergeApiCompanies();

/* helpers */
function fmtRelative(iso) {
  if (!iso) return "—";
  const t = new Date(iso).getTime();
  const now = Date.now();
  const diff = (now - t) / 1000;
  if (diff < 60) return "just now";
  if (diff < 3600) return Math.round(diff / 60) + "m ago";
  if (diff < 86400) return Math.round(diff / 3600) + "h ago";
  if (diff < 604800) return Math.round(diff / 86400) + "d ago";
  const d = new Date(iso);
  return d.toLocaleDateString("en-GB", { day: "2-digit", month: "short" });
}
function fmtDate(iso, opts) {
  if (!iso) return "—";
  return new Date(iso).toLocaleDateString("en-GB", opts || { day: "2-digit", month: "short", year: "numeric" });
}
function fmtTime(iso) {
  if (!iso) return "";
  return new Date(iso).toLocaleTimeString("en-GB", { hour: "2-digit", minute: "2-digit" });
}
function fmtCurrency(value, currency) {
  if (!value && value !== 0) return "—";
  return new Intl.NumberFormat("en-GB", { style: "currency", currency: currency || "EUR", maximumFractionDigits: 0 }).format(value);
}
function getCompany(id) { return COMPANIES.find(c => c.id === id); }
function getContact(id) { return CONTACTS.find(c => c.id === id); }
function getUser(id)    { return USERS.find(u => u.id === id); }
function initials(name) {
  if (!name) return "?";
  const parts = name.trim().split(/\s+/);
  return ((parts[0]?.[0] || "") + (parts[1]?.[0] || "")).toUpperCase();
}
/* Deterministic warm-ish color for avatar fallback from string */
function colorFromString(s) {
  if (!s) return "oklch(0.85 0.02 80)";
  let h = 0;
  for (const c of s) h = (h * 31 + c.charCodeAt(0)) % 360;
  return `oklch(0.78 0.06 ${h})`;
}

/* ───────────────────────────────────────────────────────────────────
   API contacts ingestion
   ───────────────────────────────────────────────────────────────────
   Sample payload sits at uploads/call-contacts-test.json; api-contacts.js
   ships it as window.API_CONTACTS_RAW. Each LinkedIn-style profile is
   adapted to the internal CONTACTS shape (so the lists/kanban/sort all
   keep working) while preserving the full raw payload under `.raw` so
   the detail UI can render skills, languages, certifications, etc. */

function pickPicture(pic, preferredHeight = 200) {
  if (!pic) return null;
  const sizes = pic.sizes || [];
  /* Prefer the size closest to `preferredHeight`, else fall back to the
     headline URL. */
  let best = null;
  let bestDelta = Infinity;
  for (const s of sizes) {
    const d = Math.abs((s.height || 0) - preferredHeight);
    if (d < bestDelta) { bestDelta = d; best = s; }
  }
  return (best && best.url) || pic.url || null;
}

function deriveAbmFromApi(api) {
  /* No CRM-side relationship signal in this payload — derive sensible
     placeholders so the existing UI doesn't show NaN scores. */
  const connections   = api.connectionsCount || 0;
  const followers     = api.followerCount    || 0;
  const seniorityRank = ({ c_level: 100, vp: 85, director: 70, head: 60, manager: 45,
                           individual_contributor: 25, owner: 80, unknown: 30 })
                       [api.currentPosition?.[0]?.roleEnrichment?.seniority] || 30;
  const verifiedBoost = api.verified ? 10 : 0;
  const intentScore = Math.min(95, Math.round(40 + (followers / 200) + verifiedBoost));
  const engagementScore   = Math.min(90, Math.round(20 + (connections / 80)));
  const relationshipStrength = api.openToWork ? 25 : Math.min(60, Math.round(connections / 120));
  const composeReason = api.composeOptionType === "PREMIUM_INMAIL"
    ? "Premium InMail recommended — connection limit reached."
    : "Upsell warm intro — connection slot available.";
  return {
    persona: api.currentPosition?.[0]?.roleEnrichment?.department === "human_resources"
      ? "HR decision maker"
      : (api.currentPosition?.[0]?.position || "Stakeholder"),
    buyingCommitteeRole:
      seniorityRank >= 85 ? "economic_buyer" :
      seniorityRank >= 70 ? "decision_maker" :
      seniorityRank >= 45 ? "influencer" : "end_user",
    relationshipStrength, engagementScore, intentScore,
    lastSignal: api.openToWork ? "Open to work" : (api.hiring ? "Currently hiring" : "Imported from LinkedIn search"),
    weakBuyingSignals: [
      api.openToWork && "Open to new opportunities",
      api.hiring && "Hiring signal",
      api.premium && "LinkedIn Premium",
      api.influencer && "LinkedIn Influencer",
      api.verified && "Verified profile",
    ].filter(Boolean),
    recommendedNextAction: composeReason,
  };
}

function adaptApiContact(api) {
  const cur = (api.currentPosition && api.currentPosition[0]) || {};
  const enr = cur.roleEnrichment || {};
  const primaryEmail = (api.emails || []).find(e => e.status === "valid") || (api.emails || [])[0];
  return {
    id:                 api.objectUrn || api.linkedinContactId || api.id,
    publicIdentifier:   api.publicIdentifier,
    linkedinUrl:        api.linkedinUrl,
    firstName:          api.firstName,
    lastName:           api.lastName,
    headline:           api.headline,
    about:              api.about,
    profilePictureUrl:  pickPicture(api.profilePicture, 200),
    coverPictureUrl:    pickPicture(api.coverPicture, 350),
    location:           api.location?.linkedinText || api.location?.parsed?.text || "—",
    locationCity:       api.location?.parsed?.city,
    locationCountry:    api.location?.parsed?.country,
    connectionsCount:   api.connectionsCount,
    followerCount:      api.followerCount,
    verified:           !!api.verified,
    premium:            !!api.premium,
    openToWork:         !!api.openToWork,
    hiring:             !!api.hiring,
    influencer:         !!api.influencer,
    composeOptionType:  api.composeOptionType,
    companyId:          String(cur.companyId || ""),
    companyName:        cur.companyName,
    companyLogoUrl:     pickPicture(cur.companyLogo, 100),
    companyLinkedinUrl: cur.companyLinkedinUrl,
    companyWebsites:    api.companyWebsites || [],
    position:           cur.position || api.headline,
    department:         enr.department || "unknown",
    seniority:          enr.seniority  || "unknown",
    tenure:             cur.duration,
    workplaceType:      cur.workplaceType,
    employmentType:     cur.employmentType,
    positionStart:      cur.startDate?.text,
    positionEnd:        cur.endDate?.text,
    primaryEmail,
    emails:             api.emails || [],
    linkedinStatus:     "none", /* no CRM relationship data in this payload */
    /* Rich extras for detail views */
    languages:          (api.languages || []).map(l => l.name + (l.proficiency ? ` · ${shortenProficiency(l.proficiency)}` : "")),
    languagesRich:      api.languages || [],
    skills:             api.skills    || [],
    topSkills:          (api.skills   || []).slice(0, 5).map(s => s.name),
    certifications:     api.certifications || [],
    honorsAndAwards:    api.honorsAndAwards || [],
    publications:       api.publications || [],
    projects:           api.projects   || [],
    patents:            api.patents    || [],
    volunteering:       api.volunteering || [],
    organizations:      api.organizations || [],
    courses:            api.courses    || [],
    causes:             api.causes     || [],
    moreProfiles:       api.moreProfiles || [],
    registeredAt:       api.registeredAt,
    updatedAt:          api.updatedAt,
    abm: deriveAbmFromApi(api),
    experience: (api.experience || []).map(ex => ({
      companyId:     String(ex.companyId || ""),
      company:       ex.companyName,
      companyLogo:   pickPicture(ex.companyLogo, 100),
      position:      ex.position,
      period:        ex.startDate?.text
                       ? `${ex.startDate.text} — ${ex.endDate?.text || "Present"}`
                       : (ex.endDate?.text || ""),
      duration:      ex.duration,
      location:      ex.location,
      employmentType: ex.employmentType,
      workplaceType: ex.workplaceType,
      description:   ex.description,
      skills:        ex.skills || [],
    })),
    education: (api.education || []).map(ed => ({
      school:      ed.schoolName,
      schoolLogo:  pickPicture(ed.schoolLogo, 100),
      degree:      ed.degree,
      field:       ed.fieldOfStudy,
      period:      ed.period || [ed.startDate?.text, ed.endDate?.text].filter(Boolean).join(" — "),
      description: ed.description,
      activities:  ed.activities,
    })),
    /* Keep raw around for any field the UI doesn't surface yet. */
    raw: api,
  };
}

function shortenProficiency(p) {
  if (!p) return "";
  const t = p.toLowerCase();
  if (t.includes("native")) return "native";
  if (t.includes("full"))   return "full";
  if (t.includes("professional working")) return "professional";
  if (t.includes("limited")) return "limited";
  if (t.includes("elementary")) return "elementary";
  return t;
}

/* Auto-create a COMPANIES entry for each unseen company referenced by an
   API contact's currentPosition. Keeps account lookup, account-filter
   chips, and conversation grouping all working without manual seeding. */
function ensureCompanyForApiContact(api) {
  const cur = api.currentPosition?.[0];
  if (!cur || !cur.companyId) return;
  const id = String(cur.companyId);
  if (COMPANIES.some(c => c.id === id)) return;
  const websiteDomain = (api.companyWebsites && api.companyWebsites[0]?.domain) || null;
  COMPANIES.push({
    id,
    name:         cur.companyName,
    domain:       websiteDomain,
    logoUrl:      pickPicture(cur.companyLogo, 200),
    description:  "",
    industry:     "—",
    employeeCount: 0,
    employeeRange: "—",
    yearFounded:  null,
    hqCity:       cur.location || "—",
    hqCountry:    api.location?.parsed?.country || "—",
    gtmPriority:  "medium",
    tags:         ["api-imported"],
    technologies: [], competitors: [], specialties: [],
    abm: {
      lifecycleStage: "target",
      fitScore: 0, intentScore: 0, relationshipScore: 0, priorityScore: 0,
      openOpportunitiesCount: 0, stakeholdersCount: 0, connectedStakeholdersCount: 0,
      lastEngagementAt: null,
      nextBestAction: "Imported via LinkedIn search — enrich and qualify.",
    },
    owner: "guy-lansing-0030809",
    linkedinUrl: cur.companyLinkedinUrl,
  });
}

function mergeApiContacts() {
  const raw = (window.API_CONTACTS_RAW && window.API_CONTACTS_RAW.data) || [];
  if (!raw.length) return 0;
  raw.forEach(ensureCompanyForApiContact);
  const adapted = raw.map(adaptApiContact);
  /* Drop any pre-existing mock with the same id, then prepend so the
     API-sourced rows appear at the top of the Contacts list. */
  const ids = new Set(adapted.map(c => c.id));
  for (let i = CONTACTS.length - 1; i >= 0; i--) {
    if (ids.has(CONTACTS[i].id)) CONTACTS.splice(i, 1);
  }
  CONTACTS.unshift(...adapted);
  return adapted.length;
}
/* Backfill helper — adapts ONLY the new records and appends them. The
   first-page records keep their lead position; pages 2+ trail behind. */
function appendApiContacts(newRecords) {
  if (!Array.isArray(newRecords) || !newRecords.length) return 0;
  newRecords.forEach(ensureCompanyForApiContact);
  const adapted = newRecords.map(adaptApiContact);
  const ids = new Set(adapted.map(c => c.id));
  for (let i = CONTACTS.length - 1; i >= 0; i--) {
    if (ids.has(CONTACTS[i].id)) CONTACTS.splice(i, 1);
  }
  CONTACTS.push(...adapted);
  return adapted.length;
}
mergeApiContacts();

Object.assign(window, {
  ORG, CURRENT_USER, USERS, NAV,
  COMPANIES, CONTACTS, CONVERSATIONS, OPPORTUNITIES, OPPORTUNITY_STAGES,
  TASKS, CALENDAR_EVENTS, CONTENT,
  CHANNEL_META, SENIORITY_LABEL, DEPT_LABEL, LIFECYCLE_LABEL,
  TIER_LABEL, TIER_TONE, TIER_TO_LIFECYCLE, countryName,
  fmtRelative, fmtDate, fmtTime, fmtCurrency,
  getCompany, getContact, getUser, initials, colorFromString,
  pickPicture,
  /* Live-API integration: boot-api.jsx swaps payloads into the *_RAW
     containers and re-runs these to refresh the in-memory stores. */
  adaptApiCompany, adaptApiContact,
  mergeApiCompanies, mergeApiContacts,
  appendApiCompanies, appendApiContacts,
  ensureCompanyForApiContact,
});
