import React, { useEffect, useMemo, useState } from "react";
import { createRoot } from "react-dom/client";

type BuyerInput = {
  clientName: string;
  agentName: string;
  meetingDate: string;
  budgetMin: string;
  budgetMax: string;
  timeline: string;
  financingStatus: string;
  propertyType: string;
  bedrooms: string;
  bathrooms: string;
  parkingNeeds: string;
  mustHaves: string[];
  niceToHaves: string[];
  dealBreakers: string[];
  designPreferences: string;
  lifestyleNotes: string;
  neighbourhoods: string[];
  agentNotes: string;
};

type Neighbourhood = {
  name: string;
  description: string;
  pricePoint: string;
  buyerFit: string;
  keywords: string[];
  mapQuery: string;
};

type NeighbourhoodMarketData = {
  sales: number;
  active: number;
  monthsInventory: number;
  avgPrice: number;
  avgDom: number;
  overAsk: number;
};

type GeneratedBrief = {
  buyerSummary: string;
  criteriaSummary: string;
  whatMattersMost: string;
  neighbourhoodSections: Array<Neighbourhood & { whyItFits: string }>;
  nextSteps: string;
  email: { subject: string; body: string };
};

type SavedBriefMeta = {
  clientSlug: string;
  sharePath: string;
  clientUrl?: string;
  agentPath?: string;
  agentUrl?: string;
};

type StoredBrief = {
  input: BuyerInput;
  brief: GeneratedBrief;
  meta?: SavedBriefMeta;
};

const storageKey = "the-central-buyer-search-brief";
const appsScriptEndpoint = "https://script.google.com/macros/s/AKfycbztJBc_ZcbiOS7_OM0uSUqb-PGONIn9KpujIIRy0__GlNLag4PsgfvqdOl87Yzg9A1G/exec";

const neighbourhoodMarketData: Record<string, NeighbourhoodMarketData> = {
  "Forest Hill": { sales: 100, active: 59, monthsInventory: 7.1, avgPrice: 2627588, avgDom: 38, overAsk: 14 },
  "King West": { sales: 100, active: 265, monthsInventory: 31.8, avgPrice: 665569, avgDom: 32, overAsk: 14 },
  "Forest Hill North": { sales: 62, active: 23, monthsInventory: 4.5, avgPrice: 2204617, avgDom: 26, overAsk: 11 },
  "Casa Loma": { sales: 100, active: 62, monthsInventory: 7.4, avgPrice: 2221305, avgDom: 42, overAsk: 16 },
  "Yonge & St. Clair": { sales: 100, active: 68, monthsInventory: 8.2, avgPrice: 1828611, avgDom: 31, overAsk: 16 },
  "The Annex": { sales: 100, active: 281, monthsInventory: 33.7, avgPrice: 1392888, avgDom: 37, overAsk: 25 },
  "Cabbagetown": { sales: 100, active: 76, monthsInventory: 9.1, avgPrice: 694530, avgDom: 40, overAsk: 20 },
  "Lawrence Park": { sales: 100, active: 73, monthsInventory: 8.8, avgPrice: 2567719, avgDom: 29, overAsk: 23 },
  "Leaside": { sales: 100, active: 58, monthsInventory: 7.0, avgPrice: 2044399, avgDom: 22, overAsk: 35 },
  "The Junction": { sales: 100, active: 81, monthsInventory: 9.7, avgPrice: 1115503, avgDom: 31, overAsk: 35 },
  "Roncesvalles": { sales: 100, active: 56, monthsInventory: 6.7, avgPrice: 1352586, avgDom: 30, overAsk: 36 },
  "The Beaches": { sales: 100, active: 71, monthsInventory: 8.5, avgPrice: 1569125, avgDom: 25, overAsk: 40 },
  "Leslieville": { sales: 100, active: 134, monthsInventory: 16.1, avgPrice: 1125922, avgDom: 23, overAsk: 41 },
  "High Park": { sales: 100, active: 41, monthsInventory: 4.9, avgPrice: 1322415, avgDom: 17, overAsk: 45 },
  "Queen West": { sales: 100, active: 63, monthsInventory: 7.6, avgPrice: 1086626, avgDom: 26, overAsk: 53 },
  "Bloor West Village": { sales: 100, active: 26, monthsInventory: 3.1, avgPrice: 1410739, avgDom: 14, overAsk: 64 }
};

const neighbourhoodDatabase: Record<string, Neighbourhood> = {
  "Leaside": {
    name: "Leaside",
    description: "A steady east end pocket with detached family homes, mature streets, strong schools, and practical access to parks, shops, and daily services.",
    pricePoint: "$2.6M to $4.5M for strong detached family homes, with renovated or architecturally distinct properties moving higher.",
    buyerFit: "Leaside suits buyers who want a composed family setting with walkability, parking, and a neighbourhood rhythm that works during the week.",
    keywords: ["schools", "parking", "family layout", "walkability"],
    mapQuery: "Leaside, Toronto, Ontario"
  },
  "Lawrence Park": {
    name: "Lawrence Park",
    description: "A quieter residential enclave defined by deep lots, established architecture, ravine edges, and access to several of Toronto's most recognized schools.",
    pricePoint: "$3.5M to $7M+, depending on lot, renovation quality, and proximity to ravine or school corridors.",
    buyerFit: "Lawrence Park fits buyers prioritizing long-term ownership, privacy, school access, and homes with architectural permanence.",
    keywords: ["ravine", "schools", "privacy", "long-term value"],
    mapQuery: "Lawrence Park, Toronto, Ontario"
  },
  "Summerhill": {
    name: "Summerhill",
    description: "An elegant central neighbourhood with refined streets, heritage character, useful transit access, and a close relationship to Yonge Street amenities.",
    pricePoint: "$2.8M to $5.5M for freehold homes, with premium pricing for wider lots, finished renovations, and quieter positions.",
    buyerFit: "Summerhill works for buyers who want character, daily convenience, and a more urban form of family living.",
    keywords: ["heritage", "transit", "shops", "central"],
    mapQuery: "Summerhill, Toronto, Ontario"
  },
  "Rosedale": {
    name: "Rosedale",
    description: "A historic residential landscape shaped by ravines, generous lots, and a sense of remove while remaining close to the core.",
    pricePoint: "$4M to $10M+, with wide variance based on architecture, lot scale, and renovation depth.",
    buyerFit: "Rosedale is strongest for buyers seeking privacy, mature architecture, and a quieter relationship to central Toronto.",
    keywords: ["ravines", "heritage", "privacy", "scale"],
    mapQuery: "Rosedale, Toronto, Ontario"
  },
  "Forest Hill": {
    name: "Forest Hill",
    description: "A polished west midtown address with substantial homes, established schools, quiet streets, and a formal residential character.",
    pricePoint: "$3.5M to $8M+, with larger renovated homes and premium streets commanding higher values.",
    buyerFit: "Forest Hill fits buyers who value school access, long-term stability, and a more traditional residential setting.",
    keywords: ["schools", "stability", "large homes", "formal streets"],
    mapQuery: "Forest Hill, Toronto, Ontario"
  },
  "The Annex": {
    name: "The Annex",
    description: "A layered central neighbourhood with Victorian and Edwardian housing, cultural depth, transit, and immediate access to restaurants, shops, and institutions.",
    pricePoint: "$2.5M to $5M for strong freehold homes, with larger renovated properties above that range.",
    buyerFit: "The Annex suits buyers who want character, walkability, and an urban lifestyle without giving up residential texture.",
    keywords: ["character", "culture", "transit", "walkability"],
    mapQuery: "The Annex, Toronto, Ontario"
  },
  "Casa Loma": {
    name: "Casa Loma",
    description: "A distinctive pocket with dramatic topography, period homes, quiet streets, and close access to ravine paths and midtown amenities.",
    pricePoint: "$2.8M to $5.5M for freehold homes, with premiums for views, scale, and thoughtful renovation.",
    buyerFit: "Casa Loma works well for buyers drawn to architectural character, elevation, and a slightly more secluded central address.",
    keywords: ["topography", "period homes", "ravine", "central"],
    mapQuery: "Casa Loma, Toronto, Ontario"
  },
  "Yonge & St. Clair": {
    name: "Yonge & St. Clair",
    description: "A connected midtown node with refined residential side streets, strong transit, and practical access to shops, services, and ravine systems.",
    pricePoint: "$2.4M to $5M for freehold homes nearby, with broader options across townhomes and condominiums.",
    buyerFit: "Yonge & St. Clair fits buyers who want a precise balance of city access, walkability, and quieter residential streets.",
    keywords: ["transit", "walkability", "midtown", "services"],
    mapQuery: "Yonge and St. Clair, Toronto, Ontario"
  },
  "Davisville Village": {
    name: "Davisville Village",
    description: "A practical midtown neighbourhood with approachable family streets, good transit, parks, and a mix of renovated and original homes.",
    pricePoint: "$2M to $3.8M for many detached and semi-detached homes, with renovated detached properties moving above that band.",
    buyerFit: "Davisville Village is a strong fit for buyers seeking family function, daily convenience, and value relative to neighbouring pockets.",
    keywords: ["family function", "transit", "parks", "value"],
    mapQuery: "Davisville Village, Toronto, Ontario"
  },
  "Moore Park": {
    name: "Moore Park",
    description: "A calm residential area set between ravine systems, known for generous streets, established homes, and a restrained neighbourhood feel.",
    pricePoint: "$3M to $6M+, shaped by lot size, condition, and proximity to ravine corridors.",
    buyerFit: "Moore Park suits buyers who want family scale, nature access, and a quieter version of central living.",
    keywords: ["ravine", "quiet", "family scale", "nature"],
    mapQuery: "Moore Park, Toronto, Ontario"
  },
  "Yorkville": {
    name: "Yorkville",
    description: "A dense, design-conscious address with galleries, dining, boutiques, and a concentration of refined condominium and townhouse options.",
    pricePoint: "$2M to $6M+ across larger condominiums and townhomes, with trophy residences priced well beyond.",
    buyerFit: "Yorkville fits buyers prioritizing service, design, cultural access, and a more compact urban lifestyle.",
    keywords: ["design", "culture", "service", "urban"],
    mapQuery: "Yorkville, Toronto, Ontario"
  },
  "Leslieville": {
    name: "Leslieville",
    description: "An east end neighbourhood with renovated semis, converted industrial character, independent retail, and a practical connection to parks and Queen Street.",
    pricePoint: "$1.6M to $3.2M for many freehold homes, with larger renovated properties and distinctive architecture moving higher.",
    buyerFit: "Leslieville fits buyers who want design energy, walkability, and a less formal version of family living.",
    keywords: ["east end", "restaurants", "renovated semis", "parks"],
    mapQuery: "Leslieville, Toronto, Ontario"
  },
  "Queen West": {
    name: "Queen West",
    description: "A highly urban corridor with galleries, restaurants, converted spaces, townhomes, and condominium options tied closely to Toronto's creative economy.",
    pricePoint: "$1.2M to $3M+ across townhomes, lofts, and larger condominium residences.",
    buyerFit: "Queen West suits buyers who want cultural access, walkability, and a more compact urban search profile.",
    keywords: ["culture", "lofts", "restaurants", "urban"],
    mapQuery: "Queen Street West, Toronto, Ontario"
  },
  "King West": {
    name: "King West",
    description: "A downtown west neighbourhood with a dense mix of lofts, condominiums, restaurants, and converted commercial buildings.",
    pricePoint: "$900K to $3M+ across condominiums and lofts, with larger or design-led residences priced above the area average.",
    buyerFit: "King West fits buyers prioritizing services, transit, restaurants, and a more vertical form of city living.",
    keywords: ["downtown", "lofts", "services", "restaurants"],
    mapQuery: "King West, Toronto, Ontario"
  },
  "The Beaches": {
    name: "The Beaches",
    description: "A lakeside east end community with established houses, neighbourhood retail, parks, schools, and immediate access to the waterfront.",
    pricePoint: "$1.8M to $4M+ for many freehold homes, with premiums for larger lots, lake proximity, and renovated detached properties.",
    buyerFit: "The Beaches suits buyers who want a softer neighbourhood rhythm with water access and strong daily walkability.",
    keywords: ["waterfront", "schools", "parks", "family"],
    mapQuery: "The Beaches, Toronto, Ontario"
  },
  "Bedford Park": {
    name: "Bedford Park",
    description: "A north Toronto family neighbourhood with detached and semi-detached homes, strong school access, and useful connections to Avenue Road and Yonge Street.",
    pricePoint: "$2M to $4.5M+ depending on lot width, renovation quality, and location within the school corridors.",
    buyerFit: "Bedford Park fits buyers looking for family function, practical amenities, and a long-term residential setting.",
    keywords: ["schools", "family", "north Toronto", "detached"],
    mapQuery: "Bedford Park, Toronto, Ontario"
  },
  "Bennington Heights": {
    name: "Bennington Heights",
    description: "A quiet enclave near ravine systems with detached homes, winding residential streets, and a more private east-central feel.",
    pricePoint: "$2.8M to $5.5M+ shaped by lot, condition, and architectural quality.",
    buyerFit: "Bennington Heights works for buyers seeking privacy, ravine proximity, and an established residential setting.",
    keywords: ["ravine", "privacy", "detached", "quiet"],
    mapQuery: "Bennington Heights, Toronto, Ontario"
  },
  "Bloor West Village": {
    name: "Bloor West Village",
    description: "A west end neighbourhood with strong main-street retail, subway access, family housing, and close proximity to High Park and the Humber.",
    pricePoint: "$1.7M to $3.5M+ for many freehold homes, with larger renovated detached homes moving above that range.",
    buyerFit: "Bloor West Village fits buyers who want walkability, transit, schools, and a grounded west end neighbourhood structure.",
    keywords: ["subway", "shops", "schools", "west end"],
    mapQuery: "Bloor West Village, Toronto, Ontario"
  },
  "Bridle Path": {
    name: "Bridle Path",
    description: "A low-density estate neighbourhood defined by deep lots, privacy, significant homes, and proximity to ravine and park systems.",
    pricePoint: "$6M to $20M+, with substantial variance by lot scale, architecture, and condition.",
    buyerFit: "Bridle Path fits buyers prioritizing scale, privacy, and a more estate-oriented ownership profile.",
    keywords: ["estate", "privacy", "scale", "ravine"],
    mapQuery: "Bridle Path, Toronto, Ontario"
  },
  "Cabbagetown": {
    name: "Cabbagetown",
    description: "A historic east-central neighbourhood with Victorian housing, intimate streets, strong architectural identity, and quick access to downtown.",
    pricePoint: "$1.5M to $3.5M+ for many freehold homes, with larger restored properties commanding premiums.",
    buyerFit: "Cabbagetown suits buyers drawn to heritage character, walkability, and a central residential setting.",
    keywords: ["Victorian", "heritage", "downtown", "walkability"],
    mapQuery: "Cabbagetown, Toronto, Ontario"
  },
  "High Park": {
    name: "High Park",
    description: "A west end neighbourhood anchored by Toronto's largest park, with established homes, leafy streets, subway access, and a strong family orientation.",
    pricePoint: "$1.8M to $4M+ depending on home type, renovation quality, and proximity to the park.",
    buyerFit: "High Park fits buyers seeking green space, transit, and a balanced west end lifestyle.",
    keywords: ["park", "subway", "family", "west end"],
    mapQuery: "High Park, Toronto, Ontario"
  },
  "Hoggs Hollow": {
    name: "Hoggs Hollow",
    description: "A secluded north Toronto pocket shaped by ravines, larger lots, and a quiet residential character near Yonge Street amenities.",
    pricePoint: "$3M to $7M+ with premiums for ravine settings, lot scale, and substantial renovations.",
    buyerFit: "Hoggs Hollow suits buyers who want privacy, natural setting, and strong access to midtown and north Toronto.",
    keywords: ["ravine", "privacy", "large lots", "north Toronto"],
    mapQuery: "Hoggs Hollow, Toronto, Ontario"
  },
  "Lytton Park": {
    name: "Lytton Park",
    description: "A refined north Toronto neighbourhood with detached homes, quiet streets, and direct access to established schools and Yonge Street amenities.",
    pricePoint: "$2.8M to $6M+ depending on lot, condition, and renovation quality.",
    buyerFit: "Lytton Park fits buyers looking for school access, architectural permanence, and a composed family setting.",
    keywords: ["schools", "detached", "family", "north Toronto"],
    mapQuery: "Lytton Park, Toronto, Ontario"
  },
  "Parkdale": {
    name: "Parkdale",
    description: "A west end neighbourhood with Victorian and Edwardian housing, apartment stock, cultural texture, and direct access to Queen Street and the waterfront.",
    pricePoint: "$1.4M to $3.2M+ for many freehold properties, with wide variation by condition and configuration.",
    buyerFit: "Parkdale fits buyers who value character, urban texture, and access to the west end's cultural corridors.",
    keywords: ["character", "west end", "Queen Street", "waterfront"],
    mapQuery: "Parkdale, Toronto, Ontario"
  },
  "Ramsden Park": {
    name: "Ramsden Park",
    description: "A small central focus area near Rosedale and Yorkville, valued for park access, townhomes, historic housing, and refined urban convenience.",
    pricePoint: "$2M to $5M+ across townhomes, freeholds, and larger residences near the park.",
    buyerFit: "Ramsden Park suits buyers who want central access, park proximity, and a quieter pocket beside major amenities.",
    keywords: ["park", "central", "townhomes", "walkability"],
    mapQuery: "Ramsden Park, Toronto, Ontario"
  },
  "Roncesvalles": {
    name: "Roncesvalles",
    description: "A west end neighbourhood with family houses, independent retail, streetcar access, and a strong relationship to High Park and the lake.",
    pricePoint: "$1.6M to $3.5M+ for many freehold homes, with renovated detached and larger semis moving higher.",
    buyerFit: "Roncesvalles fits buyers seeking walkability, community structure, and character-driven west end housing.",
    keywords: ["west end", "shops", "streetcar", "family"],
    mapQuery: "Roncesvalles, Toronto, Ontario"
  },
  "The Junction": {
    name: "The Junction",
    description: "A west Toronto neighbourhood with converted industrial character, independent retail, family housing, and improving connections across the west end.",
    pricePoint: "$1.4M to $3M+ for many freehold homes, with larger renovated properties priced above the area average.",
    buyerFit: "The Junction fits buyers who want character, local retail, and relative value beside more established west end pockets.",
    keywords: ["character", "retail", "west end", "value"],
    mapQuery: "The Junction, Toronto, Ontario"
  },
  "The Kingsway": {
    name: "The Kingsway",
    description: "A west-end enclave with substantial detached homes, established streets, Humber River access, and a formal residential character.",
    pricePoint: "$2.5M to $6M+ depending on lot, architecture, and proximity to premium streets or ravine edges.",
    buyerFit: "The Kingsway suits buyers looking for scale, privacy, and a classic west-end residential environment.",
    keywords: ["detached", "Humber", "west end", "scale"],
    mapQuery: "The Kingsway, Toronto, Ontario"
  }
};

const allNeighbourhoods = [
  "Leaside",
  "Lawrence Park",
  "Summerhill",
  "Rosedale",
  "The Annex",
  "Yonge & St. Clair",
  "Davisville Village",
  "Moore Park",
  "Yorkville",
  "Leslieville",
  "Forest Hill",
  "Casa Loma",
  "Queen West",
  "King West",
  "The Beaches",
  "Bedford Park",
  "Bennington Heights",
  "Bloor West Village",
  "Bridle Path",
  "Cabbagetown",
  "High Park",
  "Hoggs Hollow",
  "Lytton Park",
  "Parkdale",
  "Ramsden Park",
  "Roncesvalles",
  "The Junction",
  "The Kingsway"
];

const sampleInput: BuyerInput = {
  clientName: "Sarah and Daniel",
  agentName: "Michael McLachlan",
  meetingDate: "2026-04-27",
  budgetMin: "$3,000,000",
  budgetMax: "$4,250,000",
  timeline: "3 to 6 months",
  financingStatus: "Pre-approved with flexibility on timing",
  propertyType: "Detached or semi-detached home",
  bedrooms: "4",
  bathrooms: "3+",
  parkingNeeds: "Private parking preferred",
  mustHaves: ["Family-friendly layout", "Strong natural light", "Parking", "Walkable neighbourhood", "Architectural character"],
  niceToHaves: ["Finished lower level", "Main floor office", "South-facing garden", "Renovated kitchen"],
  dealBreakers: ["No major structural work", "No overly generic flip", "No busy main road"],
  designPreferences: "Warm modern, classic architecture, natural materials, thoughtful renovations",
  lifestyleNotes: "They want a home that supports family life, school access, weekend hosting, and daily walkability.",
  neighbourhoods: ["Leaside", "Lawrence Park", "Summerhill"],
  agentNotes: "They responded well to homes with a strong front hall, good light through the main floor, and a sense of original character preserved through renovation."
};

const emptyInput: BuyerInput = {
  clientName: "",
  agentName: "",
  meetingDate: "",
  budgetMin: "",
  budgetMax: "",
  timeline: "",
  financingStatus: "",
  propertyType: "",
  bedrooms: "",
  bathrooms: "",
  parkingNeeds: "",
  mustHaves: [],
  niceToHaves: [],
  dealBreakers: [],
  designPreferences: "",
  lifestyleNotes: "",
  neighbourhoods: [],
  agentNotes: ""
};

const buyerProfileExamples: BuyerInput[] = [
  {
    clientName: "Alex Morgan",
    agentName: "Michael McLachlan",
    meetingDate: "2026-04-27",
    budgetMin: "$900,000",
    budgetMax: "$1,350,000",
    timeline: "1 to 3 months",
    financingStatus: "Pre-approved with a firm upper limit",
    propertyType: "Condominium, loft, or townhouse",
    bedrooms: "1+1 or 2",
    bathrooms: "2",
    parkingNeeds: "Parking preferred, strong transit can offset",
    mustHaves: ["Transit access", "Short commute downtown", "Space for hybrid work", "Walkable restaurants", "Good building management"],
    niceToHaves: ["Outdoor space", "Concrete loft character", "Gym in building", "Separate office nook"],
    dealBreakers: ["Long walk to transit", "Poor natural light", "High-maintenance boutique building"],
    designPreferences: "Clean modern, warm finishes, efficient storage, city views where possible",
    lifestyleNotes: "They work hybrid, go out often, and want a neighbourhood that supports restaurants, fitness, friends, and a low-friction commute.",
    neighbourhoods: ["King West", "Queen West", "Yorkville", "Yonge & St. Clair"],
    agentNotes: "They care more about building quality, transit, and lifestyle fit than square footage alone."
  },
  {
    clientName: "Maya and Thomas",
    agentName: "Michael McLachlan",
    meetingDate: "2026-04-27",
    budgetMin: "$2,600,000",
    budgetMax: "$3,700,000",
    timeline: "3 to 6 months",
    financingStatus: "Pre-approved with proceeds from a planned sale",
    propertyType: "Detached or larger semi-detached home",
    bedrooms: "4",
    bathrooms: "3+",
    parkingNeeds: "Private parking required",
    mustHaves: ["Family-friendly layout", "School access", "Parking", "Main floor family space", "Walkable daily amenities"],
    niceToHaves: ["Finished lower level", "Mudroom", "Main floor office", "South or west-facing garden"],
    dealBreakers: ["Busy main road", "Major structural work", "No functional family room"],
    designPreferences: "Classic architecture with warm modern updates, durable materials, thoughtful storage",
    lifestyleNotes: "They are moving up from a smaller home and want more room for children, school routines, weekend hosting, and hybrid work.",
    neighbourhoods: ["Leaside", "Bedford Park", "Davisville Village", "Lawrence Park"],
    agentNotes: "They need a home that solves the pressure points of family life rather than simply adding more square footage."
  },
  {
    clientName: "Victoria and James",
    agentName: "Michael McLachlan",
    meetingDate: "2026-04-27",
    budgetMin: "$7,500,000",
    budgetMax: "$14,000,000",
    timeline: "6 to 12 months",
    financingStatus: "Fully underwritten with flexibility for the right property",
    propertyType: "Substantial detached residence or estate property",
    bedrooms: "5+",
    bathrooms: "5+",
    parkingNeeds: "Multiple car parking required",
    mustHaves: ["Privacy", "Architectural presence", "Large principal rooms", "Elevated renovation quality", "Strong long-term address"],
    niceToHaves: ["Ravine setting", "Pool", "Wine storage", "Gym", "Guest suite"],
    dealBreakers: ["Compromised lot", "Inferior renovation quality", "Overexposed street position"],
    designPreferences: "Quietly substantial, natural stone, millwork, mature landscaping, refined contemporary or classic architecture",
    lifestyleNotes: "They are seeking a significant upgrade with privacy, entertaining capacity, family scale, and a property that feels considered rather than showy.",
    neighbourhoods: ["Rosedale", "Forest Hill", "Bridle Path", "Lawrence Park", "The Kingsway"],
    agentNotes: "They will move for the right property, not because they need to. The search should be selective and discreet."
  }
];

function listToSentence(items: string[]) {
  const clean = items.filter(Boolean);
  if (clean.length === 0) return "";
  if (clean.length === 1) return clean[0].toLowerCase();
  return `${clean.slice(0, -1).join(", ").toLowerCase()}, and ${clean[clean.length - 1].toLowerCase()}`;
}

function formatDate(date: string) {
  const parsed = new Date(`${date}T12:00:00`);
  if (Number.isNaN(parsed.getTime())) return date;
  return new Intl.DateTimeFormat("en-CA", { month: "long", day: "numeric", year: "numeric" }).format(parsed);
}

function formatAveragePrice(price: number) {
  return `$${(price / 1000000).toFixed(1)}M`;
}

function slugify(value: string) {
  const slug = value.toLowerCase().trim().replace(/&/g, " and ").replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "");
  return slug || `brief-${Date.now()}`;
}

function buildClientUrl(path: string) {
  if (!path) return "";
  return `${window.location.origin}${path}`;
}

function buildEmailBody(input: BuyerInput, clientUrl?: string) {
  const link = clientUrl || "[View your search brief]";
  return `Hi ${input.clientName || "there"},\n\nGood to meet with you.\n\nI have prepared your buyer search brief, including the priorities we discussed and the neighbourhoods or search areas we will be watching closely.\n\n${link}\n\nWe will use this as a working reference as we begin reviewing opportunities.\n\nBest,\n${input.agentName || "The Central"}`;
}

function withClientLink(brief: GeneratedBrief, input: BuyerInput, meta?: SavedBriefMeta): GeneratedBrief {
  const clientUrl = meta?.clientUrl || (meta?.sharePath ? buildClientUrl(meta.sharePath) : "");
  return {
    ...brief,
    email: {
      subject: brief.email.subject,
      body: buildEmailBody(input, clientUrl)
    }
  };
}

async function saveBriefToSite(payload: { input: BuyerInput; brief: GeneratedBrief; clientSlug: string; sharePath: string; briefId: string; status: string }) {
  if (appsScriptEndpoint) {
    await fetch(appsScriptEndpoint, {
      method: "POST",
      mode: "no-cors",
      headers: { "Content-Type": "text/plain" },
      body: JSON.stringify(payload)
    });
    return {
      clientSlug: payload.clientSlug,
      sharePath: payload.sharePath,
      clientUrl: buildClientUrl(payload.sharePath),
      agentPath: `/agent/${payload.clientSlug}`,
      agentUrl: buildClientUrl(`/agent/${payload.clientSlug}`)
    } as SavedBriefMeta;
  }
  const response = await fetch("/.netlify/functions/save-brief", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(payload)
  });
  const data = await response.json().catch(() => ({}));
  if (!response.ok) throw new Error(data.error || "Unable to save brief.");
  return data as SavedBriefMeta;
}

async function loadBriefFromSite(slug: string) {
  if (appsScriptEndpoint) {
    const callback = `buyerBriefCallback_${Date.now()}_${Math.random().toString(36).slice(2)}`;
    return await new Promise<{ input: BuyerInput; brief: GeneratedBrief; clientSlug: string; sharePath: string }>((resolve, reject) => {
      const script = document.createElement("script");
      const cleanup = () => {
        delete (window as unknown as Record<string, unknown>)[callback];
        script.remove();
      };
      const timeout = window.setTimeout(() => {
        cleanup();
        reject(new Error("Unable to load brief."));
      }, 10000);
      (window as unknown as Record<string, (data: { ok?: boolean; error?: string; input: BuyerInput; brief: GeneratedBrief; clientSlug?: string; sharePath?: string }) => void>)[callback] = (data) => {
        window.clearTimeout(timeout);
        cleanup();
        if (!data.ok) {
          reject(new Error(data.error || "Unable to load brief."));
          return;
        }
        resolve({
          input: data.input,
          brief: data.brief,
          clientSlug: data.clientSlug || slug,
          sharePath: data.sharePath || `/brief/${slug}`
        });
      };
      script.onerror = () => {
        window.clearTimeout(timeout);
        cleanup();
        reject(new Error("Unable to load brief."));
      };
      script.src = `${appsScriptEndpoint}?slug=${encodeURIComponent(slug)}&callback=${encodeURIComponent(callback)}`;
      document.body.appendChild(script);
    });
  }
  const response = await fetch(`/.netlify/functions/get-brief?slug=${encodeURIComponent(slug)}`);
  const data = await response.json().catch(() => ({}));
  if (!response.ok) throw new Error(data.error || "Unable to load brief.");
  return data as { input: BuyerInput; brief: GeneratedBrief; clientSlug: string; sharePath: string };
}

function generateBuyerBrief(input: BuyerInput): GeneratedBrief {
  const selected = input.neighbourhoods.map((name) => neighbourhoodDatabase[name] || {
    name,
    description: `${name} will be reviewed for housing quality, street position, pricing behaviour, and fit against the priorities in this brief.`,
    pricePoint: "To be assessed against current inventory and recent comparable sales.",
    buyerFit: `${name} is included as a custom focus area for this search.`,
    keywords: ["custom focus", "fit", "pricing"],
    mapQuery: `${name}, Toronto, Ontario`
  }).filter(Boolean);
  const buyerSummary = `${input.clientName} is looking for a ${input.propertyType.toLowerCase()} that can support daily family life without losing architectural character. The search should stay disciplined around homes with ${listToSentence(input.mustHaves)}, with particular attention to light, flow, and the quality of past renovations.`;
  const criteriaSummary = `The working range is ${input.budgetMin} to ${input.budgetMax}, with a ${input.timeline.toLowerCase()} timeline and ${input.financingStatus.toLowerCase()}. We will focus on ${input.bedrooms} bedrooms, ${input.bathrooms} bathrooms, and ${input.parkingNeeds.toLowerCase()}, while filtering out properties with ${listToSentence(input.dealBreakers)}.`;
  const whatMattersMost = `The brief favours ${input.designPreferences.toLowerCase()}. ${input.lifestyleNotes} In practice, that means fewer tours and a sharper review of homes that combine layout, street position, renovation quality, and long-term value. ${input.agentNotes}`;
  const neighbourhoodSections = selected.map((area) => ({
    ...area,
    whyItFits: `${area.buyerFit} For ${input.clientName}, the fit comes from how its ${area.keywords.slice(0, 3).join(", ")} align with the priorities discussed.`
  }));
  const nextSteps = "We will begin watching for homes aligned with this brief, with attention to pricing, presentation, and long-term value. The focus will be fit, not volume. Each opportunity will be reviewed against your priorities before being brought forward.";
  const email = {
    subject: "Your Search Brief",
    body: buildEmailBody(input)
  };
  return { buyerSummary, criteriaSummary, whatMattersMost, neighbourhoodSections, nextSteps, email };
}

function useRoute() {
  const [path, setPath] = useState(window.location.pathname);
  useEffect(() => {
    const handle = () => setPath(window.location.pathname);
    window.addEventListener("popstate", handle);
    return () => window.removeEventListener("popstate", handle);
  }, []);
  const navigate = (next: string) => {
    window.history.pushState({}, "", next);
    setPath(next);
    window.scrollTo({ top: 0, behavior: "smooth" });
  };
  return { path, navigate };
}

function BrandHeader({ tone = "light", navigate, publicPage = false }: { tone?: "light" | "dark"; navigate: (path: string) => void; publicPage?: boolean }) {
  const dark = tone === "dark";
  const logoSrc = dark ? "/src/the-central-wordmark-green.svg" : "/src/the-central-wordmark-cream.svg";
  const logo = <img className="brand-wordmark" src={logoSrc} alt="The Central" />;
  return (
    <header className={`flex items-center justify-between gap-6 px-5 py-5 sm:px-8 lg:px-12 ${dark ? "text-night" : "text-white"}`}>
      {publicPage ? (
        <a className="flex items-center text-left" href="https://www.thecentral.ca" aria-label="Visit The Central website">
          {logo}
        </a>
      ) : (
        <>
          <button className="flex items-center text-left" onClick={() => navigate("/agent")} aria-label="Go to agent dashboard">
            {logo}
          </button>
          <nav className={`flex border text-xs font-bold uppercase tracking-[0.14em] ${dark ? "border-night/20" : "border-white/25"}`}>
            <button className="px-4 py-3 hover:bg-ecru hover:text-night" onClick={() => navigate("/agent")}>Agent</button>
            <button className="border-l border-current/20 px-4 py-3 hover:bg-ecru hover:text-night" onClick={() => navigate("/brief")}>Brief</button>
          </nav>
        </>
      )}
    </header>
  );
}

function TextField({ label, value, onChange, type = "text" }: { label: string; value: string; onChange: (value: string) => void; type?: string }) {
  return <label><span className="label">{label}</span><input className="field" type={type} value={value} onChange={(event) => onChange(event.target.value)} /></label>;
}

function TextArea({ label, value, onChange, rows = 5 }: { label: string; value: string; onChange: (value: string) => void; rows?: number }) {
  return <label><span className="label">{label}</span><textarea className="field resize-y" rows={rows} value={value} onChange={(event) => onChange(event.target.value)} /></label>;
}

function MultiTextField({ label, values, onChange }: { label: string; values: string[]; onChange: (values: string[]) => void }) {
  const updateItem = (index: number, value: string) => {
    const next = [...values];
    next[index] = value;
    onChange(next.filter((item, itemIndex) => item.trim() || itemIndex === index));
  };
  const addItem = () => onChange([...values, ""]);
  const removeItem = (index: number) => onChange(values.filter((_, itemIndex) => itemIndex !== index));
  return (
    <div>
      <span className="label">{label}</span>
      <div className="space-y-3">
        {values.map((item, index) => (
          <div className="grid grid-cols-[1fr_auto] gap-2" key={`${label}-${index}`}>
            <input className="field" value={item} onChange={(event) => updateItem(index, event.target.value)} />
            <button className="border border-night/20 px-4 text-xs font-bold uppercase tracking-[0.12em] text-night/70 hover:bg-night hover:text-white" type="button" onClick={() => removeItem(index)}>Remove</button>
          </div>
        ))}
      </div>
      <button className="mt-3 border border-night/20 px-4 py-3 text-xs font-bold uppercase tracking-[0.12em] text-night hover:bg-night hover:text-white" type="button" onClick={addItem}>Add item</button>
    </div>
  );
}

function BriefSection({ eyebrow, title, children, dark = false }: { eyebrow?: string; title: string; children: React.ReactNode; dark?: boolean }) {
  return (
    <section className={dark ? "bg-night text-alabaster" : "bg-paper text-night"}>
      <div className="mx-auto grid max-w-7xl gap-10 px-5 py-16 sm:px-8 lg:grid-cols-[0.36fr_0.64fr] lg:px-12 lg:py-24">
        <div>
          {eyebrow && <p className={`mb-4 text-xs font-bold uppercase tracking-[0.18em] ${dark ? "text-ecru" : "text-forest"}`}>{eyebrow}</p>}
          <h2 className="font-headline text-4xl font-bold leading-[0.95] sm:text-5xl">{title}</h2>
        </div>
        <div>{children}</div>
      </div>
    </section>
  );
}

function MapEmbed({ area }: { area: Neighbourhood & { whyItFits?: string } }) {
  const src = `https://www.google.com/maps?q=${encodeURIComponent(area.mapQuery)}&output=embed`;
  return (
    <div className="relative min-h-[320px] overflow-hidden border border-night/15 bg-alabaster/50">
      <iframe
        title={`${area.name} map`}
        src={src}
        className="absolute inset-0 h-full w-full grayscale"
        loading="lazy"
        referrerPolicy="no-referrer-when-downgrade"
      />
      <div className="pointer-events-none absolute inset-0 border-[14px] border-paper/70" />
      <div className="pointer-events-none absolute bottom-4 left-4 border border-night/20 bg-paper/90 px-3 py-2 text-[0.65rem] font-bold uppercase tracking-[0.16em] text-night/70">{area.name}</div>
    </div>
  );
}

function MarketDataStrip({ data }: { data: NeighbourhoodMarketData }) {
  const stats = [
    ["AVG PRICE", formatAveragePrice(data.avgPrice)],
    ["DAYS ON MARKET", String(Math.round(data.avgDom))],
    ["OVER ASK", `${Math.round(data.overAsk)}%`],
    ["INVENTORY", `${data.monthsInventory.toFixed(1)} MO`]
  ];
  return (
    <div className="market-strip mt-8">
      {stats.map(([label, value]) => (
        <div className="market-stat" key={label}>
          <p className="market-label">{label}</p>
          <p className="market-value">{value}</p>
        </div>
      ))}
    </div>
  );
}

function NeighbourhoodCard({ area, index }: { area: Neighbourhood & { whyItFits: string }; index: number }) {
  const marketData = neighbourhoodMarketData[area.name];
  return (
    <article className="grid gap-6 border-t border-night/18 py-10 lg:grid-cols-[0.55fr_0.45fr]">
      <div className="max-w-2xl">
        <p className="mb-5 text-xs font-bold uppercase tracking-[0.18em] text-forest">Focus {String(index + 1).padStart(2, "0")}</p>
        <h3 className="font-headline text-4xl font-bold leading-none sm:text-5xl">{area.name}</h3>
        <p className="mt-6 text-lg leading-8 text-night/78">{area.description}</p>
        {marketData && <MarketDataStrip data={marketData} />}
        <dl className="mt-8 grid gap-6 sm:grid-cols-2">
          <div><dt className="label">Typical price point</dt><dd className="text-sm leading-6 text-night/78">{area.pricePoint}</dd></div>
          <div><dt className="label">Why it fits</dt><dd className="text-sm leading-6 text-night/78">{area.whyItFits}</dd></div>
        </dl>
      </div>
      <MapEmbed area={area} />
    </article>
  );
}

function EmailPreview({ brief }: { brief: GeneratedBrief }) {
  const copyEmail = async () => navigator.clipboard.writeText(`Subject: ${brief.email.subject}\n\n${brief.email.body}`);
  return (
    <aside className="panel p-6 lg:p-8">
      <div className="mb-6 flex items-start justify-between gap-4">
        <div><p className="text-xs font-bold uppercase tracking-[0.18em] text-forest">Email output</p><h3 className="mt-2 font-headline text-3xl font-bold">Client note</h3></div>
        <button className="border border-night px-4 py-3 text-xs font-bold uppercase tracking-[0.14em] hover:bg-night hover:text-white" onClick={copyEmail}>Copy</button>
      </div>
      <p className="border-b border-night/15 pb-4 text-sm"><span className="font-bold">Subject:</span> {brief.email.subject}</p>
      <pre className="mt-5 whitespace-pre-wrap font-body text-sm leading-7 text-night/78">{brief.email.body}</pre>
    </aside>
  );
}

function AgentForm({
  input,
  setInput,
  brief,
  setBrief,
  meta,
  setMeta,
  navigate
}: {
  input: BuyerInput;
  setInput: (input: BuyerInput) => void;
  brief: GeneratedBrief;
  setBrief: (brief: GeneratedBrief) => void;
  meta?: SavedBriefMeta;
  setMeta: (meta?: SavedBriefMeta) => void;
  navigate: (path: string) => void;
}) {
  const [customNeighbourhood, setCustomNeighbourhood] = useState("");
  const [exampleIndex, setExampleIndex] = useState(0);
  const [saveStatus, setSaveStatus] = useState("");
  const update = <K extends keyof BuyerInput,>(key: K, value: BuyerInput[K]) => setInput({ ...input, [key]: value });
  const addCustomNeighbourhood = () => {
    const value = customNeighbourhood.trim();
    if (!value || input.neighbourhoods.includes(value)) return;
    update("neighbourhoods", [...input.neighbourhoods, value]);
    setCustomNeighbourhood("");
  };
  const generate = () => {
    const next = withClientLink(generateBuyerBrief(input), input, meta);
    setBrief(next);
    localStorage.setItem(storageKey, JSON.stringify({ input, brief: next, meta }));
  };
  const preview = () => {
    generate();
    navigate(meta?.sharePath || "/brief");
  };
  const copyEmail = async () => {
    const next = withClientLink(generateBuyerBrief(input), input, meta);
    setBrief(next);
    await navigator.clipboard.writeText(`Subject: ${next.email.subject}\n\n${next.email.body}`);
  };
  const reset = () => {
    const next = generateBuyerBrief(emptyInput);
    setInput(emptyInput);
    setBrief(next);
    setMeta(undefined);
    setCustomNeighbourhood("");
    localStorage.removeItem(storageKey);
    window.history.replaceState({}, "", "/agent");
  };
  const loadExample = () => {
    const example = buyerProfileExamples[exampleIndex % buyerProfileExamples.length];
    const next = generateBuyerBrief(example);
    setInput(example);
    setBrief(next);
    setMeta(undefined);
    setExampleIndex((current) => (current + 1) % buyerProfileExamples.length);
    localStorage.setItem(storageKey, JSON.stringify({ input: example, brief: next }));
  };
  const saveBrief = async () => {
    const next = generateBuyerBrief(input);
    const clientSlug = slugify(`${input.clientName || "buyer"}-${input.meetingDate || new Date().toISOString().slice(0, 10)}`);
    const sharePath = `/brief/${clientSlug}`;
    const payload = {
      briefId: `${clientSlug}-${Date.now()}`,
      clientSlug,
      sharePath,
      status: "saved",
      input,
      brief: next
    };
    const localMeta = { clientSlug, sharePath, clientUrl: buildClientUrl(sharePath), agentPath: `/agent/${clientSlug}`, agentUrl: buildClientUrl(`/agent/${clientSlug}`) };
    try {
      const savedMeta = await saveBriefToSite(payload);
      const finalMeta = { ...localMeta, ...savedMeta };
      const linkedBrief = withClientLink(next, input, finalMeta);
      setBrief(linkedBrief);
      setMeta(finalMeta);
      localStorage.setItem(storageKey, JSON.stringify({ input, brief: linkedBrief, meta: finalMeta }));
      navigate(finalMeta.agentPath || `/agent/${clientSlug}`);
      setSaveStatus(`Saved. Client link: ${finalMeta.clientUrl || finalMeta.sharePath}`);
    } catch (error) {
      const linkedBrief = withClientLink(next, input, localMeta);
      setBrief(linkedBrief);
      setMeta(localMeta);
      localStorage.setItem(storageKey, JSON.stringify({ input, brief: linkedBrief, meta: localMeta }));
      navigate(localMeta.agentPath);
      setSaveStatus(`Saved locally for preview. Google Sheets will connect after Netlify environment variables are added. Client link: ${localMeta.clientUrl}`);
    }
  };

  return (
    <main className="bg-paper text-night">
      <section className="bg-night text-white architectural-lines">
        <BrandHeader navigate={navigate} />
        <div className="mx-auto grid max-w-7xl gap-10 px-5 pb-16 pt-12 sm:px-8 lg:grid-cols-[0.7fr_0.3fr] lg:px-12 lg:pb-24">
          <div>
            <p className="mb-5 text-xs font-bold uppercase tracking-[0.18em] text-ecru">Internal working page</p>
            <h1 className="font-headline text-6xl font-extrabold lowercase leading-[0.86] sm:text-7xl lg:text-8xl">buyer search brief</h1>
            <p className="mt-8 max-w-2xl text-lg leading-8 text-alabaster/82">Turn meeting notes into a composed client-facing search direction, grounded in priorities, neighbourhood logic, and The Central voice.</p>
          </div>
          <div className="border-l border-white/20 pl-6 text-sm leading-7 text-alabaster/76"><p>Prepared as a digital brief rather than a CRM report. The agent side stays practical, while the client page reads as a polished search document.</p></div>
        </div>
      </section>

      <section className="mx-auto grid max-w-7xl gap-8 px-5 py-12 sm:px-8 lg:grid-cols-[1fr_0.42fr] lg:px-12 lg:py-16">
        <div className="space-y-8">
          <div className="panel p-6 lg:p-8">
            <p className="mb-3 text-xs font-bold uppercase tracking-[0.18em] text-forest">Client details</p>
            <div className="grid gap-5 md:grid-cols-2">
              <TextField label="Client name" value={input.clientName} onChange={(value) => update("clientName", value)} />
              <TextField label="Agent name" value={input.agentName} onChange={(value) => update("agentName", value)} />
              <TextField label="Meeting date" type="date" value={input.meetingDate} onChange={(value) => update("meetingDate", value)} />
              <TextField label="Purchase timeline" value={input.timeline} onChange={(value) => update("timeline", value)} />
              <TextField label="Budget minimum" value={input.budgetMin} onChange={(value) => update("budgetMin", value)} />
              <TextField label="Budget maximum" value={input.budgetMax} onChange={(value) => update("budgetMax", value)} />
              <div className="md:col-span-2"><TextField label="Financing status" value={input.financingStatus} onChange={(value) => update("financingStatus", value)} /></div>
            </div>
          </div>

          <div className="panel p-6 lg:p-8">
            <p className="mb-3 text-xs font-bold uppercase tracking-[0.18em] text-forest">Search criteria</p>
            <div className="grid gap-5 md:grid-cols-2">
              <TextField label="Property type" value={input.propertyType} onChange={(value) => update("propertyType", value)} />
              <TextField label="Bedrooms" value={input.bedrooms} onChange={(value) => update("bedrooms", value)} />
              <TextField label="Bathrooms" value={input.bathrooms} onChange={(value) => update("bathrooms", value)} />
              <TextField label="Parking needs" value={input.parkingNeeds} onChange={(value) => update("parkingNeeds", value)} />
              <MultiTextField label="Must-haves" values={input.mustHaves} onChange={(values) => update("mustHaves", values)} />
              <MultiTextField label="Nice-to-haves" values={input.niceToHaves} onChange={(values) => update("niceToHaves", values)} />
              <MultiTextField label="Deal breakers" values={input.dealBreakers} onChange={(values) => update("dealBreakers", values)} />
              <TextArea label="Design preferences" value={input.designPreferences} onChange={(value) => update("designPreferences", value)} />
              <div className="md:col-span-2"><TextArea label="Lifestyle notes" rows={4} value={input.lifestyleNotes} onChange={(value) => update("lifestyleNotes", value)} /></div>
            </div>
          </div>

          <div className="panel p-6 lg:p-8">
            <p className="mb-5 text-xs font-bold uppercase tracking-[0.18em] text-forest">Neighbourhoods</p>
            <div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-3">
              {allNeighbourhoods.map((name) => {
                const active = input.neighbourhoods.includes(name);
                return <button key={name} className={`border px-4 py-4 text-left text-sm font-bold transition ${active ? "border-forest bg-forest text-white" : "border-night/18 bg-white/45 text-night hover:border-forest"}`} onClick={() => update("neighbourhoods", active ? input.neighbourhoods.filter((item) => item !== name) : [...input.neighbourhoods, name])}>{name}</button>;
              })}
            </div>
            <div className="mt-6 grid gap-3 sm:grid-cols-[1fr_auto]">
              <TextField label="Add neighbourhood" value={customNeighbourhood} onChange={setCustomNeighbourhood} />
              <button className="self-end border border-night px-5 py-4 text-xs font-bold uppercase tracking-[0.14em] text-night hover:bg-night hover:text-white" type="button" onClick={addCustomNeighbourhood}>Add</button>
            </div>
            {input.neighbourhoods.some((name) => !neighbourhoodDatabase[name]) && (
              <div className="mt-5 flex flex-wrap gap-2">
                {input.neighbourhoods.filter((name) => !neighbourhoodDatabase[name]).map((name) => (
                  <button key={name} className="border border-forest bg-paper px-3 py-2 text-xs font-bold uppercase tracking-[0.12em] text-forest" type="button" onClick={() => update("neighbourhoods", input.neighbourhoods.filter((item) => item !== name))}>{name} remove</button>
                ))}
              </div>
            )}
          </div>
          <div className="panel p-6 lg:p-8"><TextArea label="Agent notes" rows={8} value={input.agentNotes} onChange={(value) => update("agentNotes", value)} /></div>
        </div>

        <div className="space-y-8 lg:sticky lg:top-6 lg:self-start">
          <div className="dark-panel p-6 text-white lg:p-8">
            <p className="text-xs font-bold uppercase tracking-[0.18em] text-ecru">Actions</p>
            <div className="mt-6 grid gap-3">
              <button className="bg-ecru px-5 py-4 text-sm font-bold uppercase tracking-[0.14em] text-night hover:bg-white" onClick={preview}>Preview Brief</button>
              <button className="border border-white/30 px-5 py-4 text-sm font-bold uppercase tracking-[0.14em] text-white hover:bg-white hover:text-night" onClick={saveBrief}>Save Brief Profile</button>
              <button className="border border-white/30 px-5 py-4 text-sm font-bold uppercase tracking-[0.14em] text-white hover:bg-white hover:text-night" onClick={copyEmail}>Copy Client Email</button>
              <button className="border border-white/30 px-5 py-4 text-sm font-bold uppercase tracking-[0.14em] text-white hover:bg-white hover:text-night" onClick={loadExample}>Load Example</button>
              <button className="border border-white/30 px-5 py-4 text-sm font-bold uppercase tracking-[0.14em] text-white hover:bg-white hover:text-night" onClick={reset}>Reset</button>
            </div>
            {saveStatus && <p className="mt-5 text-xs leading-6 text-alabaster/76">{saveStatus}</p>}
            {meta?.sharePath && (
              <div className="mt-5 space-y-2 border-t border-white/15 pt-5 text-xs leading-6 text-alabaster/76">
                <p><span className="font-bold text-ecru">Client link:</span> {meta.clientUrl || buildClientUrl(meta.sharePath)}</p>
                <p><span className="font-bold text-ecru">Agent edit:</span> {meta.agentUrl || buildClientUrl(meta.agentPath || `/agent/${meta.clientSlug}`)}</p>
              </div>
            )}
            <p className="mt-5 text-xs leading-6 text-alabaster/76">Load Example rotates through young professional, midtown family upsizer, and significant upgrade profiles.</p>
          </div>
          <EmailPreview brief={brief} />
        </div>
      </section>
    </main>
  );
}

function ClientBrief({ input, brief, navigate }: { input: BuyerInput; brief: GeneratedBrief; navigate: (path: string) => void }) {
  return (
    <main className="bg-paper text-night">
      <section className="relative min-h-[86vh] overflow-hidden bg-night text-white">
        <div className="absolute inset-0 opacity-28 architectural-lines" />
        <div className="relative">
          <BrandHeader navigate={navigate} publicPage />
          <div className="mx-auto max-w-7xl px-5 pb-16 pt-16 sm:px-8 lg:px-12 lg:pb-24 lg:pt-24">
            <p className="mb-7 text-xs font-bold uppercase tracking-[0.2em] text-ecru">Prepared for {input.clientName}</p>
            <h1 className="font-headline text-5xl font-extrabold lowercase leading-[0.86] sm:text-7xl lg:text-[7.6rem] xl:text-[8.4rem] whitespace-nowrap">your search brief</h1>
            <div className="mt-10 grid max-w-4xl gap-6 border-t border-white/18 pt-8 text-sm leading-7 text-alabaster/82 sm:grid-cols-3">
              <p><span className="block text-xs font-bold uppercase tracking-[0.16em] text-ecru">Prepared by</span>{input.agentName}</p>
              <p><span className="block text-xs font-bold uppercase tracking-[0.16em] text-ecru">Date</span>{formatDate(input.meetingDate)}</p>
              <p><span className="block text-xs font-bold uppercase tracking-[0.16em] text-ecru">Reference</span>Buyer search direction</p>
            </div>
            <p className="mt-12 max-w-2xl text-xl leading-9 text-alabaster">Following our conversation, this brief outlines the priorities, neighbourhoods, and search direction we will use to guide your property search.</p>
            <p className="mt-8 max-w-2xl border-l border-ecru pl-6 text-base leading-8 text-alabaster/78">{brief.buyerSummary}</p>
          </div>
        </div>
      </section>

      <BriefSection eyebrow="Search direction" title="working criteria">
        <div className="grid gap-px overflow-hidden border border-night/15 bg-night/15 sm:grid-cols-2 lg:grid-cols-3">
          {[["Budget", `${input.budgetMin} to ${input.budgetMax}`], ["Property type", input.propertyType], ["Bedrooms", input.bedrooms], ["Bathrooms", input.bathrooms], ["Timeline", input.timeline], ["Financing", input.financingStatus]].map(([label, value]) => (
            <div key={label} className="bg-paper p-6"><p className="label">{label}</p><p className="text-lg leading-7">{value}</p></div>
          ))}
        </div>
        <p className="mt-8 max-w-3xl text-lg leading-8 text-night/76">{brief.criteriaSummary}</p>
      </BriefSection>

      <BriefSection eyebrow="What matters most" title="the fit">
        <p className="max-w-3xl text-2xl leading-10 text-night/82">{brief.whatMattersMost}</p>
      </BriefSection>

      <section className="bg-paper px-5 py-16 sm:px-8 lg:px-12 lg:py-24">
        <div className="mx-auto max-w-7xl">
          <div className="mb-8 max-w-3xl">
            <p className="mb-4 text-xs font-bold uppercase tracking-[0.18em] text-forest">Neighbourhood focus</p>
            <h2 className="font-headline text-5xl font-bold lowercase leading-none sm:text-6xl">where the search should concentrate</h2>
          </div>
          {brief.neighbourhoodSections.map((area, index) => <NeighbourhoodCard key={area.name} area={area} index={index} />)}
        </div>
      </section>

      <BriefSection eyebrow="Search priorities" title="decision filter" dark>
        <div className="grid gap-8 md:grid-cols-3">
          {[["Must-haves", input.mustHaves], ["Nice-to-haves", input.niceToHaves], ["Deal breakers", input.dealBreakers]].map(([title, items]) => (
            <div key={title as string} className="border-t border-alabaster/25 pt-5">
              <h3 className="font-headline text-2xl font-bold">{title as string}</h3>
              <ul className="mt-5 space-y-3 text-sm leading-6 text-alabaster/78">{(items as string[]).map((item) => <li key={item} className="border-b border-alabaster/12 pb-3">{item}</li>)}</ul>
            </div>
          ))}
        </div>
      </BriefSection>

      <BriefSection eyebrow="Next steps" title="how we move">
        <p className="max-w-3xl text-2xl leading-10 text-night/82">{brief.nextSteps}</p>
      </BriefSection>

      <footer className="bg-night px-5 py-12 text-alabaster sm:px-8 lg:px-12">
        <div className="mx-auto grid max-w-7xl gap-8 border-t border-alabaster/18 pt-8 md:grid-cols-[0.5fr_0.5fr]">
          <a className="flex items-center" href="https://www.thecentral.ca" aria-label="Visit The Central website"><img className="brand-wordmark" src="/src/the-central-wordmark-cream.svg" alt="The Central" /></a>
          <div className="text-sm leading-7 text-alabaster/76 md:text-right">
            <p>info@thecentral.ca</p><p>www.thecentral.ca</p><p>@thecentral.ca</p>
            <p className="mt-6 text-xs leading-6 text-alabaster/55">The Central By Royal LePage Real Estate Services Ltd., Brokerage. Not intended to solicit buyers or sellers currently under contract.</p>
          </div>
        </div>
      </footer>
    </main>
  );
}

function Home({ navigate }: { navigate: (path: string) => void }) {
  return (
    <main className="min-h-screen bg-night text-white architectural-lines">
      <BrandHeader navigate={navigate} />
      <section className="mx-auto grid max-w-7xl gap-10 px-5 py-16 sm:px-8 lg:grid-cols-[0.64fr_0.36fr] lg:px-12 lg:py-24">
        <div>
          <p className="mb-6 text-xs font-bold uppercase tracking-[0.2em] text-ecru">The Central</p>
          <h1 className="font-headline text-7xl font-extrabold lowercase leading-[0.82] sm:text-8xl lg:text-[9rem]">buyer search brief</h1>
          <p className="mt-10 max-w-2xl text-xl leading-9 text-alabaster/82">A composed working tool for turning buyer meeting notes into a client-ready search summary.</p>
          <div className="mt-10 flex flex-wrap gap-3">
            <button className="bg-ecru px-6 py-4 text-sm font-bold uppercase tracking-[0.14em] text-night hover:bg-white" onClick={() => navigate("/agent")}>Open Agent Page</button>
            <button className="border border-white/30 px-6 py-4 text-sm font-bold uppercase tracking-[0.14em] text-white hover:bg-white hover:text-night" onClick={() => navigate("/brief")}>View Sample Brief</button>
          </div>
        </div>
        <div className="self-end border border-white/18 p-8">
          <p className="text-xs font-bold uppercase tracking-[0.18em] text-ecru">brand palette</p>
          <div className="mt-8 grid grid-cols-4 gap-3">
            {["#e3e1d7", "#cbb783", "#365344", "#385947", "#ffffff", "#f5aa16"].map((colour) => (
              <span key={colour} className="aspect-square border border-white/20" style={{ backgroundColor: colour }} />
            ))}
          </div>
        </div>
      </section>
    </main>
  );
}

function App() {
  const { path, navigate } = useRoute();
  const saved = useMemo(() => {
    try {
      const raw = localStorage.getItem(storageKey);
      return raw ? JSON.parse(raw) as StoredBrief : null;
    } catch {
      return null;
    }
  }, []);
  const [input, setInputState] = useState<BuyerInput>(saved?.input || sampleInput);
  const [brief, setBriefState] = useState<GeneratedBrief>(saved?.brief || generateBuyerBrief(saved?.input || sampleInput));
  const [meta, setMetaState] = useState<SavedBriefMeta | undefined>(saved?.meta);
  const [routeStatus, setRouteStatus] = useState("");

  const setInput = (next: BuyerInput) => {
    setInputState(next);
    localStorage.setItem(storageKey, JSON.stringify({ input: next, brief, meta }));
  };
  const setBrief = (next: GeneratedBrief) => {
    setBriefState(next);
    localStorage.setItem(storageKey, JSON.stringify({ input, brief: next, meta }));
  };
  const setMeta = (next?: SavedBriefMeta) => {
    setMetaState(next);
    localStorage.setItem(storageKey, JSON.stringify({ input, brief, meta: next }));
  };

  useEffect(() => {
    const match = path.match(/^\/(agent|brief)\/([^/]+)$/);
    if (!match) {
      setRouteStatus("");
      return;
    }
    const slug = match[2];
    let cancelled = false;
    setRouteStatus("Loading saved brief...");
    loadBriefFromSite(slug)
      .then((loaded) => {
        if (cancelled) return;
        const loadedMeta = {
          clientSlug: loaded.clientSlug || slug,
          sharePath: loaded.sharePath || `/brief/${slug}`,
          clientUrl: buildClientUrl(loaded.sharePath || `/brief/${slug}`),
          agentPath: `/agent/${loaded.clientSlug || slug}`,
          agentUrl: buildClientUrl(`/agent/${loaded.clientSlug || slug}`)
        };
        const linkedBrief = withClientLink(loaded.brief, loaded.input, loadedMeta);
        setInputState(loaded.input);
        setBriefState(linkedBrief);
        setMetaState(loadedMeta);
        localStorage.setItem(storageKey, JSON.stringify({ input: loaded.input, brief: linkedBrief, meta: loadedMeta }));
        setRouteStatus("");
      })
      .catch(() => {
        if (!cancelled) setRouteStatus("This saved brief will load from Google Sheets after Netlify is connected.");
      });
    return () => {
      cancelled = true;
    };
  }, [path]);

  const statusBanner = routeStatus ? <div className="bg-ecru px-5 py-3 text-center text-xs font-bold uppercase tracking-[0.12em] text-night">{routeStatus}</div> : null;
  if (path === "/brief" || path.startsWith("/brief/")) return <>{statusBanner}<ClientBrief input={input} brief={brief} navigate={navigate} /></>;
  if (path === "/agent" || path.startsWith("/agent/")) return <>{statusBanner}<AgentForm input={input} setInput={setInput} brief={brief} setBrief={setBrief} meta={meta} setMeta={setMeta} navigate={navigate} /></>;
  return <Home navigate={navigate} />;
}

createRoot(document.getElementById("root")!).render(<App />);
