import { useEffect, useMemo, useState } from 'react';
import { createRoot } from 'react-dom/client';
import { BrowserRouter, Link, NavLink, Route, Routes, useNavigate, useParams } from 'react-router-dom';
import { supabase } from './lib/supabase';
import './styles.css';

const SITE = 'https://crimemapcheck.calyvent.com';
const contact = 'mailto:contact@calyvent.com?subject=CrimeMapCheck%20Inquiry';

type CrimeResult = { address:string; agency:{name:string; ori:string; state:string; city:string; fbiUrl:string}; population:number; rates:{violent:number; property:number}; comparison:{violentState:number; propertyState:number; violentNational:number; propertyNational:number}; trend:{year:number; violent:number; property:number}[]; offenses:{name:string; count:number; rate:number}[]; fetchedAt:string };

export function Meta({title, description, faq}:{title:string;description:string;faq?:[string,string][]}) { useEffect(()=>{document.title=title; const set=(key:string, value:string, property=false)=>{let el=document.querySelector(`meta[${property?'property':'name'}="${key}"]`) as HTMLMetaElement|null; if(!el){el=document.createElement('meta');el.setAttribute(property?'property':'name',key);document.head.appendChild(el)}el.content=value}; set('description',description); set('og:title',title,true); set('og:description',description,true); set('og:url',SITE+location.pathname,true); set('og:type','website',true); set('twitter:card','summary_large_image'); set('twitter:title',title); set('twitter:description',description); set('robots','index,follow'); let canonical=document.querySelector('link[rel=canonical]') as HTMLLinkElement|null; if(!canonical){canonical=document.createElement('link');canonical.rel='canonical';document.head.appendChild(canonical)} canonical.href=SITE+location.pathname; const schema=[{'@context':'https://schema.org','@type':'Organization',name:'CrimeMapCheck',url:SITE,email:'contact@calyvent.com'},...(faq?[{'@context':'https://schema.org','@type':'FAQPage',mainEntity:faq.map(([q,a])=>({'@type':'Question',name:q,acceptedAnswer:{'@type':'Answer',text:a}}))}]:[])]; let script=document.getElementById('jsonld') as HTMLScriptElement|null; if(!script){script=document.createElement('script');script.id='jsonld';script.type='application/ld+json';document.head.appendChild(script)}script.textContent=JSON.stringify(schema)},[title,description,faq]); return null }

function Header(){return <header className="header"><Link to="/" className="brand"><span className="brand-mark">C</span><span>CrimeMap<span className="orange">Check</span></span></Link><nav><NavLink to="/">Search</NavLink><NavLink to="/pricing">Pricing</NavLink><NavLink to="/about">About</NavLink><NavLink to="/dashboard">My areas</NavLink></nav><a className="contact" href={contact}>Contact <span>↗</span></a></header>}
function Footer(){return <footer><div className="footer-brand"><Link to="/" className="brand"><span className="brand-mark">C</span><span>CrimeMap<span className="orange">Check</span></span></Link><p>Official crime context<br/>for real-world decisions.</p></div><div className="footer-links"><Link to="/">Home</Link><Link to="/pricing">Pricing</Link><Link to="/about">About</Link><a href={contact}>Contact</a></div><p className="disclaimer">Crime data reflects agency-reported statistics for the jurisdiction covering this address, not incident-level data for the exact property. Reporting completeness varies by agency. This is not a guarantee of safety.</p></footer>}
export function Shell({children}:{children:React.ReactNode}){return <><Header/><main>{children}</main><Footer/></>}
function Layout({children}:{children:React.ReactNode}){return <Shell>{children}</Shell>}

function SearchBox({onResult}:{onResult:(r:CrimeResult)=>void}){const [address,setAddress]=useState('');const [loading,setLoading]=useState(false);const [error,setError]=useState('');const submit=async(e:React.FormEvent)=>{e.preventDefault();if(!address.trim())return;setLoading(true);setError('');try{const response=await fetch(`/api/crime?address=${encodeURIComponent(address)}`);const body=await response.json();if(!response.ok)throw new Error(body.error||'We could not resolve that address.');onResult(body)}catch(err){setError(err instanceof Error?err.message:'Search failed.')}finally{setLoading(false)}};return <form className="search-box" onSubmit={submit}><label htmlFor="address">Street address, city, state, or ZIP</label><div className="search-line"><input id="address" value={address} onChange={e=>setAddress(e.target.value)} placeholder="1600 Pennsylvania Ave NW, Washington, DC"/><button type="submit" disabled={loading}>{loading?'Reading data…':'Check Crime Data'} <span>↗</span></button></div>{error&&<p className="error">{error}</p>}<p className="search-note">No login required. Your search is not saved unless you choose to watch the area.</p></form>}

function Rate({value}:{value:number}){return <span className="rate">{value.toFixed(1)}<small>/ 1k</small></span>}
function Results({result}:{result:CrimeResult}){const max=Math.max(...result.trend.map(x=>Math.max(x.violent,x.property)),1);return <section className="results" aria-live="polite"><div className="results-head"><div><p className="eyebrow">COVERING JURISDICTION</p><h2>{result.agency.name}</h2><p className="muted">{result.address}</p></div><a href={result.agency.fbiUrl} target="_blank" rel="noreferrer">View official FBI record ↗</a></div><div className="snapshot"><div><p className="eyebrow">VIOLENT CRIME</p><Rate value={result.rates.violent}/><p>{comparison(result.rates.violent,result.comparison.violentNational)} the national average</p><small>{comparison(result.rates.violent,result.comparison.violentState)} the state average</small></div><div><p className="eyebrow">PROPERTY CRIME</p><Rate value={result.rates.property}/><p>{comparison(result.rates.property,result.comparison.propertyNational)} the national average</p><small>{comparison(result.rates.property,result.comparison.propertyState)} the state average</small></div></div><div className="result-grid"><div className="trend"><div className="section-top"><h3>Five-year trend</h3><span>Rate per 1,000 residents</span></div><div className="chart">{result.trend.map((item)=><div className="bar-group" key={item.year}><div className="bars"><i style={{height:`${Math.max(8,item.violent/max*100)}%`}} title={`Violent ${item.violent}`}/><b style={{height:`${Math.max(8,item.property/max*100)}%`}} title={`Property ${item.property}`}/></div><small>{item.year}</small></div>)}</div><div className="legend"><span><i/> Violent</span><span><i/> Property</span></div></div><div className="offenses"><div className="section-top"><h3>Offense breakdown</h3><span>Latest reporting year</span></div>{result.offenses.map(o=><div className="offense" key={o.name}><span>{o.name}</span><strong>{o.count.toLocaleString()}</strong><small>{o.rate.toFixed(1)} / 1k</small></div>)}</div></div><div className="attribution"><strong>This data covers {result.agency.name},</strong> the law enforcement agency serving this address. FBI data is agency-reported and updated annually. <a href={result.agency.fbiUrl} target="_blank" rel="noreferrer">See the source record ↗</a></div><div className="watch-cta"><div><p className="eyebrow">STAY CURRENT</p><h3>Get monthly updates on this area.</h3></div><Link to="/dashboard" className="button">Create a free account ↗</Link></div></section>}
function comparison(value:number, average:number){if(!average)return 'comparison unavailable';const pct=Math.round(Math.abs((value-average)/average)*100);return `${pct}% ${value<=average?'below':'above'}`}

function Home(){const [result,setResult]=useState<CrimeResult|null>(null);return <Layout><Meta title="CrimeMapCheck — Real crime data for any address" description="See official FBI crime statistics for the law enforcement agency covering any U.S. address, with five-year trends and national comparisons."/><section className="home-hero"><div className="hero-copy"><p className="eyebrow">THE ADDRESS-LEVEL STARTING POINT</p><h1>See the real crime data <em>for any address.</em></h1><p className="hero-lede">Official FBI crime statistics, not guesses or crowdsourced opinions. Search an address and see the agency-level picture behind it.</p><SearchBox onResult={setResult}/></div><div className="hero-aside"><div className="aside-number">01</div><p>One address<br/><span>one accountable agency.</span></p><div className="aside-rule"/><p className="micro">LIVE SOURCE<br/><strong>FBI UCR / CDE</strong></p></div></section>{result?<Results result={result}/>:<TrustAndExplain/>}</Layout>}
function TrustAndExplain(){return <><section className="trust"><div className="trust-stamp">✓</div><div><p className="eyebrow">SOURCE YOU CAN CHECK</p><h2>Live data pulled directly from the FBI’s official Uniform Crime Reporting Program.</h2><p>We geocode your address, identify the agency responsible for the jurisdiction, and show the latest comparable rates available. The agency is the unit of truth—not a neighborhood rumor.</p></div></section><section className="explain"><div className="explain-title"><p className="eyebrow">READ THE NUMBER</p><h2>How to read crime statistics</h2></div><div className="explain-copy"><p>Crime statistics are most useful when they give you a fair denominator and a clear jurisdiction. CrimeMapCheck reports rates per 1,000 residents, which makes a large city and a small town easier to compare than raw incident counts alone. A rate is not a prediction of what will happen to one person or one address; it is a description of what an agency reported across its entire service area.</p><p>Start with the agency name. A postal address can sit inside a city but be served by a county sheriff, a municipal police department, or another jurisdiction. That is why every result names the covering agency and links back to its official FBI record.</p><h3>What counts as violent vs. property crime?</h3><p>Violent crime generally includes homicide, rape, robbery, and aggravated assault—offenses involving force or the threat of force against a person. Property crime covers burglary, larceny-theft, and motor vehicle theft. The categories are broad: a rise in one offense can be hidden by a flat overall number, so the breakdown matters.</p><p>Compare the five-year trend, then compare the current rate to state and national averages. Look for direction, consistency, and reporting completeness. An apparent improvement may reflect changing reporting practices, while a spike may be concentrated in one offense. Use this data as one grounded input alongside a visit, local context, and questions for the agency.</p></div></section><section className="pricing-teaser"><p className="eyebrow">WHEN YOU’RE COMPARING HOMES</p><h2>Keep an eye on the places<br/><em>you’re considering.</em></h2><div><p>Free accounts can watch up to three areas and get notified when new annual FBI data changes the picture. Paid plans unlock unlimited watched areas, side-by-side comparisons, and downloadable reports.</p><Link to="/pricing" className="text-link">See plans ↗</Link></div></section></>}

function About(){return <Layout><Meta title="About CrimeMapCheck — Official FBI crime context" description="CrimeMapCheck connects any U.S. address to the responsible law enforcement agency and shows official FBI UCR crime statistics."/><article className="simple-page"><p className="eyebrow">ABOUT THE PROJECT</p><h1>Context before<br/><em>conclusion.</em></h1><div className="simple-copy"><p>CrimeMapCheck is a fast way to see the crime statistics for the law enforcement jurisdiction covering an address. It uses the official FBI UCR / Crime Data Explorer API, then presents rates, trends, and comparisons in plain language.</p><p>Crime data reflects agency-reported statistics for the jurisdiction covering this address, not incident-level data for the exact property. Reporting completeness varies by agency. This is not a guarantee of safety.</p><a href={contact} className="button">Ask a question ↗</a></div></article></Layout>}
function Pricing(){return <Layout><Meta title="CrimeMapCheck pricing — Watch areas for free" description="Search unlimited addresses for free. Watch three areas free, or compare four areas and download reports for $6.99 per month."/><section className="simple-page pricing-page"><p className="eyebrow">PRICING</p><h1>Useful context should<br/><em>stay accessible.</em></h1><div className="plans"><div className="plan"><p className="eyebrow">FREE</p><h2>$0</h2><p>For a few places you want to keep in view.</p><ul><li>Unlimited crime searches</li><li>3 watched areas</li><li>Annual data update alerts</li></ul><Link to="/dashboard" className="button button-dark">Create free account ↗</Link></div><div className="plan featured"><p className="eyebrow">DECISION SUPPORT</p><h2>$6.99 <small>/ month</small></h2><p>Or $59 per year. For relocations, home buying, and side-by-side research.</p><ul><li>Unlimited watched areas</li><li>Compare up to 4 areas</li><li>Downloadable PDF reports</li></ul><a href={contact} className="button">Start with a question ↗</a><small className="billing-note">Stripe Checkout link ready for your live price ID.</small></div></div></section></Layout>}
function Dashboard(){const [email,setEmail]=useState('');const [password,setPassword]=useState('');const [mode,setMode]=useState<'sign-in'|'sign-up'>('sign-in');const [message,setMessage]=useState('');const [session,setSession]=useState(false);useEffect(()=>{supabase?.auth.getSession().then(({data})=>setSession(!!data.session))},[]);const auth=async(e:React.FormEvent)=>{e.preventDefault();if(!supabase){setMessage('Add Supabase public credentials to enable accounts.');return}const response=mode==='sign-in'?await supabase.auth.signInWithPassword({email,password}):await supabase.auth.signUp({email,password,options:{emailRedirectTo:undefined}});if(response.error)setMessage(response.error.message);else{setSession(true);setMessage(mode==='sign-up'?'Account created. Your watched areas will appear here.':'Signed in.')}};return <Layout><Meta title="My watched areas — CrimeMapCheck" description="Save CrimeMapCheck areas and receive an alert when annual FBI crime data updates."/><section className="dashboard"><p className="eyebrow">PRIVATE WORKSPACE</p><h1>My watched<br/><em>areas.</em></h1>{session?<div className="empty-dashboard"><h2>No watched areas yet.</h2><p>Run an address search, then save the covering agency here. You’ll get an email alert when new annual FBI data changes its numbers.</p><Link to="/" className="button">Search an address ↗</Link></div>:<form className="auth-form" onSubmit={auth}><h2>{mode==='sign-in'?'Sign in to watch areas':'Create your free account'}</h2><input type="email" required placeholder="Email address" value={email} onChange={e=>setEmail(e.target.value)}/><input type="password" required minLength={6} placeholder="Password" value={password} onChange={e=>setPassword(e.target.value)}/><button className="button" type="submit">{mode==='sign-in'?'Sign in':'Create account'} ↗</button><button type="button" className="text-button" onClick={()=>setMode(mode==='sign-in'?'sign-up':'sign-in')}>{mode==='sign-in'?'Need an account? Create one.':'Already have an account? Sign in.'}</button>{message&&<p className="muted">{message}</p>}</form>}</section></Layout>}

const states=['alabama','alaska','arizona','arkansas','california','colorado','connecticut','florida','georgia','illinois','maryland','massachusetts','michigan','minnesota','missouri','nevada','new-jersey','new-york','north-carolina','ohio','oregon','pennsylvania','tennessee','texas','utah','virginia','washington','wisconsin'];
function SeoPage(){const {state,city}=useParams();const label=(city||state||'United States').split('-').map(x=>x[0].toUpperCase()+x.slice(1)).join(' ');const [data,setData]=useState<any>(null);useEffect(()=>{fetch(`/api/city?state=${encodeURIComponent(state||'')}&city=${encodeURIComponent(city||'')}`).then(r=>r.ok?r.json():null).then(setData)},[state,city]);const isCity=!!city;const faq:[[string,string],[string,string],[string,string]]=[[`Is ${label} safe?`,`Crime statistics can help establish context for ${label}, but they are agency-level reporting and not a guarantee of safety for any address.`],[`What is the crime rate in ${label} compared with the national average?`,data?`${label} reports a violent crime rate of ${data.violentRate} and a property crime rate of ${data.propertyRate} per 1,000 residents.`:`The latest comparable FBI data is loaded from the official Crime Data Explorer.`],[`Where does ${label} crime data come from?`,`CrimeMapCheck uses agency-reported statistics from the FBI Uniform Crime Reporting Program.`]];return <Layout><Meta title={`Crime rate in ${label} — CrimeMapCheck`} description={`See official FBI crime statistics, rates, trends, and agency context for ${label}. Compare ${label} with state and national averages.`} faq={faq}/><article className="seo-page"><p className="eyebrow">{isCity?'CITY CRIME DATA':'STATE CRIME DATA'}</p><h1>Crime rate in<br/><em>{label}.</em></h1><p className="answer-first">{data?`The latest FBI-reported data for ${label} shows a violent crime rate of ${data.violentRate} and a property crime rate of ${data.propertyRate} per 1,000 residents.`:`CrimeMapCheck loads the latest FBI-reported crime rates for ${label} directly from the official Crime Data Explorer.`}</p><SearchBox onResult={()=>location.assign('/')}/><div className="seo-body"><p>{label} crime statistics are best understood through the agencies that report them. CrimeMapCheck connects the place name to the latest available FBI data and keeps the distinction clear: this is jurisdiction-level information, not a list of incidents at individual properties.</p><p>When you compare {label}, look at the violent and property crime rates separately. Violent crime includes homicide, robbery, and aggravated assault. Property crime includes burglary, larceny, and motor vehicle theft. Five-year trends add important context because a single annual number can move for many reasons, including reporting completeness and population changes.</p><h2>{isCity?`Is ${label} safe?`:`${label} crime rate by city`}</h2><p>There is no single statistic that can answer whether a place is safe for everyone. The more useful question is what the data says, which agency reported it, and whether the trend is moving consistently. Use this page as a starting point, then search the exact address you are considering.</p></div><div className="faq"><h2>Questions people ask</h2>{faq.map(([q,a])=><details key={q}><summary>{q}</summary><p>{a}</p></details>)}</div></article></Layout>}
function App(){return <Routes><Route path="/" element={<Home/>}/><Route path="/about" element={<About/>}/><Route path="/pricing" element={<Pricing/>}/><Route path="/dashboard" element={<Dashboard/>}/><Route path="/crime-rate/:state" element={<SeoPage/>}/><Route path="/crime-rate/:state/:city" element={<SeoPage/>}/><Route path="*" element={<Home/>}/></Routes>}
export default function Root(){return <BrowserRouter><App/></BrowserRouter>}

createRoot(document.getElementById('root')!).render(<Root/>);
